internal void UpdateFont(WindowsFont font)
 {
     if (this.LastUsedFont != font)
     {
         this.LastUsedFont = font;
         this.LeftTextMargin = -1;
         this.RightTextMargin = -1;
     }
 }
 internal static bool IsFontInUse(WindowsFont wf)
 {
     if (wf != null)
     {
         for (int i = 0; i < activeDeviceContexts.Count; i++)
         {
             DeviceContext context = activeDeviceContexts[i] as DeviceContext;
             if ((context != null) && ((context.ActiveFont == wf) || context.IsFontOnContextStack(wf)))
             {
                 return true;
             }
         }
     }
     return false;
 }
 internal static IntNativeMethods.DRAWTEXTPARAMS GetTextMargins(WindowsGraphics wg, WindowsFont font)
 {
     CachedInfo cachedMeasurementDCInfo = MeasurementDCInfo.cachedMeasurementDCInfo;
     if (((cachedMeasurementDCInfo == null) || (cachedMeasurementDCInfo.LeftTextMargin <= 0)) || ((cachedMeasurementDCInfo.RightTextMargin <= 0) || (font != cachedMeasurementDCInfo.LastUsedFont)))
     {
         if (cachedMeasurementDCInfo == null)
         {
             cachedMeasurementDCInfo = new CachedInfo();
             MeasurementDCInfo.cachedMeasurementDCInfo = cachedMeasurementDCInfo;
         }
         IntNativeMethods.DRAWTEXTPARAMS textMargins = wg.GetTextMargins(font);
         cachedMeasurementDCInfo.LeftTextMargin = textMargins.iLeftMargin;
         cachedMeasurementDCInfo.RightTextMargin = textMargins.iRightMargin;
     }
     return new IntNativeMethods.DRAWTEXTPARAMS(cachedMeasurementDCInfo.LeftTextMargin, cachedMeasurementDCInfo.RightTextMargin);
 }
 public void ResetFont()
 {
     MeasurementDCInfo.ResetIfIsMeasurementDC(this.Hdc);
     IntUnsafeNativeMethods.SelectObject(new HandleRef(this, this.Hdc), new HandleRef(null, this.hInitialFont));
     this.selectedFont = null;
     this.hCurrentFont = this.hInitialFont;
 }
 internal void DisposeFont(bool disposing)
 {
     if (disposing)
     {
         DeviceContexts.RemoveDeviceContext(this);
     }
     if ((this.selectedFont != null) && (this.selectedFont.Hfont != IntPtr.Zero))
     {
         if (IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(this, this.hDC), 6) == this.selectedFont.Hfont)
         {
             IntUnsafeNativeMethods.SelectObject(new HandleRef(this, this.Hdc), new HandleRef(null, this.hInitialFont));
             IntPtr hInitialFont = this.hInitialFont;
         }
         this.selectedFont.Dispose(disposing);
         this.selectedFont = null;
     }
 }
예제 #6
0
 /// <summary>
 ///  Returns the Size in logical units of the given text using the given Font and using the specified rectangle
 ///  as the text bounding box (see overload below for more info).
 ///  TAB/CR/LF are taken into account.
 /// </summary>
 public Size MeasureText(string text, WindowsFont font, Size proposedSize)
 => MeasureText(text, font, proposedSize, User32.DT.BOTTOM);
예제 #7
0
 /// <summary>
 ///  Draws the text centered in the given rectangle and using the given Font, foreColor and backColor.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor, Color backColor)
 => DrawText(text, font, bounds, foreColor, backColor, User32.DT.CENTER | User32.DT.VCENTER);
예제 #8
0
 /// <summary>
 ///  Draws the text in the given bounds, using the given Font and foreColor, and according to the specified flags.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color color, Interop.User32.TextFormatFlags flags)
 {
     DrawText(text, font, bounds, color, Color.Empty, flags);
 }
예제 #9
0
 /// <summary>
 ///  Draws the text at the specified point, using the given Font, foreColor and backColor.
 ///  CR/LF are honored.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor)
 {
     DrawText(text, font, pt, foreColor, backColor, Interop.User32.TextFormatFlags.DT_DEFAULT);
 }
