public static uint SelectFont(GDIContext hdc, System.Drawing.Font font) { GDI32.SelectObject(hdc, font.ToHfont()); uint size = GDI32.GetOutlineTextMetrics(hdc, 0, IntPtr.Zero); if (size != uint.MaxValue) { UnmanagedMemory otm = new UnmanagedMemory((int)size); uint err = GDI32.GetOutlineTextMetrics(hdc, size, otm.MemoryPointer); uint otmEMSquare = (uint)Marshal.ReadInt32(otm, 92); otm.Dispose(); LOGFONT log = new LOGFONT(); font.ToLogFont(log); log.lfHeight = -(int)otmEMSquare; font = System.Drawing.Font.FromLogFont(log); GDI32.SelectObject(hdc, font.ToHfont()); } return size; }
public RectangleI[] GetRectangles() { // If the region is empty, return a single empty rectangle if (IsEmpty) { return new RectangleI[1]; } // 1. Call GetRgnData with null to get size uint dataLengthNeeded = GDI32.GetRegionData(DangerousGetHandle(), 0, IntPtr.Zero); // 2. allocate some memory to hold the data UnmanagedMemory uMem = new UnmanagedMemory((int)dataLengthNeeded); IntPtr memoryPtr = uMem.MemoryPointer; UnmanagedPointer structPtr = new UnmanagedPointer(memoryPtr); // 3. call again passing in memory uint bytesFilled = GDI32.GetRegionData(DangerousGetHandle(), dataLengthNeeded, structPtr); // If the return value is 0, then the call failed. if (0 == bytesFilled) return null; // 4. convert memory to data structures // First get the RGNDATAHEADER RGNDATAHEADER dataHeader; dataHeader = (RGNDATAHEADER)Marshal.PtrToStructure(structPtr, typeof(RGNDATAHEADER)); // dataHeader.dwSize - tells us how big the header is, and thus how many bytes to skip to get // to the rectangle information // dataHeader.nRgnSize - tells us how many bytes are needed for the rectangle information // dataHeader.nCount - tells us how many rectangles there are structPtr = structPtr + dataHeader.dwSize; // The nRgnSize / nCount will tell us how many bytes per rectangle structure // and therefore how much to advance the pointer as we turn the buffer // into a set of rectangles using PtrToStructure. int structIncrement = (int)(dataHeader.nRgnSize / dataHeader.nCount); // Create a list to add the rectangles to. This is simply convenient. RectangleI[] rects = new RectangleI[dataHeader.nCount]; // Loop through creating as many rectangles as indicated by the dataheader nCount field for (int i = 0; i < dataHeader.nCount; i++) { RECT rect = (RECT)Marshal.PtrToStructure(structPtr, typeof(RECT)); rects[i].x1 = rect.X; rects[i].y1 = rect.Y; rects[i].x2 = rect.X + rect.Width; rects[i].y2 = rect.Y + rect.Height; rects[i].Normalize(); structPtr = structPtr + structIncrement; } // 5. free memory uMem.Dispose(); return rects; }
public static bool IsTrueType(GDIContext hdc, System.Drawing.Font font) { GDI32.SelectObject(hdc, font.ToHfont()); UnmanagedMemory tmPtr = new UnmanagedMemory(Marshal.SizeOf(typeof(TEXTMETRIC))); uint err = GDI32.GetTextMetrics(hdc, tmPtr.MemoryPointer); TEXTMETRIC tm = (TEXTMETRIC)Marshal.PtrToStructure(tmPtr.MemoryPointer, typeof(TEXTMETRIC)); tmPtr.Dispose(); return (tm.tmPitchAndFamily & 4) != 0; }