using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using static System.Net.Mime.MediaTypeNames; namespace lts { using RenderRef = UIntPtr; using Handle = UIntPtr; using ContextHandle = UIntPtr; using RendererHandle = UIntPtr; using TextBlockHandle = UIntPtr; using FontCreatorHandle = UIntPtr; using FontHandle = UIntPtr; using PostProcessorHandle = UIntPtr; using ImageHandle = UIntPtr; using CharHandle = UIntPtr; using WideChar = UInt16; using System.Collections; using System.IO; public enum ErrorCode : Int32 { Unknown = -1, None = 0, // misc NotInitialized = 1, InvalidEnum = 2, InvalidValue = 3, InvalidOperation = 4, InvalidType = 5, // invalid handles InvalidContextHandle = 100, InvalidRendererHandle = 101, InvalidTextBlockHandle = 102, InvalidFontHandle = 103, InvalidFontCreatorHandle = 104, InvalidImageHandle = 105, InvalidPostProcHandle = 106, // library InvalidLibName = 200, InvalidLibHandle = 201, InvalidMethodName = 202 }; public enum CodePage : UInt32 { cpUTF8, cpISO_8859_1, cpISO_8859_2, cpISO_8859_3, cpISO_8859_4, cpISO_8859_5, cpISO_8859_6, cpISO_8859_7, cpISO_8859_8, cpISO_8859_9, cpISO_8859_10, cpISO_8859_11, cpISO_8859_13, cpISO_8859_14, cpISO_8859_15, cpISO_8859_16, cpISO_037, cpISO_437, cpISO_500, cpISO_737, cpISO_775, cpISO_850, cpISO_852, cpISO_855, cpISO_857, cpISO_860, cpISO_861, cpISO_862, cpISO_863, cpISO_864, cpISO_865, cpISO_866, cpISO_869, cpISO_874, cpISO_875, cpISO_1026, cpISO_1250, cpISO_1251, cpISO_1252, cpISO_1253, cpISO_1254, cpISO_1255, cpISO_1256, cpISO_1257, cpISO_1258 }; public enum Format : UInt32 { Empty, RGBA8, LumAlpha8, Alpha8, Lum8 }; public enum RendererType : UInt32 { Unknown, OpenGL, OpenGLES }; public enum FontCreatorType : UInt32 { Unknown, FreeType, GDI, Custom }; public enum VertAlign : UInt32 { Top, Center, Bottom }; public enum HorzAlign : UInt32 { Left, Center, Right, Justify }; public enum Clipping : UInt32 { None, WordBorder, CharBorder, WordComplete, CharComplete }; public enum AntiAliasing : UInt32 { None, Normal }; public enum CharRangeUsage : UInt32 { Include, Exclude }; public enum ImageMode : UInt32 { Ignore, Replace, Modulate }; public enum StreamOrigin : UInt32 { Begin = 0, Current = 1, End = 2 }; [Flags] public enum BlockFlags : UInt32 { Empty = 0, WordWrap = (1 << 0) }; [Flags] public enum FontStyles : UInt32 { Empty = 0, Bold = (1 << 0), Italic = (1 << 1), Underline = (1 << 2), Strikeout = (1 << 3) }; [Flags] public enum ColorChannels : UInt32 { Empty = 0, Red = (1 << 0), Green = (1 << 1), Blue = (1 << 2), Alpha = (1 << 3) }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Position { public Int32 x; public Int32 y; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct GlyphMetric { Position GlyphOrigin; Rect GlyphRect; Int32 Advance; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TextMetric { public UInt32 Ascent; public UInt32 Descent; public UInt32 ExternalLeading; public UInt32 BaseLineOffset; public UInt32 CharSpacing; public UInt32 LineHeight; public UInt32 LineSpacing; }; [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct FontMetric { public UInt32 Size; public FontStyles Styles; public AntiAliasing AntiAliasing; public WideChar defaultChar; //private fixed byte __reserved[2]; public Int32 Ascent; public Int32 Descent; public Int32 ExternalLeading; public Int32 BaseLineOffset; public Int32 UnderlinePos; public Int32 UnderlineSize; public Int32 StrikeoutPos; public Int32 StrikeoutSize; } [StructLayout(LayoutKind.Explicit, Pack = 1)] public struct Rect { [FieldOffset(0)] public Position TopLeft; [FieldOffset(8)] public Position BottomRight; [FieldOffset(0)] public Int32 Left; [FieldOffset(4)] public Int32 Top; [FieldOffset(8)] public Int32 Right; [FieldOffset(12)] public Int32 Bottom; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public unsafe struct Color { public float R; public float G; public float B; public float A; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct ImageModes { public ImageMode R; public ImageMode G; public ImageMode B; public ImageMode A; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Vector4f { public float X; public float Y; public float Z; public float W; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Matrix4f { public Vector4f AxisX; public Vector4f AxisY; public Vector4f AxisZ; public Vector4f Pos; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct RendererCustomData { public IntPtr args; public IntPtr BeginRenderCallback; public IntPtr EndRenderCallback; public IntPtr GetDrawPosCallback; public IntPtr SetDrawPosCallback; public IntPtr MoveDrawPosCallback; public IntPtr SetColorCallback; public IntPtr RenderCallback; public IntPtr CreateRefCallback; public IntPtr FreeRefCallback; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct StreamData { public IntPtr args; public IntPtr ReadCallback; public IntPtr SeekCallback; }; [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct PostProcessorData { public IntPtr args; public IntPtr ExecuteCallback; }; public class Constants { public static readonly ImageModes ImageModeReplaceAll = new ImageModes() { R = ImageMode.Replace, G = ImageMode.Replace, B = ImageMode.Replace, A = ImageMode.Replace }; public static readonly ImageModes ImageModeModulateAlpha = new ImageModes() { R = ImageMode.Replace, G = ImageMode.Replace, B = ImageMode.Replace, A = ImageMode.Modulate }; public static readonly ImageModes ImageModeModulateAll = new ImageModes() { R = ImageMode.Modulate, G = ImageMode.Modulate, B = ImageMode.Modulate, A = ImageMode.Modulate }; public const ColorChannels ColorChannelsRGB = ColorChannels.Red | ColorChannels.Green | ColorChannels.Blue; public const ColorChannels ColorChannelsRGBA = ColorChannels.Red | ColorChannels.Green | ColorChannels.Blue | ColorChannels.Alpha; }; public static unsafe class Imports { #region General [DllImport("libtextsuite.dll", EntryPoint = "ltsInitialize", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode Initialize(); [DllImport("libtextsuite.dll", EntryPoint = "ltsGetVersion", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr GetVersion(); [DllImport("libtextsuite.dll", EntryPoint = "ltsGetLastErrorCode", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode GetLastErrorCode(); [DllImport("libtextsuite.dll", EntryPoint = "ltsGetLastErrorMsg", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr GetLastErrorMsg(); [DllImport("libtextsuite.dll", EntryPoint = "ltsFinalize", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode Finalize(); #endregion #region Context [DllImport("libtextsuite.dll", EntryPoint = "ltsContextCreate", CallingConvention = CallingConvention.StdCall)] public static extern ContextHandle ContextCreate(); [DllImport("libtextsuite.dll", EntryPoint = "ltsContextGetCodePage", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ContextGetCodePage(ContextHandle handle, out CodePage value); [DllImport("libtextsuite.dll", EntryPoint = "ltsContextGetDefaultChar", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ContextGetDefaultChar(ContextHandle handle, out WideChar value); [DllImport("libtextsuite.dll", EntryPoint = "ltsContextSetCodePage", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ContextSetCodePage(ContextHandle handle, CodePage value); [DllImport("libtextsuite.dll", EntryPoint = "ltsContextSetDefaultChar", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ContextSetDefaultChar(ContextHandle handle, WideChar value); [DllImport("libtextsuite.dll", EntryPoint = "ltsContextAnsiToWide", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr ContextAnsiToWide(ContextHandle handle, [MarshalAs(UnmanagedType.LPStr)] String text); [DllImport("libtextsuite.dll", EntryPoint = "ltsContextDestroy", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ContextDestroy(ContextHandle handle); #endregion #region Renderer [DllImport("libtextsuite.dll", EntryPoint = "ltsRendererCreate", CallingConvention = CallingConvention.StdCall)] public static extern RendererHandle RendererCreate(ContextHandle handle, Int32 type, Int32 format); [DllImport("libtextsuite.dll", EntryPoint = "ltsRendererCreateCustom", CallingConvention = CallingConvention.StdCall)] public static extern RendererHandle RendererCreateCustom(ContextHandle handle, Format format, ref RendererCustomData data); [DllImport("libtextsuite.dll", EntryPoint = "ltsRendererBeginBlock", CallingConvention = CallingConvention.StdCall)] public static extern TextBlockHandle RendererBeginBlock(RendererHandle handle, Int32 top, Int32 left, Int32 width, Int32 height, BlockFlags flags); [DllImport("libtextsuite.dll", EntryPoint = "ltsRendererEndBlock", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode RendererEndBlock(RendererHandle handle, TextBlockHandle block); [DllImport("libtextsuite.dll", EntryPoint = "ltsRendererAbortBlock", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode RendererAbortBlock(RendererHandle handle, TextBlockHandle block); [DllImport("libtextsuite.dll", EntryPoint = "ltsRendererGetTextWidthA", CallingConvention = CallingConvention.StdCall)] public static extern Int32 RendererGetTextWidthA(RendererHandle handle, FontHandle font, [MarshalAs(UnmanagedType.LPStr)] String text); [DllImport("libtextsuite.dll", EntryPoint = "ltsRendererGetTextWidthW", CallingConvention = CallingConvention.StdCall)] public static extern Int32 RendererGetTextWidthW(RendererHandle handle, FontHandle font, [MarshalAs(UnmanagedType.LPWStr)] String text); [DllImport("libtextsuite.dll", EntryPoint = "ltsRendererDestroy", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode RendererDestroy(RendererHandle handle); #endregion #region FontCreator [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate Int32 FontCreatorStreamReadHandler(IntPtr args, IntPtr buffer, Int32 count); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate Int32 FontCreatorStreamSeekHandler(IntPtr args, StreamOrigin origin, Int32 offset); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontCreatorCreate", CallingConvention = CallingConvention.StdCall)] public static extern FontCreatorHandle FontCreatorCreate(ContextHandle cHandle, FontCreatorType type); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontCreatorGetFontByName", CallingConvention = CallingConvention.StdCall)] public static extern FontHandle FontCreatorGetFontByName(FontCreatorHandle handle, [MarshalAs(UnmanagedType.LPStr)] String fontname, Int32 size, FontStyles style, AntiAliasing antiAliasing); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontCreatorGetFontByFile", CallingConvention = CallingConvention.StdCall)] public static extern FontHandle FontCreatorGetFontByFile(FontCreatorHandle handle, [MarshalAs(UnmanagedType.LPStr)] String filename, Int32 size, FontStyles style, AntiAliasing antiAliasing); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontCreatorGetFontByStream", CallingConvention = CallingConvention.StdCall)] public static extern FontHandle FontCreatorGetFontByStream(FontCreatorHandle handle, ref StreamData stream, Int32 size, FontStyles style, AntiAliasing antiAliasing); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontCreatorDestroy", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontCreatorDestory(FontCreatorHandle handle); #endregion #region Font [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetPostProcessor", CallingConvention = CallingConvention.StdCall)] public static extern PostProcessorHandle FontGetPostProcessor(FontHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetTabWidth", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontGetTabWidth(FontHandle handle, out Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetCharSpacing", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontGetCharSpacing(FontHandle handle, out Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetLineSpacing", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontGetLineSpacing(FontHandle handle, out Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetMetric", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontGetMetric(FontHandle handle, out FontMetric value); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetFontName", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr FontGetFontName(FontHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetFaceName", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr FontGetFaceName(FontHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetStyleName", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr FontGetStyleName(FontHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetFullName", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr FontGetFullName(FontHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontGetCopyrightName", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr FontGetCopyrightName(FontHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontSetPostProcessor", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontSetPostProcessor(FontHandle handle, PostProcessorHandle pp); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontSetTabWidth", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontSetTabWidth(FontHandle handle, Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontSetCharSpacing", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontSetCharSpacing(FontHandle handle, Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontSetLineSpacing", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontSetLineSpacing(FontHandle handle, Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsFontDestroy", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode FontDestroy(FontHandle handle); #endregion #region TextBlock [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetRect", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetRect(TextBlockHandle handle, out Rect value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetWidth", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetWidth(TextBlockHandle handle, out Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetHeight", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetHeight(TextBlockHandle handle, out Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetFlags", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetFlags(TextBlockHandle handle, out BlockFlags value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetTop", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetTop(TextBlockHandle handle, out Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetLeft", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetLeft(TextBlockHandle handle, out Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetVertAlign", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetVertAlign(TextBlockHandle handle, out VertAlign value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetHorzAlign", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetHorzAlign(TextBlockHandle handle, out HorzAlign value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetClipping", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetClipping(TextBlockHandle handle, out Clipping value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetColor", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetColor(TextBlockHandle handle, out Color value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetFont", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockGetFont(TextBlockHandle handle, out FontHandle value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockSetTop", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockSetTop(TextBlockHandle handle, Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockSetLeft", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockSetLeft(TextBlockHandle handle, Int32 value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockSetVertAlign", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockSetVertAlign(TextBlockHandle handle, VertAlign value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockSetHorzAlign", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockSetHorzAlign(TextBlockHandle handle, HorzAlign value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockSetClipping", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockSetClipping(TextBlockHandle handle, Clipping value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockSetColor", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockSetColor(TextBlockHandle handle, Color value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockSetFont", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockSetFont(TextBlockHandle handle, FontHandle value); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetActualHeight", CallingConvention = CallingConvention.StdCall)] public static extern Int32 TextBlockGetActualHeight(TextBlockHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetTextWidthA", CallingConvention = CallingConvention.StdCall)] public static extern Int32 TextBlockGetTextWidthA(TextBlockHandle handle, [MarshalAs(UnmanagedType.LPStr)] String text); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockGetTextWidthW", CallingConvention = CallingConvention.StdCall)] public static extern Int32 TextBlockGetTextWidthW(TextBlockHandle handle, [MarshalAs(UnmanagedType.LPWStr)] String text); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockTextOutA", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockTextOutA(TextBlockHandle handle, [MarshalAs(UnmanagedType.LPStr)] String text); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockTextOutW", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockTextOutW(TextBlockHandle handle, [MarshalAs(UnmanagedType.LPWStr)] String text); [DllImport("libtextsuite.dll", EntryPoint = "ltsTextBlockDestroy", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode TextBlockDestroy(TextBlockHandle handle); #endregion #region Image [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void LoadHandler(ImageHandle handle, Int32 x, Int32 y, ref Color pixel, IntPtr args); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void BlendHandler(ImageHandle handle, Color src, Color dst, out Color merged, IntPtr args); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageCreate", CallingConvention = CallingConvention.StdCall)] public static extern ImageHandle ImageCreate(ContextHandle cHandle); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetIsEmpty", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageGetIsEmpty(ImageHandle handle, out bool value); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetWidth", CallingConvention = CallingConvention.StdCall)] public static extern Int32 ImageGetWidth(ImageHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetHeight", CallingConvention = CallingConvention.StdCall)] public static extern Int32 ImageGetHeight(ImageHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetLineSize", CallingConvention = CallingConvention.StdCall)] public static extern Int32 ImageGetLineSize(ImageHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetDataSize", CallingConvention = CallingConvention.StdCall)] public static extern Int32 ImageGetDataSize(ImageHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetFormat", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageGetFormat(ImageHandle handle, out Format format); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetData", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr ImageGetData(ImageHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetScanLine", CallingConvention = CallingConvention.StdCall)] public static extern IntPtr ImageGetScanLine(ImageHandle handle, Int32 index); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageGetPixelAt", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageGetPixelAt(ImageHandle handle, Int32 x, Int32 y, out Color pixel); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageAssign", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageAssign(ImageHandle handle, ImageHandle source); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageCreateEmpty", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageCreateEmpty(ImageHandle handle, Format format, Int32 width, Int32 height); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageLoadFromFunc", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageLoadFromFunc(ImageHandle handle, LoadHandler callback, IntPtr args); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageResize", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageResize(ImageHandle handle, Int32 width, Int32 height, Int32 x, Int32 y); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageFillColor", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageFillColor(ImageHandle handle, Color color, ColorChannels mask, ref ImageModes modes); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageFillPattern", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageFillPattern(ImageHandle handle, ImageHandle patter, Int32 x, Int32 y, ColorChannels mask, ref ImageModes modes); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageBlend", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageBlend(ImageHandle handle, ImageHandle source, Int32 x, Int32 y, BlendHandler callback, IntPtr args); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageBlur", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageBlur(ImageHandle handle, float horzRad, float hortStr, float vertRad, float vertStr, ColorChannels mask); [DllImport("libtextsuite.dll", EntryPoint = "ltsImageDestroy", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode ImageDestroy(ImageHandle handle); #endregion #region PostProcessor [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void PostProcessorHandler(CharHandle charHandle, ImageHandle imageHandle, IntPtr args); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorAddRange", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode PostProcessorAddRange(PostProcessorHandle handle, CharRangeUsage usage, WideChar start, WideChar stop); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorAddChars", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode PostProcessorAddChars(PostProcessorHandle handle, CharRangeUsage usage, [MarshalAs(UnmanagedType.LPWStr)] String text); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorClearRanges", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode PostProcessorClearRanges(PostProcessorHandle handle); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorExecute", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode PostProcessorExecute(PostProcessorHandle handle, CharHandle charHandle, ImageHandle imageHandle); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorFillColorCreate", CallingConvention = CallingConvention.StdCall)] public static extern PostProcessorHandle PostProcessorFillColorCreate(PostProcessorHandle handle, Color color, ref ImageModes modes, ColorChannels channels); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorFillPatternCreate", CallingConvention = CallingConvention.StdCall)] public static extern PostProcessorHandle PostProcessorFillPatternCreate(ContextHandle handle, ImageHandle pattern, bool ownsPattern, Position position, ref ImageModes modes, ColorChannels channels); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorBorderCreate", CallingConvention = CallingConvention.StdCall)] public static extern PostProcessorHandle PostProcessorBorderCreate(PostProcessorHandle handle, float width, float strength, Color color, bool keepSize); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorShadowCreate", CallingConvention = CallingConvention.StdCall)] public static extern PostProcessorHandle PostProcessorShadowCreate(PostProcessorHandle handle, float raduis, float strength, Position position, Color color); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorCustomCreate", CallingConvention = CallingConvention.StdCall)] public static extern PostProcessorHandle PostProcessorCustomCreate(PostProcessorHandle handle, ref PostProcessorData data); [DllImport("libtextsuite.dll", EntryPoint = "ltsPostProcessorDestroy", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode PostProcessorDestroy(PostProcessorHandle handle); #endregion #region Char [DllImport("libtextsuite.dll", EntryPoint = "ltsCharGetCharCode", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode CharGetCharCode(CharHandle handle, out WideChar value); [DllImport("libtextsuite.dll", EntryPoint = "ltsCharGetGlyphMetric", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode CharGetGlyphMetric(CharHandle handle, out GlyphMetric value); [DllImport("libtextsuite.dll", EntryPoint = "ltsCharSetGlyphMetric", CallingConvention = CallingConvention.StdCall)] public static extern ErrorCode CharSetGlyphMetric(CharHandle handle, ref GlyphMetric value); #endregion }; public class Exception : System.Exception { public ErrorCode ErrorCode { get; private set; } public string ErrorMessage { get; private set; } public static void ThrowError(ErrorCode err, string msg) { throw new Exception() { ErrorCode = err, ErrorMessage = msg, }; } public static void ThrowLastError(ErrorCode err) { var pMsg = Imports.GetLastErrorMsg(); var msg = Marshal.PtrToStringAnsi(pMsg); ThrowError(err, msg); } public static void ThrowLastError() { var err = Imports.GetLastErrorCode(); ThrowLastError(err); } public static void HandleError(ErrorCode err) { if (err != ErrorCode.None) ThrowLastError(err); } }; static class Impl { private static bool _isInitialized = false; private static int _refCount = 0; private static object _lock = new object(); public static void Initialize() { lock (_lock) { ++_refCount; if (!_isInitialized) { var err = Imports.Initialize(); if (err != ErrorCode.None) Exception.ThrowLastError(); } } } public static void Finish() { lock (_lock) { --_refCount; if (_refCount == 0 && _isInitialized) { var err = Imports.Finalize(); if (err != ErrorCode.None) Exception.ThrowLastError(); } } } } public class Context : IDisposable { bool _initialized; public Context() { Impl.Initialize(); _initialized = true; Handle = Imports.ContextCreate(); if (Handle == ContextHandle.Zero) Exception.ThrowLastError(); } ~Context() { Dispose(false); } public ContextHandle Handle { get; private set; } #region IDisposable Support protected virtual void Dispose(bool disposing) { if (Handle != UIntPtr.Zero) { Imports.ContextDestroy(Handle); Handle = UIntPtr.Zero; } if (_initialized) { Impl.Finish(); _initialized = false; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion }; public class Char { public Char(CharHandle handle) { Handle = handle; } public CharHandle Handle { get; private set; } public WideChar DefaultChar { get { WideChar value; Exception.HandleError(Imports.CharGetCharCode(Handle, out value)); return value; } } public GlyphMetric GlyphMetriy { get { GlyphMetric value; Exception.HandleError(Imports.CharGetGlyphMetric(Handle, out value)); return value; } set { Exception.HandleError(Imports.CharSetGlyphMetric(Handle, ref value)); } } } public class Image : IDisposable { [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void LoadCallback(Image image, Int32 x, Int32 y, ref Color pixel); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate Color BlendCallback(Image image, Color src, Color dst); private struct LoadArgs { public LoadCallback callback; public Image image; }; private static Imports.LoadHandler _loadHandler = new Imports.LoadHandler(LoadHandlerImpl); private static void LoadHandlerImpl(ImageHandle handle, Int32 x, Int32 y, ref Color pixel, IntPtr args) { var loadArgs = (LoadArgs)Marshal.PtrToStructure(args, typeof(LoadArgs)); loadArgs.callback(loadArgs.image, x, y, ref pixel); } private struct BlendArgs { public BlendCallback callback; public Image image; }; private static Imports.BlendHandler _blendHandler = new Imports.BlendHandler(BlendHandlerImpl); private static void BlendHandlerImpl(ImageHandle handle, Color src, Color dst, out Color merged, IntPtr args) { var blendArgs = (BlendArgs)Marshal.PtrToStructure(args, typeof(BlendArgs)); merged = blendArgs.callback(blendArgs.image, src, dst); } bool _ownsHandle; byte[] _data; public Image(Context context) { _ownsHandle = true; Handle = Imports.ImageCreate(context.Handle); if (Handle == ImageHandle.Zero) Exception.ThrowLastError(); } public Image(ImageHandle handle) { _ownsHandle = false; Handle = handle; } ~Image() { Dispose(false); } public ImageHandle Handle { get; private set; } public bool IsEmpty { get { bool value; Imports.ImageGetIsEmpty(Handle, out value); return value; } } public Int32 Width { get { Int32 value = Imports.ImageGetWidth(Handle); if (value < 0) Exception.ThrowLastError(); return value; } } public Int32 Height { get { Int32 value = Imports.ImageGetHeight(Handle); if (value < 0) Exception.ThrowLastError(); return value; } } public Int32 LineSize { get { Int32 value = Imports.ImageGetLineSize(Handle); if (value < 0) Exception.ThrowLastError(); return value; } } public Int32 DataSize { get { Int32 value = Imports.ImageGetDataSize(Handle); if (value < 0) Exception.ThrowLastError(); return value; } } public Format Format { get { Format value; Exception.HandleError(Imports.ImageGetFormat(Handle, out value)); return value; } } public byte[] Data { get { if (_data == null) { IntPtr value = Imports.ImageGetData(Handle); if (value == IntPtr.Zero) Exception.ThrowLastError(); var sz = DataSize; _data = new byte[sz]; Marshal.Copy(value, _data, 0, sz); } return _data; } set { if (value == null) throw new ArgumentNullException("Data"); var sz = DataSize; IntPtr ptr = Imports.ImageGetData(Handle); if (ptr == IntPtr.Zero) Exception.ThrowLastError(); Marshal.Copy(value, 0, ptr, Math.Min(sz, value.Length)); _data = null; } } public Color GetPixelAt(Int32 x, Int32 y) { Color value; Exception.HandleError(Imports.ImageGetPixelAt(Handle, x, y, out value)); return value; } public void Assign(Image source) { _data = null; Exception.HandleError(Imports.ImageAssign(Handle, source.Handle)); } public void CreateEmpty(Format format, Int32 width, Int32 height) { _data = null; Exception.HandleError(Imports.ImageCreateEmpty(Handle, format, width, height)); } public void LoadFromFunc(LoadCallback callback) { _data = null; LoadArgs args = new LoadArgs() { callback = callback, image = this, }; var argsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(args)); Marshal.StructureToPtr(args, argsPtr, false); try { Exception.HandleError(Imports.ImageLoadFromFunc(Handle, _loadHandler, argsPtr)); } finally { Marshal.FreeHGlobal(argsPtr); } } public void Resize(Int32 width, Int32 height, Int32 x, Int32 y) { _data = null; Exception.HandleError(Imports.ImageResize(Handle, width, height, x, y)); } public void FillColor(Color color, ColorChannels mask, ImageModes modes) { _data = null; Exception.HandleError(Imports.ImageFillColor(Handle, color, mask, ref modes)); } public void FillPattern(Image pattern, Int32 x, Int32 y, ColorChannels mask, ImageModes modes) { _data = null; Exception.HandleError(Imports.ImageFillPattern(Handle, pattern.Handle, x, y, mask, ref modes)); } public void Blend(Image other, Int32 x, Int32 y, BlendCallback callback) { _data = null; BlendArgs args = new BlendArgs() { callback = callback, image = this, }; var argsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(args)); Marshal.StructureToPtr(args, argsPtr, false); try { Exception.HandleError(Imports.ImageBlend(Handle, other.Handle, x, y, _blendHandler, argsPtr)); } finally { Marshal.FreeHGlobal(argsPtr); } } public void Blur(float horzRad, float horzStr, float vertRad, float vertStr, ColorChannels mask) { _data = null; Exception.HandleError(Imports.ImageBlur(Handle, horzRad, horzStr, vertRad, vertStr, mask)); } #region IDisposable Support protected virtual void Dispose(bool disposing) { if (Handle != UIntPtr.Zero && _ownsHandle) { Imports.ImageDestroy(Handle); Handle = UIntPtr.Zero; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } public abstract class PostProcessor : IDisposable { ~PostProcessor() { Dispose(false); } public PostProcessorHandle Handle { get; protected set; } public void Execute(Char c, Image i) { Exception.HandleError(Imports.PostProcessorExecute(Handle, c.Handle, i.Handle)); } public void AddRange(CharRangeUsage usage, WideChar start, WideChar stop) { Exception.HandleError(Imports.PostProcessorAddRange(Handle, usage, start, stop)); } public void AddChars(CharRangeUsage usage, string s) { Exception.HandleError(Imports.PostProcessorAddChars(Handle, usage, s)); } public void ClearRanges() { Exception.HandleError(Imports.PostProcessorClearRanges(Handle)); } #region IDisposable Support protected virtual void Dispose(bool disposing) { if (Handle != UIntPtr.Zero) { Imports.PostProcessorDestroy(Handle); Handle = UIntPtr.Zero; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } public class PostProcessorFillColor : PostProcessor { public PostProcessorFillColor(Context context, Color color, ImageModes modes, ColorChannels channels) { if (context == null) throw new ArgumentNullException("context"); Color = color; Modes = modes; Channels = channels; Handle = Imports.PostProcessorFillColorCreate(context.Handle, color, ref modes, channels); if (Handle == UIntPtr.Zero) Exception.ThrowLastError(); } public Color Color { get; private set; } public ImageModes Modes { get; private set; } public ColorChannels Channels { get; private set; } } public class PostProcessorFillPattern : PostProcessor { public PostProcessorFillPattern(Context context, Image pattern, Position pos, ImageModes modes, ColorChannels channels) { if (context == null) throw new ArgumentNullException("context"); if (pattern == null) throw new ArgumentNullException("pattern"); Pattern = pattern; Position = pos; Modes = modes; Channels = channels; Handle = Imports.PostProcessorFillPatternCreate(context.Handle, Pattern.Handle, false, Position, ref modes, Channels); if (Handle == UIntPtr.Zero) Exception.ThrowLastError(); } public Image Pattern { get; private set; } public Position Position { get; private set; } public ImageModes Modes { get; private set; } public ColorChannels Channels { get; private set; } } public class PostProcessorBorder : PostProcessor { public PostProcessorBorder(Context context, float width, float strength, Color color, bool keepSize) { if (context == null) throw new ArgumentNullException("context"); Width = width; Strength = strength; Color = color; KeepSize = keepSize; Handle = Imports.PostProcessorBorderCreate(context.Handle, Width, Strength, Color, KeepSize); if (Handle == UIntPtr.Zero) Exception.ThrowLastError(); } public float Width { get; private set; } public float Strength { get; private set; } public Color Color { get; private set; } public bool KeepSize { get; private set; } } public class PostProcessorShadow : PostProcessor { public PostProcessorShadow(Context context, float radius, float strength, Position offset, Color color) { if (context == null) throw new ArgumentNullException("context"); Radius = radius; Strength = strength; Offset = offset; Color = color; Handle = Imports.PostProcessorShadowCreate(context.Handle, Radius, Strength, Offset, Color); if (Handle == UIntPtr.Zero) Exception.ThrowLastError(); } public float Radius { get; private set; } public float Strength { get; private set; } public Position Offset { get; private set; } public Color Color { get; private set; } } public abstract class PostProcessorCustom : PostProcessor { private GCHandle _self; private static Imports.PostProcessorHandler _executeHandler = new Imports.PostProcessorHandler(ExecuteHandler); private static void ExecuteHandler(CharHandle charHandle, ImageHandle imageHandle, IntPtr args) { GCHandle self = (GCHandle)args; Char c = new Char(charHandle); Image i = new Image(imageHandle); (self.Target as PostProcessorCustom).doExecute(c, i); } public PostProcessorCustom(Context context) { if (context == null) throw new ArgumentNullException("context"); _self = GCHandle.Alloc(this); PostProcessorData data = new PostProcessorData() { args = (IntPtr)_self, ExecuteCallback = Marshal.GetFunctionPointerForDelegate(_executeHandler), }; Handle = Imports.PostProcessorCustomCreate(context.Handle, ref data); if (Handle == UIntPtr.Zero) Exception.ThrowLastError(); } protected abstract void doExecute(Char c, Image i); protected override void Dispose(bool disposing) { base.Dispose(disposing); _self.Free(); } } public class PostProcessorList : PostProcessorCustom, IList { private List _items; public PostProcessorList(Context context) : base(context) { _items = new List(); } protected override void doExecute(Char c, Image i) { foreach (var item in _items) item.Execute(c, i); } #region IList public PostProcessor this[int index] { get { return _items[index]; } set { _items[index] = value; } } public int Count { get { return _items.Count; } } public bool IsReadOnly { get { return false; } } public void Add(PostProcessor item) { _items.Add(item); } public void Clear() { _items.Clear(); } public bool Contains(PostProcessor item) { return _items.Contains(item); } public void CopyTo(PostProcessor[] array, int arrayIndex) { _items.CopyTo(array, arrayIndex); } public IEnumerator GetEnumerator() { return _items.GetEnumerator(); } public int IndexOf(PostProcessor item) { return _items.IndexOf(item); } public void Insert(int index, PostProcessor item) { _items.Insert(index, item); } public bool Remove(PostProcessor item) { return _items.Remove(item); } public void RemoveAt(int index) { _items.RemoveAt(index); } IEnumerator IEnumerable.GetEnumerator() { return _items.GetEnumerator(); } #endregion } public class Font : IDisposable { private readonly bool _ownsHandle; private PostProcessor _postProcessor; public Font(FontHandle handle, bool ownsHandle) { Handle = handle; _ownsHandle = ownsHandle; } ~Font() { Dispose(false); } public FontHandle Handle { get; private set; } public string Fontname { get { var s = Imports.FontGetFontName(Handle); if (s == IntPtr.Zero) Exception.ThrowLastError(); return Marshal.PtrToStringUni(s); } } public string Facename { get { var s = Imports.FontGetFaceName(Handle); if (s == IntPtr.Zero) Exception.ThrowLastError(); return Marshal.PtrToStringUni(s); } } public string Stylename { get { var s = Imports.FontGetStyleName(Handle); if (s == IntPtr.Zero) Exception.ThrowLastError(); return Marshal.PtrToStringUni(s); } } public string Fullname { get { var s = Imports.FontGetFullName(Handle); if (s == IntPtr.Zero) Exception.ThrowLastError(); return Marshal.PtrToStringUni(s); } } public FontMetric Metric { get { FontMetric value; Exception.HandleError(Imports.FontGetMetric(Handle, out value)); return value; } } public PostProcessor PostProcessor { get { return _postProcessor; } set { _postProcessor = value; Exception.HandleError(Imports.FontSetPostProcessor(Handle, _postProcessor != null ? _postProcessor.Handle : PostProcessorHandle.Zero)); } } public Int32 TabWidth { get { Int32 value; Exception.HandleError(Imports.FontGetTabWidth(Handle, out value)); return value; } set { Exception.HandleError(Imports.FontSetTabWidth(Handle, value)); } } public Int32 CharSpacing { get { Int32 value; Exception.HandleError(Imports.FontGetCharSpacing(Handle, out value)); return value; } set { Exception.HandleError(Imports.FontSetCharSpacing(Handle, value)); } } public Int32 LineSpacing { get { Int32 value; Exception.HandleError(Imports.FontGetLineSpacing(Handle, out value)); return value; } set { Exception.HandleError(Imports.FontSetLineSpacing(Handle, value)); } } #region IDisposable Support protected virtual void Dispose(bool disposing) { if (Handle != UIntPtr.Zero && _ownsHandle) { Imports.FontDestroy(Handle); Handle = UIntPtr.Zero; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } public abstract class FontCreator : IDisposable { private static readonly Imports.FontCreatorStreamReadHandler _readHandler = new Imports.FontCreatorStreamReadHandler(ReadHandler); private static Int32 ReadHandler(IntPtr args, IntPtr buffer, int count) { GCHandle sHandle = (GCHandle)args; var stream = (sHandle.Target as Stream); var buf = new byte[count]; var read = stream.Read(buf, 0, buf.Length); Marshal.Copy(buf, 0, buffer, read); return read; } private static readonly Imports.FontCreatorStreamSeekHandler _seekHandler = new Imports.FontCreatorStreamSeekHandler(SeekHandler); private static Int32 SeekHandler(IntPtr args, StreamOrigin origin, int offset) { GCHandle sHandle = (GCHandle)args; var stream = (sHandle.Target as Stream); switch (origin) { case StreamOrigin.Begin: return (Int32)stream.Seek(offset, SeekOrigin.Begin); case StreamOrigin.Current: return (Int32)stream.Seek(offset, SeekOrigin.Current); case StreamOrigin.End: return (Int32)stream.Seek(offset, SeekOrigin.End); } throw new ArgumentException("invalid stream origin" + origin); } ~FontCreator() { Dispose(false); } public FontCreatorHandle Handle { get; protected set; } public Font GetFontByName(string name, Int32 size, FontStyles style, AntiAliasing antiAliasing) { var handle = Imports.FontCreatorGetFontByName(Handle, name, size, style, antiAliasing); if (handle == FontHandle.Zero) Exception.ThrowLastError(); return new Font(handle, true); } public Font GetFontByFile(string filename, Int32 size, FontStyles style, AntiAliasing antiAliasing) { var handle = Imports.FontCreatorGetFontByFile(Handle, filename, size, style, antiAliasing); if (handle == FontHandle.Zero) Exception.ThrowLastError(); return new Font(handle, true); } public Font GetFontByStream(Stream stream, Int32 size, FontStyles style, AntiAliasing antiAliasing) { var streamHandle = GCHandle.Alloc(stream); try { var data = new StreamData() { args = (IntPtr)streamHandle, ReadCallback = Marshal.GetFunctionPointerForDelegate(_readHandler), SeekCallback = Marshal.GetFunctionPointerForDelegate(_seekHandler), }; var handle = Imports.FontCreatorGetFontByStream(Handle, ref data, size, style, antiAliasing); if (handle == FontHandle.Zero) Exception.ThrowLastError(); return new Font(handle, true); } finally { streamHandle.Free(); } } #region IDisposable Support protected virtual void Dispose(bool disposing) { if (Handle != UIntPtr.Zero) { Imports.FontCreatorDestory(Handle); Handle = UIntPtr.Zero; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } public class FontCreatorGdi : FontCreator { public FontCreatorGdi(Context context) : base() { if (context == null) throw new ArgumentNullException("context"); Handle = Imports.FontCreatorCreate(context.Handle, FontCreatorType.GDI); if (Handle == FontHandle.Zero) Exception.ThrowLastError(); } } public class FontCreatorFreeType : FontCreator { public FontCreatorFreeType(Context context) : base() { if (context == null) throw new ArgumentNullException("context"); Handle = Imports.FontCreatorCreate(context.Handle, FontCreatorType.FreeType); if (Handle == FontHandle.Zero) Exception.ThrowLastError(); } } public class TextBlock : IDisposable { Font _font = null; private readonly bool _ownsHandle; public TextBlock(TextBlockHandle handle, bool ownsHandle) { Handle = handle; _ownsHandle = ownsHandle; } ~TextBlock() { Dispose(false); } public TextBlockHandle Handle { get; private set; } public Rect Rect { get { Rect value; Exception.HandleError(Imports.TextBlockGetRect(Handle, out value)); return value; } } public Int32 Width { get { Int32 value; Exception.HandleError(Imports.TextBlockGetWidth(Handle, out value)); return value; } } public Int32 Height { get { Int32 value; Exception.HandleError(Imports.TextBlockGetHeight(Handle, out value)); return value; } } public BlockFlags Flags { get { BlockFlags value; Exception.HandleError(Imports.TextBlockGetFlags(Handle, out value)); return value; } } public Int32 Top { get { Int32 value; Exception.HandleError(Imports.TextBlockGetTop(Handle, out value)); return value; } set { Exception.HandleError(Imports.TextBlockSetTop(Handle, value)); } } public Int32 Left { get { Int32 value; Exception.HandleError(Imports.TextBlockGetLeft(Handle, out value)); return value; } set { Exception.HandleError(Imports.TextBlockSetLeft(Handle, value)); } } public VertAlign VertAlign { get { VertAlign value; Exception.HandleError(Imports.TextBlockGetVertAlign(Handle, out value)); return value; } set { Exception.HandleError(Imports.TextBlockSetVertAlign(Handle, value)); } } public HorzAlign HorzAlign { get { HorzAlign value; Exception.HandleError(Imports.TextBlockGetHorzAlign(Handle, out value)); return value; } set { Exception.HandleError(Imports.TextBlockSetHorzAlign(Handle, value)); } } public Clipping Clipping { get { Clipping value; Exception.HandleError(Imports.TextBlockGetClipping(Handle, out value)); return value; } set { Exception.HandleError(Imports.TextBlockSetClipping(Handle, value)); } } public Color Color { get { Color value; Exception.HandleError(Imports.TextBlockGetColor(Handle, out value)); return value; } set { Exception.HandleError(Imports.TextBlockSetColor(Handle, value)); } } public Font Font { get { return _font; } set { _font = value; Exception.HandleError(Imports.TextBlockSetFont(Handle, _font == null ? FontHandle.Zero : _font.Handle)); } } public Int32 ActualHeight { get { Int32 value = Imports.TextBlockGetActualHeight(Handle); if (value < 0) Exception.ThrowLastError(); return value; } } public void TextOut(string text) { if (text == null) throw new ArgumentNullException("text"); Exception.HandleError(Imports.TextBlockTextOutA(Handle, text)); } Int32 GetTextWidth(string text) { Int32 value = Imports.TextBlockGetTextWidthA(Handle, text); if (value < 0) Exception.ThrowLastError(); return value; } #region IDisposable Support protected virtual void Dispose(bool disposing) { if (Handle != UIntPtr.Zero && _ownsHandle) { Imports.TextBlockDestroy(Handle); Handle = UIntPtr.Zero; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } public abstract class Renderer : IDisposable { ~Renderer() { Dispose(false); } public RendererHandle Handle { get; protected set; } public TextBlock BeginBlock(Int32 top, Int32 left, Int32 width, Int32 height, BlockFlags flags) { var tb = Imports.RendererBeginBlock(Handle, top, left, width, height, flags); if (tb == TextBlockHandle.Zero) Exception.ThrowLastError(); return new TextBlock(tb, false); } public void EndBlock(TextBlock block) { if (block == null) return; Exception.HandleError(Imports.RendererEndBlock(Handle, block.Handle)); block = null; } public void AbortBlock(TextBlock block) { if (block == null) return; Exception.HandleError(Imports.RendererAbortBlock(Handle, block.Handle)); block = null; } public Int32 GetTextWidth(Font font, string text) { if (font == null) throw new ArgumentNullException("font"); if (text == null) throw new ArgumentNullException("text"); Int32 value = Imports.RendererGetTextWidthA(Handle, font.Handle, text); if (value < 0) Exception.ThrowLastError(); return value; } #region IDisposable Support protected virtual void Dispose(bool disposing) { if (Handle != UIntPtr.Zero) { Imports.RendererDestroy(Handle); Handle = UIntPtr.Zero; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } public class RendererOpenGl : Renderer { public RendererOpenGl(Context context, Format format) { Handle = Imports.RendererCreate(context.Handle, (Int32)RendererType.OpenGL, (Int32)format); if (Handle == RendererHandle.Zero) Exception.ThrowLastError(); } } }