예제 #10
0
        /// <summary>
        ///  Draws the text in the given bounds, using the given Font, foreColor and backColor, and according to the specified
        ///  TextFormatFlags flags.
        ///  If font is null, the font currently selected in the hdc is used.
        ///  If foreColor and/or backColor are Color.Empty, the hdc current text and/or background color are used.
        /// </summary>
        public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor, Color backColor, IntTextFormatFlags flags)
        {
            if (string.IsNullOrEmpty(text) || foreColor == Color.Transparent)
            {
                return;
            }

            Debug.Assert(((uint)flags & GdiUnsupportedFlagMask) == 0, "Some custom flags were left over and are not GDI compliant!");
            Debug.Assert((flags & IntTextFormatFlags.CalculateRectangle) == 0, "CalculateRectangle flag is set, text won't be drawn");

            HandleRef hdc = new HandleRef(dc, dc.Hdc);

            // DrawText requires default text alignment.
            if (dc.TextAlignment != DeviceContextTextAlignment.Default)
            {
                dc.SetTextAlignment(DeviceContextTextAlignment.Default);
            }

            // color empty means use the one currently selected in the dc.

            if (!foreColor.IsEmpty && foreColor != dc.TextColor)
            {
                dc.SetTextColor(foreColor);
            }

            if (font != null)
            {
                dc.SelectFont(font);
            }

            DeviceContextBackgroundMode newBackGndMode = (backColor.IsEmpty || backColor == Color.Transparent) ?
                                                         DeviceContextBackgroundMode.Transparent :
                                                         DeviceContextBackgroundMode.Opaque;

            if (dc.BackgroundMode != newBackGndMode)
            {
                dc.SetBackgroundMode(newBackGndMode);
            }

            if (newBackGndMode != DeviceContextBackgroundMode.Transparent && backColor != dc.BackgroundColor)
            {
                dc.SetBackgroundColor(backColor);
            }

            IntNativeMethods.DRAWTEXTPARAMS dtparams = GetTextMargins(font);

            bounds = AdjustForVerticalAlignment(hdc, text, bounds, flags, dtparams);

            // Adjust unbounded rect to avoid overflow since Rectangle ctr does not do param validation.
            if (bounds.Width == MaxSize.Width)
            {
                bounds.Width -= bounds.X;
            }
            if (bounds.Height == MaxSize.Height)
            {
                bounds.Height -= bounds.Y;
            }

            IntNativeMethods.RECT rect = new IntNativeMethods.RECT(bounds);

            IntUnsafeNativeMethods.DrawTextEx(hdc, text, ref rect, (int)flags, dtparams);

            // No need to restore previous objects into the dc (see comments on top of the class).
        }
예제 #11
0
 /// <summary>
 ///  Draws the text centered in the given rectangle and using the given Font, foreColor and backColor.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor, Color backColor)
 {
     DrawText(text, font, bounds, foreColor, backColor, IntTextFormatFlags.HorizontalCenter | IntTextFormatFlags.VerticalCenter);
 }
예제 #12
0
 /// <summary>
 ///  Draws the text at the specified point, using the given Font, foreColor and backColor.
 ///  CR/LF are honored.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor)
 {
     DrawText(text, font, pt, foreColor, backColor, IntTextFormatFlags.Default);
 }
        public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor, IntTextFormatFlags flags)
        {
            Rectangle bounds = new Rectangle(pt.X, pt.Y, 0x7fffffff, 0x7fffffff);

            this.DrawText(text, font, bounds, foreColor, backColor, flags);
        }
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, IntTextFormatFlags flags)
 {
     this.DrawText(text, font, pt, foreColor, Color.Empty, flags);
 }
 public IntPtr SelectFont(WindowsFont font)
 {
     if (font.Equals(this.Font))
     {
         return IntPtr.Zero;
     }
     IntPtr ptr = this.SelectObject(font.Hfont, GdiObjectType.Font);
     WindowsFont selectedFont = this.selectedFont;
     this.selectedFont = font;
     this.hCurrentFont = font.Hfont;
     if ((selectedFont != null) && MeasurementDCInfo.IsMeasurementDC(this))
     {
         selectedFont.Dispose();
     }
     if (MeasurementDCInfo.IsMeasurementDC(this))
     {
         if (ptr != IntPtr.Zero)
         {
             MeasurementDCInfo.LastUsedFont = font;
             return ptr;
         }
         MeasurementDCInfo.Reset();
     }
     return ptr;
 }
