Set eol style
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / TextRenderer.cs
1 //
2 // TextRenderer.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Copyright (c) 2006 Novell, Inc.
24 //
25 // Authors:
26 //      Jonathan Pobst (monkey@jpobst.com)
27 //
28
29 #if NET_2_0
30 using System.Drawing;
31 using System.Runtime.InteropServices;
32 using System.Text;
33 using System.Drawing.Text;
34
35 namespace System.Windows.Forms
36 {
37         public sealed class TextRenderer
38         {
39                 #region Public Methods
40                 [MonoTODO("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
41                 public static void DrawText (IDeviceContext dc, string text, Font font, Rectangle bounds, Color foreColor, TextFormatFlags flags)
42                 {
43                         if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
44                                 Rectangle new_bounds = bounds;
45                                 new_bounds.Offset ((int)(dc as Graphics).Transform.OffsetX + 0, (int)(dc as Graphics).Transform.OffsetY + 0);
46                                 IntPtr hdc = dc.GetHdc ();
47
48                                 SetTextColor (hdc, ColorTranslator.ToWin32 (foreColor));
49                                 SetBkMode (hdc, 1);     //1-Transparent, 2-Opaque
50
51                                 VisualStyles.UXTheme.RECT r = VisualStyles.UXTheme.RECT.FromRectangle (new_bounds);
52
53                                 if (font != null)
54                                         SelectObject (hdc, font.ToHfont ());
55
56                                 DrawText (hdc, text, text.Length, ref r, (int)flags);
57                                 dc.ReleaseHdc ();
58                         }
59                         else {
60                                 Graphics g;
61
62                                 if (dc is Graphics)
63                                         g = (Graphics)dc;
64                                 else
65                                         g = Graphics.FromHdc (dc.GetHdc ());
66
67                                 StringFormat sf = FlagsToStringFormat (flags);
68
69                                 using (Brush b = new SolidBrush (foreColor))
70                                         g.DrawString (text, font, b, bounds, sf);
71
72                                 if (!(dc is Graphics)) {
73                                         g.Dispose ();
74                                         dc.ReleaseHdc ();
75                                 }
76                         }
77                 }
78
79                 [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
80                 public static void DrawText (IDeviceContext dc, string text, Font font, Point pt, Color foreColor, TextFormatFlags flags)
81                 {
82                         if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
83                                 IntPtr hdc = dc.GetHdc ();
84
85                                 SetTextColor (hdc, ColorTranslator.ToWin32 (foreColor));
86                                 SetBkMode (hdc, 1);     //1-Transparent, 2-Opaque
87
88                                 Size sz = MeasureText(text, font);
89                                 
90                                 VisualStyles.UXTheme.RECT r = new System.Windows.Forms.VisualStyles.UXTheme.RECT(pt.X, pt.Y, pt.X + sz.Width, pt.Y + sz.Height);
91
92                                 if (font != null)
93                                         SelectObject (hdc, font.ToHfont ());
94
95                                 DrawText (hdc, text, text.Length, ref r, (int)flags);
96                                 dc.ReleaseHdc ();
97                         }
98                         else {
99                                 Graphics g;
100
101                                 if (dc is Graphics)
102                                         g = (Graphics)dc;
103                                 else
104                                         g = Graphics.FromHdc (dc.GetHdc ());
105
106                                 StringFormat sf = FlagsToStringFormat (flags);
107
108                                 using (Brush b = new SolidBrush (foreColor))
109                                         g.DrawString (text, font, b, pt, sf);
110
111                                 if (!(dc is Graphics)) {
112                                         g.Dispose ();
113                                         dc.ReleaseHdc ();
114                                 }
115                         }
116                 }
117
118                 [MonoTODO ("This should be correct for Windows, other platforms need a more accurate fallback method than the one provided")]
119                 public static Size MeasureText (string text, Font font)
120                 {
121                         if (Environment.OSVersion.Platform == PlatformID.Win32NT || Environment.OSVersion.Platform == PlatformID.Win32Windows) {
122                                 Bitmap b = new Bitmap (5, 5);
123                                 Graphics g = Graphics.FromImage (b);
124                                 
125                                 IntPtr hdc = g.GetHdc ();
126
127                                 if (font != null)
128                                         SelectObject (hdc, font.ToHfont ());
129                                         
130                                 VisualStyles.UXTheme.SIZE text_size = new System.Windows.Forms.VisualStyles.UXTheme.SIZE();
131
132                                 GetTextExtentPoint32 (hdc, text, text.Length, out text_size);
133                                 
134                                 g.ReleaseHdc();
135                                 
136                                 Size retval = text_size.ToSize();
137                                 //retval.Height += 4;
138                                 if (retval.Width > 0) retval.Width += 6;
139                                 return retval;
140                         }
141                         else {
142                                 Bitmap b = new Bitmap (5, 5);
143                                 Graphics g = Graphics.FromImage (b);
144
145                                 Size retval = g.MeasureString(text,font).ToSize();
146                                 if (retval.Width > 0) retval.Width += 6;
147                                 return retval;  
148                         }
149                 }
150                 #endregion
151
152                 #region Private Methods
153                 private static StringFormat FlagsToStringFormat (TextFormatFlags flags)
154                 {
155                         StringFormat sf = new StringFormat ();
156
157                         // Translation table: http://msdn.microsoft.com/msdnmag/issues/06/03/TextRendering/default.aspx?fig=true#fig4
158
159                         // Horizontal Alignment
160                         if ((flags & TextFormatFlags.HorizontalCenter) == TextFormatFlags.HorizontalCenter)
161                                 sf.Alignment = StringAlignment.Center;
162                         else if ((flags & TextFormatFlags.Right) == TextFormatFlags.Right)
163                                 sf.Alignment = StringAlignment.Far;
164                         else
165                                 sf.Alignment = StringAlignment.Near;
166
167                         // Vertical Alignment
168                         if ((flags & TextFormatFlags.Bottom) == TextFormatFlags.Bottom)
169                                 sf.LineAlignment = StringAlignment.Far;
170                         else if ((flags & TextFormatFlags.VerticalCenter) == TextFormatFlags.VerticalCenter)
171                                 sf.LineAlignment = StringAlignment.Center;
172                         else
173                                 sf.LineAlignment = StringAlignment.Near;
174
175                         // Ellipsis
176                         if ((flags & TextFormatFlags.EndEllipsis) == TextFormatFlags.EndEllipsis)
177                                 sf.Trimming = StringTrimming.EllipsisCharacter;
178                         else if ((flags & TextFormatFlags.PathEllipsis) == TextFormatFlags.PathEllipsis)
179                                 sf.Trimming = StringTrimming.EllipsisPath;
180                         else if ((flags & TextFormatFlags.WordEllipsis) == TextFormatFlags.WordEllipsis)
181                                 sf.Trimming = StringTrimming.EllipsisWord;
182                         else
183                                 sf.Trimming = StringTrimming.Character;
184
185                         // Hotkey Prefix
186                         if ((flags & TextFormatFlags.NoPrefix) == TextFormatFlags.NoPrefix)
187                                 sf.HotkeyPrefix = HotkeyPrefix.None;
188                         else if ((flags & TextFormatFlags.HidePrefix) == TextFormatFlags.HidePrefix)
189                                 sf.HotkeyPrefix = HotkeyPrefix.Hide;
190                         else
191                                 sf.HotkeyPrefix = HotkeyPrefix.Show;
192
193                         // Text Padding
194                         if ((flags & TextFormatFlags.NoPadding) == TextFormatFlags.NoPadding)
195                                 sf.FormatFlags |= StringFormatFlags.FitBlackBox;
196
197                         // Text Wrapping
198                         if ((flags & TextFormatFlags.SingleLine) == TextFormatFlags.SingleLine)
199                                 sf.FormatFlags |= StringFormatFlags.NoWrap;
200                         else if ((flags & TextFormatFlags.TextBoxControl) == TextFormatFlags.TextBoxControl)
201                                 sf.FormatFlags |= StringFormatFlags.LineLimit;
202
203                         // Other Flags
204                         if ((flags & TextFormatFlags.RightToLeft) == TextFormatFlags.RightToLeft)
205                                 sf.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
206                         if ((flags & TextFormatFlags.NoClipping) == TextFormatFlags.NoClipping)
207                                 sf.FormatFlags |= StringFormatFlags.NoClip;
208                         sf.FormatFlags |= StringFormatFlags.NoClip;
209
210                         return sf;
211                 }
212                 #endregion
213
214                 #region DllImports (Windows)
215                 [DllImport ("user32", CharSet = CharSet.Unicode)]
216                 static extern int DrawText (IntPtr hdc, string lpStr, int nCount, ref VisualStyles.UXTheme.RECT lpRect, int wFormat);
217
218                 [DllImport ("gdi32")]
219                 static extern int SetTextColor (IntPtr hdc, int crColor);
220
221                 [DllImport ("gdi32")]
222                 private extern static IntPtr SelectObject (IntPtr hDC, IntPtr hObject);
223
224                 [DllImport ("gdi32")]
225                 static extern int SetBkColor (IntPtr hdc, int crColor);
226
227                 [DllImport ("gdi32")]
228                 static extern int SetBkMode (IntPtr hdc, int iBkMode);
229
230                 [DllImport ("gdi32")]
231                 static extern bool GetTextExtentExPoint (IntPtr hdc, string lpszStr, int cchString, int nMaxExtent, IntPtr lpnFit, IntPtr alpDx, out VisualStyles.UXTheme.SIZE lpSize);
232
233                 [DllImport ("gdi32")]
234                 static extern bool GetTextExtentPoint32 (IntPtr hdc, string lpString, int cbString, out VisualStyles.UXTheme.SIZE lpSize);
235                 #endregion
236         }
237
238 }
239 #endif