예제 #16
0
        public static WindowsFont GetWindowsFont(Font font, WindowsFontQuality fontQuality)
        {
            if (font == null)
            {
                return(null);
            }
            int num          = 0;
            int currentIndex = WindowsGraphicsCacheManager.currentIndex;

            while (num < WindowsFontCache.Count)
            {
                KeyValuePair <Font, WindowsFont> pair2 = WindowsFontCache[currentIndex];
                if (pair2.Key.Equals(font))
                {
                    KeyValuePair <Font, WindowsFont> pair3 = WindowsFontCache[currentIndex];
                    WindowsFont font2 = pair3.Value;
                    if (font2.Quality == fontQuality)
                    {
                        return(font2);
                    }
                }
                currentIndex--;
                num++;
                if (currentIndex < 0)
                {
                    currentIndex = 9;
                }
            }
            WindowsFont font3 = WindowsFont.FromFont(font, fontQuality);
            KeyValuePair <Font, WindowsFont> item = new KeyValuePair <Font, WindowsFont>(font, font3);

            WindowsGraphicsCacheManager.currentIndex++;
            if (WindowsGraphicsCacheManager.currentIndex == 10)
            {
                WindowsGraphicsCacheManager.currentIndex = 0;
            }
            if (WindowsFontCache.Count != 10)
            {
                font3.OwnedByCacheManager = true;
                WindowsFontCache.Add(item);
                return(font3);
            }
            WindowsFont wf   = null;
            bool        flag = false;
            int         num3 = WindowsGraphicsCacheManager.currentIndex;
            int         num4 = num3 + 1;

            while (!flag)
            {
                if (num4 >= 10)
                {
                    num4 = 0;
                }
                if (num4 == num3)
                {
                    flag = true;
                }
                KeyValuePair <Font, WindowsFont> pair4 = WindowsFontCache[num4];
                wf = pair4.Value;
                if (!DeviceContexts.IsFontInUse(wf))
                {
                    WindowsGraphicsCacheManager.currentIndex = num4;
                    flag = true;
                    break;
                }
                num4++;
                wf = null;
            }
            if (wf != null)
            {
                WindowsFontCache[WindowsGraphicsCacheManager.currentIndex] = item;
                font3.OwnedByCacheManager = true;
                wf.OwnedByCacheManager    = false;
                wf.Dispose();
                return(font3);
            }
            font3.OwnedByCacheManager = false;
            return(font3);
        }
예제 #17
0
 /// <summary>
 ///  Returns the Size in logical units of the given text using the given Font.
 ///  CR/LF/TAB are taken into account.
 /// </summary>
 public Size MeasureText(string text, WindowsFont font)
 {
     return(MeasureText(text, font, MaxSize, IntTextFormatFlags.Default));
 }
예제 #18
0
        /// <summary>
        ///  Draws the text at the specified point, using the given Font, foreColor and backColor, and according
        ///  to the specified flags.
        /// </summary>
        public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor, Interop.User32.TextFormatFlags flags)
        {
            Rectangle bounds = new Rectangle(pt.X, pt.Y, int.MaxValue, int.MaxValue);

            DrawText(text, font, bounds, foreColor, backColor, flags);
        }
예제 #19
0
 /// <summary>
 ///  Returns the Size in logical units of the given text using the given Font and using the specified rectangle
 ///  as the text bounding box (see overload below for more info).
 ///  TAB/CR/LF are taken into account.
 /// </summary>
 public Size MeasureText(string text, WindowsFont font, Size proposedSize)
 {
     return(MeasureText(text, font, proposedSize, IntTextFormatFlags.Default));
 }
예제 #20
0
 /// <summary>
 ///  Draws the text at the specified point, using the given Font, foreColor and backColor, and according
 ///  to the specified flags.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor, User32.DT flags)
 => DrawText(text, font, new Rectangle(pt, MaxSize), foreColor, backColor, flags);
예제 #21
0
        /// <summary>
        ///  Returns the Size in logical units of the given text using the given Font, and according to the formatting flags.
        ///  The proposed size is used to create a bounding rectangle as follows:
        ///  - If there are multiple lines of text, DrawText uses the width of the rectangle pointed to by
        ///  the lpRect parameter and extends the base of the rectangle to bound the last line of text.
        ///  - If the largest word is wider than the rectangle, the width is expanded.
        ///  - If the text is less than the width of the rectangle, the width is reduced.
        ///  - If there is only one line of text, DrawText modifies the right side of the rectangle so that
        ///  it bounds the last character in the line.
        ///  If the font is null, the hdc's current font will be used.
        ///
        ///  Note for vertical fonts (if ever supported): DrawTextEx uses GetTextExtentPoint32 for measuring the text and this
        ///  function has the following limitation (from MSDN):
        ///  - This function assumes that the text is horizontal, that is, that the escapement is always 0. This is true for both
        ///  the horizontal and vertical measurements of the text.  The application must convert it explicitly.
        /// </summary>
        public Size MeasureText(string text, WindowsFont font, Size proposedSize, IntTextFormatFlags flags)
        {
            Debug.Assert(((uint)flags & GdiUnsupportedFlagMask) == 0, "Some custom flags were left over and are not GDI compliant!");

            if (string.IsNullOrEmpty(text))
            {
                return(Size.Empty);
            }

            //
            // DrawText returns a rectangle useful for aligning, but not guaranteed to encompass all
            // pixels (its not a FitBlackBox, if the text is italicized, it will overhang on the right.)
            // So we need to account for this.
            //
            IntNativeMethods.DRAWTEXTPARAMS dtparams = null;

#if OPTIMIZED_MEASUREMENTDC
            // use the cache if we've got it
            if (MeasurementDCInfo.IsMeasurementDC(DeviceContext))
            {
                dtparams = MeasurementDCInfo.GetTextMargins(this, font);
            }
#endif

            if (dtparams == null)
            {
                dtparams = GetTextMargins(font);
            }

            //
            // If Width / Height are < 0, we need to make them larger or DrawText will return
            // an unbounded measurement when we actually trying to make it very narrow.
            //

            int minWidth = 1 + dtparams.iLeftMargin + dtparams.iRightMargin;

            if (proposedSize.Width <= minWidth)
            {
                proposedSize.Width = minWidth;
            }
            if (proposedSize.Height <= 0)
            {
                proposedSize.Height = 1;
            }

            IntNativeMethods.RECT rect = IntNativeMethods.RECT.FromXYWH(0, 0, proposedSize.Width, proposedSize.Height);

            HandleRef hdc = new HandleRef(null, dc.Hdc);

            if (font != null)
            {
                dc.SelectFont(font);
            }

            // If proposedSize.Height >= MaxSize.Height it is assumed bounds needed.  If flags contain SingleLine and
            // VerticalCenter or Bottom options, DrawTextEx does not bind the rectangle to the actual text height since
            // it assumes the text is to be vertically aligned; we need to clear the VerticalCenter and Bottom flags to
            // get the actual text bounds.
            if (proposedSize.Height >= MaxSize.Height && (flags & IntTextFormatFlags.SingleLine) != 0)
            {
                // Clear vertical-alignment flags.
                flags &= ~(IntTextFormatFlags.Bottom | IntTextFormatFlags.VerticalCenter);
            }

            if (proposedSize.Width == MaxSize.Width)
            {
                // PERF: No constraining width means no word break.
                // in this case, we dont care about word wrapping - there should be enough room to fit it all
                flags &= ~(IntTextFormatFlags.WordBreak);
            }

            flags |= IntTextFormatFlags.CalculateRectangle;
            IntUnsafeNativeMethods.DrawTextEx(hdc, text, ref rect, (int)flags, dtparams);

            /* No need to restore previous objects into the dc (see comments on top of the class).
             *
             * if( hOldFont != IntPtr.Zero )
             * {
             *  this.dc.SelectObject(hOldFont);
             * }
             */

            return(rect.Size);
        }
예제 #22
0
        /// <summary>
        ///  Draws the text in the given bounds, using the given Font, foreColor and backColor, and according to the specified
        ///  TextFormatFlags flags.
        ///
        ///  If font is null, the font currently selected in the hdc is used.
        ///
        ///  If foreColor and/or backColor are Color.Empty, the hdc current text and/or background color are used.
        /// </summary>
        public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor, Color backColor, User32.DT flags)
        {
            if (string.IsNullOrEmpty(text) || foreColor == Color.Transparent)
            {
                return;
            }

            Debug.Assert(((uint)flags & GdiUnsupportedFlagMask) == 0, "Some custom flags were left over and are not GDI compliant!");
            Debug.Assert((flags & User32.DT.CALCRECT) == 0, "CALCRECT flag is set, text won't be drawn");

            HandleRef hdc = new HandleRef(DeviceContext, DeviceContext.Hdc);

            // DrawText requires default text alignment.
            if (DeviceContext.TextAlignment != default)
            {
                DeviceContext.TextAlignment = default;
            }

            // color empty means use the one currently selected in the dc.

            if (!foreColor.IsEmpty && foreColor != DeviceContext.TextColor)
            {
                DeviceContext.TextColor = foreColor;
            }

            if (font != null)
            {
                DeviceContext.SelectFont(font);
            }

            Gdi32.BKMODE newBackGndMode = (backColor.IsEmpty || backColor == Color.Transparent) ?
                                          Gdi32.BKMODE.TRANSPARENT :
                                          Gdi32.BKMODE.OPAQUE;

            if (DeviceContext.BackgroundMode != newBackGndMode)
            {
                DeviceContext.SetBackgroundMode(newBackGndMode);
            }

            if (newBackGndMode != Gdi32.BKMODE.TRANSPARENT && backColor != DeviceContext.BackgroundColor)
            {
                DeviceContext.BackgroundColor = backColor;
            }

            User32.DRAWTEXTPARAMS dtparams = GetTextMargins(font);

            bounds = AdjustForVerticalAlignment(hdc, text, bounds, flags, ref dtparams);

            // Adjust unbounded rect to avoid overflow since Rectangle ctr does not do param validation.
            if (bounds.Width == MaxSize.Width)
            {
                bounds.Width -= bounds.X;
            }
            if (bounds.Height == MaxSize.Height)
            {
                bounds.Height -= bounds.Y;
            }

            var rect = new RECT(bounds);

            User32.DrawTextExW(hdc, text, text.Length, ref rect, flags, ref dtparams);

            // No need to restore previous objects into the dc (see comments on top of the class).
        }
예제 #23
0
        ///  Text rendering methods

        /// <summary>
        ///  Draws the text at the specified point, using the given Font and foreColor.
        ///  CR/LF are honored.
        /// </summary>
        public void DrawText(string text, WindowsFont font, Point pt, Color foreColor)
        => DrawText(text, font, pt, foreColor, Color.Empty, User32.TextFormatFlags.DT_DEFAULT);
예제 #24
0
 /// <summary>
 ///  Draws the text at the specified point, using the given Font, foreColor and backColor.
 ///  CR/LF are honored.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor)
 => DrawText(text, font, pt, foreColor, backColor, User32.DT.DEFAULT);
예제 #25
0
 /// <summary>
 ///  Returns the Size in logical units of the given text using the given Font.
 ///  CR/LF/TAB are taken into account.
 /// </summary>
 public Size MeasureText(string text, WindowsFont font)
 => MeasureText(text, font, MaxSize, User32.TextFormatFlags.DT_BOTTOM);
 public Size MeasureText(string text, WindowsFont font, Size proposedSize, IntTextFormatFlags flags)
 {
     if (string.IsNullOrEmpty(text))
     {
         return Size.Empty;
     }
     IntNativeMethods.DRAWTEXTPARAMS lpDTParams = null;
     if (MeasurementDCInfo.IsMeasurementDC(this.DeviceContext))
     {
         lpDTParams = MeasurementDCInfo.GetTextMargins(this, font);
     }
     if (lpDTParams == null)
     {
         lpDTParams = this.GetTextMargins(font);
     }
     int num = (1 + lpDTParams.iLeftMargin) + lpDTParams.iRightMargin;
     if (proposedSize.Width <= num)
     {
         proposedSize.Width = num;
     }
     if (proposedSize.Height <= 0)
     {
         proposedSize.Height = 1;
     }
     IntNativeMethods.RECT lpRect = IntNativeMethods.RECT.FromXYWH(0, 0, proposedSize.Width, proposedSize.Height);
     HandleRef hDC = new HandleRef(null, this.dc.Hdc);
     if (font != null)
     {
         this.dc.SelectFont(font);
     }
     if ((proposedSize.Height >= MaxSize.Height) && ((flags & IntTextFormatFlags.SingleLine) != IntTextFormatFlags.Default))
     {
         flags &= ~(IntTextFormatFlags.Bottom | IntTextFormatFlags.VerticalCenter);
     }
     if (proposedSize.Width == MaxSize.Width)
     {
         flags &= ~IntTextFormatFlags.WordBreak;
     }
     flags |= IntTextFormatFlags.CalculateRectangle;
     IntUnsafeNativeMethods.DrawTextEx(hDC, text, ref lpRect, (int) flags, lpDTParams);
     return lpRect.Size;
 }
예제 #27
0
 /// <summary>
 ///  Returns the Size in logical units of the given text using the given Font and using the specified rectangle
 ///  as the text bounding box (see overload below for more info).
 ///  TAB/CR/LF are taken into account.
 /// </summary>
 public Size MeasureText(string text, WindowsFont font, Size proposedSize)
 => MeasureText(text, font, proposedSize, User32.TextFormatFlags.DT_BOTTOM);
 public bool IsFontOnContextStack(WindowsFont wf)
 {
     if (this.contextStack != null)
     {
         foreach (GraphicsState state in this.contextStack)
         {
             if (state.hFont == wf.Hfont)
             {
                 return true;
             }
         }
     }
     return false;
 }
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor)
 {
     this.DrawText(text, font, bounds, foreColor, Color.Empty);
 }
 public void RestoreHdc()
 {
     IntUnsafeNativeMethods.RestoreDC(new HandleRef(this, this.hDC), -1);
     if (this.contextStack != null)
     {
         GraphicsState state = (GraphicsState) this.contextStack.Pop();
         this.hCurrentBmp = state.hBitmap;
         this.hCurrentBrush = state.hBrush;
         this.hCurrentPen = state.hPen;
         this.hCurrentFont = state.hFont;
         if ((state.font != null) && state.font.IsAlive)
         {
             this.selectedFont = state.font.Target as WindowsFont;
         }
         else
         {
             WindowsFont selectedFont = this.selectedFont;
             this.selectedFont = null;
             if ((selectedFont != null) && MeasurementDCInfo.IsMeasurementDC(this))
             {
                 selectedFont.Dispose();
             }
         }
     }
     MeasurementDCInfo.ResetIfIsMeasurementDC(this.hDC);
 }
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor)
 {
     this.DrawText(text, font, pt, foreColor, backColor, IntTextFormatFlags.Default);
 }
예제 #32
0
        public static WindowsFont GetWindowsFont(Font font, WindowsFontQuality fontQuality)
        {
            if (font == null)
            {
                return(null);
            }

            // First check if font is in the cache.

            int count = 0;
            int index = currentIndex;

            // Search by index of most recently added object.
            while (count < WindowsFontCache.Count)
            {
                if (WindowsFontCache[index].Key.Equals(font))  // don't do shallow comparison, we could miss cloned fonts.
                {
                    // We got a Font in the cache, let's see if we have a WindowsFont with the same quality as required by the caller.

                    // WARNING: It is not expected that the WindowsFont is disposed externally since it is created by this class.
                    Debug.Assert(WindowsFontCache[index].Value.Hfont != IntPtr.Zero, "Cached WindowsFont was disposed, enable GDI_FINALIZATION_WATCH to track who did it!");

                    WindowsFont wf = WindowsFontCache[index].Value;
                    if (wf.Quality == fontQuality)
                    {
                        return(wf);
                    }
                }

                index--;
                count++;

                if (index < 0)
                {
                    index = CacheSize - 1;
                }
            }

            // Font is not in the cache, let's add it.

            WindowsFont winFont = WindowsFont.FromFont(font, fontQuality);
            KeyValuePair <Font, WindowsFont> newEntry = new KeyValuePair <Font, WindowsFont>(font, winFont);

            currentIndex++;

            if (currentIndex == CacheSize)
            {
                currentIndex = 0;
            }

            if (WindowsFontCache.Count == CacheSize)  // No more room, update current index.
            {
                WindowsFont wfont = null;

                // Go through the existing fonts in the cache, and see if any
                // are not in use by a DC.  If one isn't, replace that.  If
                // all are in use, new up a new font and do not cache it.

                bool finished   = false;
                int  startIndex = currentIndex;
                int  loopIndex  = startIndex + 1;
                while (!finished)
                {
                    if (loopIndex >= CacheSize)
                    {
                        loopIndex = 0;
                    }

                    if (loopIndex == startIndex)
                    {
                        finished = true;
                    }

                    wfont = WindowsFontCache[loopIndex].Value;
                    if (!DeviceContexts.IsFontInUse(wfont))
                    {
                        currentIndex = loopIndex;
                        finished     = true;
                        break;
                    }
                    else
                    {
                        loopIndex++;
                        wfont = null;
                    }
                }

                if (wfont != null)
                {
                    WindowsFontCache[currentIndex] = newEntry;
                    winFont.OwnedByCacheManager    = true;

#if GDI_FONT_CACHE_TRACK
                    Debug.WriteLine("Removing from cache: " + wfont);
                    Debug.WriteLine("Adding to cache: " + winFont);
#endif

                    wfont.OwnedByCacheManager = false;
                    wfont.Dispose();
                }
                else
                {
                    // do not cache font - caller is ALWAYS responsible for
                    // disposing now.  If it is owned  by the CM, it will not
                    // disposed.

                    winFont.OwnedByCacheManager = false;

#if GDI_FONT_CACHE_TRACK
                    Debug.WriteLine("Creating uncached font: " + winFont);
#endif
                }
            }
            else
            {
                winFont.OwnedByCacheManager = true;
                WindowsFontCache.Add(newEntry);

#if GDI_FONT_CACHE_TRACK
                Debug.WriteLine("Adding to cache: " + winFont);
#endif
            }
            return(winFont);
        }
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, IntTextFormatFlags flags)
 {
     this.DrawText(text, font, pt, foreColor, Color.Empty, flags);
 }
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor, Color backColor)
 {
     this.DrawText(text, font, bounds, foreColor, backColor, IntTextFormatFlags.VerticalCenter | IntTextFormatFlags.HorizontalCenter);
 }
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color color, IntTextFormatFlags flags)
 {
     this.DrawText(text, font, bounds, color, Color.Empty, flags);
 }
예제 #36
0
 /// <summary>
 ///  Draws the text at the specified point, using the given Font and foreColor, and according to the
 ///  specified flags.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Interop.User32.TextFormatFlags flags)
 {
     DrawText(text, font, pt, foreColor, Color.Empty, flags);
 }
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor, IntTextFormatFlags flags)
 {
     Rectangle bounds = new Rectangle(pt.X, pt.Y, 0x7fffffff, 0x7fffffff);
     this.DrawText(text, font, bounds, foreColor, backColor, flags);
 }
예제 #38
0
 /// <summary>
 ///  Draws the text centered in the given rectangle and using the given Font, foreColor and backColor.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor, Color backColor)
 {
     DrawText(text, font, bounds, foreColor, backColor, Interop.User32.TextFormatFlags.DT_CENTER | Interop.User32.TextFormatFlags.DT_VCENTER);
 }
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor, Color backColor, IntTextFormatFlags flags)
 {
     if (!string.IsNullOrEmpty(text) && (foreColor != Color.Transparent))
     {
         HandleRef hdc = new HandleRef(this.dc, this.dc.Hdc);
         if (this.dc.TextAlignment != DeviceContextTextAlignment.Top)
         {
             this.dc.SetTextAlignment(DeviceContextTextAlignment.Top);
         }
         if (!foreColor.IsEmpty && (foreColor != this.dc.TextColor))
         {
             this.dc.SetTextColor(foreColor);
         }
         if (font != null)
         {
             this.dc.SelectFont(font);
         }
         DeviceContextBackgroundMode newMode = (backColor.IsEmpty || (backColor == Color.Transparent)) ? DeviceContextBackgroundMode.Transparent : DeviceContextBackgroundMode.Opaque;
         if (this.dc.BackgroundMode != newMode)
         {
             this.dc.SetBackgroundMode(newMode);
         }
         if ((newMode != DeviceContextBackgroundMode.Transparent) && (backColor != this.dc.BackgroundColor))
         {
             this.dc.SetBackgroundColor(backColor);
         }
         IntNativeMethods.DRAWTEXTPARAMS textMargins = this.GetTextMargins(font);
         bounds = AdjustForVerticalAlignment(hdc, text, bounds, flags, textMargins);
         if (bounds.Width == MaxSize.Width)
         {
             bounds.Width -= bounds.X;
         }
         if (bounds.Height == MaxSize.Height)
         {
             bounds.Height -= bounds.Y;
         }
         IntNativeMethods.RECT lpRect = new IntNativeMethods.RECT(bounds);
         IntUnsafeNativeMethods.DrawTextEx(hdc, text, ref lpRect, (int) flags, textMargins);
     }
 }
예제 #40
0
 /// <summary>
 ///  Returns the Size in logical units of the given text using the given Font and using the specified rectangle
 ///  as the text bounding box (see overload below for more info).
 ///  TAB/CR/LF are taken into account.
 /// </summary>
 public Size MeasureText(string text, WindowsFont font, Size proposedSize)
 {
     return(MeasureText(text, font, proposedSize, Interop.User32.TextFormatFlags.DT_BOTTOM));
 }
 public float GetOverhangPadding(WindowsFont font)
 {
     WindowsFont font2 = font;
     if (font2 == null)
     {
         font2 = this.dc.Font;
     }
     float num = ((float) font2.Height) / 6f;
     if (font2 != font)
     {
         font2.Dispose();
     }
     return num;
 }
예제 #42
0
 /// <summary>
 ///  Draws the text centered in the given rectangle and using the given Font and foreColor.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color foreColor)
 => DrawText(text, font, bounds, foreColor, Color.Empty);
 public Size GetTextExtent(string text, WindowsFont font)
 {
     if (string.IsNullOrEmpty(text))
     {
         return Size.Empty;
     }
     IntNativeMethods.SIZE size = new IntNativeMethods.SIZE();
     HandleRef hDC = new HandleRef(null, this.dc.Hdc);
     if (font != null)
     {
         this.dc.SelectFont(font);
     }
     IntUnsafeNativeMethods.GetTextExtentPoint32(hDC, text, size);
     if ((font != null) && !MeasurementDCInfo.IsMeasurementDC(this.dc))
     {
         this.dc.ResetFont();
     }
     return new Size(size.cx, size.cy);
 }
예제 #44
0
 /// <summary>
 ///  Draws the text in the given bounds, using the given Font and foreColor, and according to the specified flags.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Rectangle bounds, Color color, User32.DT flags)
 => DrawText(text, font, bounds, color, Color.Empty, flags);
        public IntNativeMethods.DRAWTEXTPARAMS GetTextMargins(WindowsFont font)
        {
            int leftMargin = 0;
            int rightMargin = 0;
            float overhangPadding = 0f;
            switch (this.TextPadding)
            {
                case TextPaddingOptions.GlyphOverhangPadding:
                    overhangPadding = this.GetOverhangPadding(font);
                    leftMargin = (int) Math.Ceiling((double) overhangPadding);
                    rightMargin = (int) Math.Ceiling((double) (overhangPadding * 1.5f));
                    break;

                case TextPaddingOptions.LeftAndRightPadding:
                    overhangPadding = this.GetOverhangPadding(font);
                    leftMargin = (int) Math.Ceiling((double) (2f * overhangPadding));
                    rightMargin = (int) Math.Ceiling((double) (overhangPadding * 2.5f));
                    break;
            }
            return new IntNativeMethods.DRAWTEXTPARAMS(leftMargin, rightMargin);
        }
예제 #46
0
 /// <summary>
 ///  Returns the Size in logical units of the given text using the given Font.
 ///  CR/LF/TAB are taken into account.
 /// </summary>
 public Size MeasureText(string text, WindowsFont font)
 => MeasureText(text, font, MaxSize, User32.DT.BOTTOM);
 public Size MeasureText(string text, WindowsFont font)
 {
     return this.MeasureText(text, font, MaxSize, IntTextFormatFlags.Default);
 }
예제 #48
0
        /// <summary>
        ///  Returns the Size in logical units of the given text using the given Font, and according to the formatting flags.
        ///  The proposed size is used to create a bounding rectangle as follows:
        ///  - If there are multiple lines of text, DrawText uses the width of the rectangle pointed to by
        ///  the lpRect parameter and extends the base of the rectangle to bound the last line of text.
        ///  - If the largest word is wider than the rectangle, the width is expanded.
        ///  - If the text is less than the width of the rectangle, the width is reduced.
        ///  - If there is only one line of text, DrawText modifies the right side of the rectangle so that
        ///  it bounds the last character in the line.
        ///  If the font is null, the hdc's current font will be used.
        ///
        ///  Note for vertical fonts (if ever supported): DrawTextEx uses GetTextExtentPoint32 for measuring the text and this
        ///  function has the following limitation (from MSDN):
        ///  - This function assumes that the text is horizontal, that is, that the escapement is always 0. This is true for both
        ///  the horizontal and vertical measurements of the text.  The application must convert it explicitly.
        /// </summary>
        public Size MeasureText(string text, WindowsFont font, Size proposedSize, User32.DT flags)
        {
            Debug.Assert(((uint)flags & GdiUnsupportedFlagMask) == 0, "Some custom flags were left over and are not GDI compliant!");

            if (string.IsNullOrEmpty(text))
            {
                return(Size.Empty);
            }

            // DrawText returns a rectangle useful for aligning, but not guaranteed to encompass all
            // pixels (its not a FitBlackBox, if the text is italicized, it will overhang on the right.)
            // So we need to account for this.

#if OPTIMIZED_MEASUREMENTDC
            User32.DRAWTEXTPARAMS dtparams;
            // use the cache if we've got it
            if (MeasurementDCInfo.IsMeasurementDC(DeviceContext))
            {
                dtparams = MeasurementDCInfo.GetTextMargins(this, font);
            }
            else
            {
                dtparams = GetTextMargins(font);
            }
#else
            User32.DRAWTEXTPARAMS dtparams = GetTextMargins(font);
#endif

            // If Width / Height are < 0, we need to make them larger or DrawText will return
            // an unbounded measurement when we actually trying to make it very narrow.
            int minWidth = 1 + dtparams.iLeftMargin + dtparams.iRightMargin;

            if (proposedSize.Width <= minWidth)
            {
                proposedSize.Width = minWidth;
            }
            if (proposedSize.Height <= 0)
            {
                proposedSize.Height = 1;
            }

            var rect = new RECT(0, 0, proposedSize.Width, proposedSize.Height);
            if (font != null)
            {
                DeviceContext.SelectFont(font);
            }

            // If proposedSize.Height >= MaxSize.Height it is assumed bounds needed.  If flags contain SINGLELINE and
            // VCENTER or BOTTOM options, DrawTextEx does not bind the rectangle to the actual text height since
            // it assumes the text is to be vertically aligned; we need to clear the VCENTER and BOTTOM flags to
            // get the actual text bounds.
            if (proposedSize.Height >= MaxSize.Height && (flags & User32.DT.SINGLELINE) != 0)
            {
                // Clear vertical-alignment flags.
                flags &= ~(User32.DT.BOTTOM | User32.DT.VCENTER);
            }

            if (proposedSize.Width == MaxSize.Width)
            {
                // PERF: No constraining width means no word break.
                // in this case, we dont care about word wrapping - there should be enough room to fit it all
                flags &= ~(User32.DT.WORDBREAK);
            }

            flags |= User32.DT.CALCRECT;
            User32.DrawTextExW(DeviceContext.Hdc, text, text.Length, ref rect, flags, ref dtparams);

            return(rect.Size);
        }
 public Size MeasureText(string text, WindowsFont font, Size proposedSize)
 {
     return this.MeasureText(text, font, proposedSize, IntTextFormatFlags.Default);
 }
예제 #50
0
 /// <summary>
 ///  Draws the text at the specified point, using the given Font and foreColor, and according to the
 ///  specified flags.
 /// </summary>
 public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, User32.DT flags)
 => DrawText(text, font, pt, foreColor, Color.Empty, flags);
        internal static IntNativeMethods.DRAWTEXTPARAMS GetTextMargins(WindowsGraphics wg, WindowsFont font)
        {
            CachedInfo cachedMeasurementDCInfo = MeasurementDCInfo.cachedMeasurementDCInfo;

            if (((cachedMeasurementDCInfo == null) || (cachedMeasurementDCInfo.LeftTextMargin <= 0)) || ((cachedMeasurementDCInfo.RightTextMargin <= 0) || (font != cachedMeasurementDCInfo.LastUsedFont)))
            {
                if (cachedMeasurementDCInfo == null)
                {
                    cachedMeasurementDCInfo = new CachedInfo();
                    MeasurementDCInfo.cachedMeasurementDCInfo = cachedMeasurementDCInfo;
                }
                IntNativeMethods.DRAWTEXTPARAMS textMargins = wg.GetTextMargins(font);
                cachedMeasurementDCInfo.LeftTextMargin  = textMargins.iLeftMargin;
                cachedMeasurementDCInfo.RightTextMargin = textMargins.iRightMargin;
            }
            return(new IntNativeMethods.DRAWTEXTPARAMS(cachedMeasurementDCInfo.LeftTextMargin, cachedMeasurementDCInfo.RightTextMargin));
        }