Browse Source

Use GDI (TextRenderer) instead of GDI+ (DrawString) for text rendering in the text editor.

Fixes SD2-1135: Font width measurement not exact for some fonts

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1893 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
bc52b86150
  1. 2
      src/AddIns/Misc/HighlightingEditor/Project/Src/Nodes/SpanNode.cs
  2. 22
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/DefaultTextEditorProperties.cs
  3. 77
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/FontContainer.cs
  4. 29
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs
  5. 41
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs
  6. 4
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/ITextEditorProperties.cs
  7. 2
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/DrawableLine.cs
  8. 2
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs
  9. 8
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs
  10. 87
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs
  11. 16
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Util/RtfWriter.cs
  12. 2
      src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkNode.cs
  13. 10
      src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/ExportProjectToHtmlDialog.cs
  14. 22
      src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextEditorProperties.cs

2
src/AddIns/Misc/HighlightingEditor/Project/Src/Nodes/SpanNode.cs

@ -281,7 +281,7 @@ namespace ICSharpCode.SharpDevelop.AddIns.HighlightingEditor.Nodes
Properties properties = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties())); Properties properties = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties()));
////samBegin.Font = samEnd.Font = samCont.Font = ParseFont(properties.Get("DefaultFont", new Font("Courier New", 10).ToString())); ////samBegin.Font = samEnd.Font = samCont.Font = ParseFont(properties.Get("DefaultFont", new Font("Courier New", 10).ToString()));
samBegin.Font = samEnd.Font = samCont.Font = FontContainer.DefaultFont; samBegin.Font = samEnd.Font = samCont.Font = ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.SharpDevelopTextEditorProperties.FontContainer.DefaultFont;
nameBox.Text = node.Name; nameBox.Text = node.Name;
ruleBox.Text = node.Rule; ruleBox.Text = node.Rule;

22
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/DefaultTextEditorProperties.cs

@ -23,6 +23,16 @@ namespace ICSharpCode.TextEditor.Document
DocumentSelectionMode documentSelectionMode = DocumentSelectionMode.Normal; DocumentSelectionMode documentSelectionMode = DocumentSelectionMode.Normal;
Encoding encoding = System.Text.Encoding.UTF8; Encoding encoding = System.Text.Encoding.UTF8;
BracketMatchingStyle bracketMatchingStyle = BracketMatchingStyle.After; BracketMatchingStyle bracketMatchingStyle = BracketMatchingStyle.After;
FontContainer fontContainer;
static Font DefaultFont;
public DefaultTextEditorProperties()
{
if (DefaultFont == null) {
DefaultFont = new Font("Courier New", 10);
}
this.fontContainer = new FontContainer(DefaultFont);
}
bool allowCaretBeyondEOL = false; bool allowCaretBeyondEOL = false;
@ -270,10 +280,16 @@ namespace ICSharpCode.TextEditor.Document
public Font Font { public Font Font {
get { get {
return FontContainer.DefaultFont; return fontContainer.DefaultFont;
} }
set { set {
FontContainer.DefaultFont = value; fontContainer.DefaultFont = value;
}
}
public FontContainer FontContainer {
get {
return fontContainer;
} }
} }
@ -293,6 +309,6 @@ namespace ICSharpCode.TextEditor.Document
set { set {
useCustomLine = value; useCustomLine = value;
} }
} }
} }
} }

77
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/FontContainer.cs

@ -23,77 +23,88 @@ namespace ICSharpCode.TextEditor.Document
/// </summary> /// </summary>
public class FontContainer public class FontContainer
{ {
static Font defaultfont = null; Font defaultFont;
static Font boldfont = null; Font regularfont, boldfont, italicfont, bolditalicfont;
static Font italicfont = null;
static Font bolditalicfont = null;
/// <value> /// <value>
/// The bold version of the base font /// The scaled, bold version of the base font
/// </value> /// </value>
public static Font BoldFont { public Font RegularFont {
get {
return regularfont;
}
}
/// <value>
/// The scaled, bold version of the base font
/// </value>
public Font BoldFont {
get { get {
Debug.Assert(boldfont != null, "ICSharpCode.TextEditor.Document.FontContainer : boldfont == null");
return boldfont; return boldfont;
} }
} }
/// <value> /// <value>
/// The italic version of the base font /// The scaled, italic version of the base font
/// </value> /// </value>
public static Font ItalicFont { public Font ItalicFont {
get { get {
Debug.Assert(italicfont != null, "ICSharpCode.TextEditor.Document.FontContainer : italicfont == null");
return italicfont; return italicfont;
} }
} }
/// <value> /// <value>
/// The bold/italic version of the base font /// The scaled, bold/italic version of the base font
/// </value> /// </value>
public static Font BoldItalicFont { public Font BoldItalicFont {
get { get {
Debug.Assert(bolditalicfont != null, "ICSharpCode.TextEditor.Document.FontContainer : bolditalicfont == null");
return bolditalicfont; return bolditalicfont;
} }
} }
static float twipsPerPixelY;
public static float TwipsPerPixelY {
get {
if (twipsPerPixelY == 0) {
using (Bitmap bmp = new Bitmap(1,1)) {
using (Graphics g = Graphics.FromImage(bmp)) {
twipsPerPixelY = 1440 / g.DpiY;
}
}
}
return twipsPerPixelY;
}
}
/// <value> /// <value>
/// The base font /// The base font
/// </value> /// </value>
public static Font DefaultFont { public Font DefaultFont {
get { get {
return defaultfont; return defaultFont;
} }
set { set {
////// Alex: free resources properly // 1440 twips is one inch
// if (defaultfont!=null) defaultfont.Dispose(); int pixelSize = (int)(value.SizeInPoints * 20 / TwipsPerPixelY);
defaultfont = value;
// if (boldfont!=null) boldfont.Dispose(); defaultFont = value;
boldfont = new Font(defaultfont, FontStyle.Bold); regularfont = new Font(value.FontFamily, pixelSize * TwipsPerPixelY / 20f, FontStyle.Regular);
// if (italicfont!=null) italicfont.Dispose(); boldfont = new Font(regularfont, FontStyle.Bold);
italicfont = new Font(defaultfont, FontStyle.Italic); italicfont = new Font(regularfont, FontStyle.Italic);
// if (bolditalicfont!=null) bolditalicfont.Dispose(); bolditalicfont = new Font(regularfont, FontStyle.Bold | FontStyle.Italic);
bolditalicfont = new Font(defaultfont, FontStyle.Bold | FontStyle.Italic);
} }
} }
// static void CheckFontChange(object sender, PropertyEventArgs e)
// {
// if (e.Key == "DefaultFont") {
// DefaultFont = ParseFont(e.NewValue.ToString());
// }
// }
public static Font ParseFont(string font) public static Font ParseFont(string font)
{ {
string[] descr = font.Split(new char[]{',', '='}); string[] descr = font.Split(new char[]{',', '='});
return new Font(descr[1], Single.Parse(descr[3])); return new Font(descr[1], Single.Parse(descr[3]));
} }
static FontContainer() public FontContainer(Font defaultFont)
{ {
DefaultFont = new Font("Courier New", 10); this.DefaultFont = defaultFont;
} }
} }
} }

29
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs

@ -18,7 +18,7 @@ using System.Xml;
namespace ICSharpCode.TextEditor.Document namespace ICSharpCode.TextEditor.Document
{ {
/// <summary> /// <summary>
/// A color used for highlighting /// A color used for highlighting
/// </summary> /// </summary>
public class HighlightColor public class HighlightColor
{ {
@ -94,21 +94,20 @@ namespace ICSharpCode.TextEditor.Document
/// <value> /// <value>
/// The font used /// The font used
/// </value> /// </value>
public Font Font { public Font GetFont(FontContainer fontContainer)
get { {
if (Bold) { if (Bold) {
return Italic ? FontContainer.BoldItalicFont : FontContainer.BoldFont; return Italic ? fontContainer.BoldItalicFont : fontContainer.BoldFont;
}
return Italic ? FontContainer.ItalicFont : FontContainer.DefaultFont;
} }
return Italic ? fontContainer.ItalicFont : fontContainer.RegularFont;
} }
Color ParseColorString(string colorName) Color ParseColorString(string colorName)
{ {
string[] cNames = colorName.Split('*'); string[] cNames = colorName.Split('*');
PropertyInfo myPropInfo = typeof(System.Drawing.SystemColors).GetProperty(cNames[0], BindingFlags.Public | PropertyInfo myPropInfo = typeof(System.Drawing.SystemColors).GetProperty(cNames[0], BindingFlags.Public |
BindingFlags.Instance | BindingFlags.Instance |
BindingFlags.Static); BindingFlags.Static);
Color c = (Color)myPropInfo.GetValue(null, null); Color c = (Color)myPropInfo.GetValue(null, null);
if (cNames.Length == 2) { if (cNames.Length == 2) {
@ -247,7 +246,7 @@ namespace ICSharpCode.TextEditor.Document
this.systemColor = true; this.systemColor = true;
systemColorName = systemColor; systemColorName = systemColor;
systemBgColor = true; systemBgColor = true;
systemBgColorName = systemBackgroundColor; systemBgColorName = systemBackgroundColor;
@ -275,10 +274,10 @@ namespace ICSharpCode.TextEditor.Document
/// </summary> /// </summary>
public override string ToString() public override string ToString()
{ {
return "[HighlightColor: Bold = " + Bold + return "[HighlightColor: Bold = " + Bold +
", Italic = " + Italic + ", Italic = " + Italic +
", Color = " + Color + ", Color = " + Color +
", BackgroundColor = " + BackgroundColor + "]"; ", BackgroundColor = " + BackgroundColor + "]";
} }
} }
} }

41
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs

@ -43,10 +43,9 @@ namespace ICSharpCode.TextEditor.Document
base.SyntaxColor = color; base.SyntaxColor = color;
} }
public override Font Font { public override Font GetFont(FontContainer fontContainer)
get { {
return null; return null;
}
} }
public override TextWordType Type { public override TextWordType Type {
@ -73,10 +72,9 @@ namespace ICSharpCode.TextEditor.Document
base.SyntaxColor = color; base.SyntaxColor = color;
} }
public override Font Font { public override Font GetFont(FontContainer fontContainer)
get { {
return null; return null;
}
} }
public override TextWordType Type { public override TextWordType Type {
@ -160,10 +158,9 @@ namespace ICSharpCode.TextEditor.Document
} }
} }
public virtual Font Font { public virtual Font GetFont(FontContainer fontContainer)
get { {
return color.Font; return color.GetFont(fontContainer);
}
} }
public Color Color { public Color Color {
@ -175,6 +172,24 @@ namespace ICSharpCode.TextEditor.Document
} }
} }
public bool Bold {
get {
if (color == null)
return false;
else
return color.Bold;
}
}
public bool Italic {
get {
if (color == null)
return false;
else
return color.Italic;
}
}
public HighlightColor SyntaxColor { public HighlightColor SyntaxColor {
get { get {
return color; return color;
@ -215,7 +230,7 @@ namespace ICSharpCode.TextEditor.Document
/// </summary> /// </summary>
public override string ToString() public override string ToString()
{ {
return "[TextWord: Word = " + Word + ", Font = " + Font + ", Color = " + Color + "]"; return "[TextWord: Word = " + Word + ", Color = " + Color + "]";
} }
} }
} }

4
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/ITextEditorProperties.cs

@ -148,6 +148,10 @@ namespace ICSharpCode.TextEditor.Document
set; set;
} }
FontContainer FontContainer {
get;
}
BracketMatchingStyle BracketMatchingStyle { // is wrapped in text editor control BracketMatchingStyle BracketMatchingStyle { // is wrapped in text editor control
get; get;
set; set;

2
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/DrawableLine.cs

@ -53,7 +53,7 @@ namespace ICSharpCode.TextEditor
} else if (word.Type == TextWordType.Tab) { } else if (word.Type == TextWordType.Tab) {
words.Add(SimpleTextWord.Tab); words.Add(SimpleTextWord.Tab);
} else { } else {
words.Add(new SimpleTextWord(TextWordType.Word, word.Word, word.Font.Bold, word.Color)); words.Add(new SimpleTextWord(TextWordType.Word, word.Word, word.Bold, word.Color));
} }
} }
} else { } else {

2
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs

@ -84,7 +84,7 @@ namespace ICSharpCode.TextEditor
if (curLine < textArea.Document.TotalNumberOfLines) { if (curLine < textArea.Document.TotalNumberOfLines) {
g.DrawString((curLine + 1).ToString(), g.DrawString((curLine + 1).ToString(),
lineNumberPainterColor.Font, lineNumberPainterColor.GetFont(TextEditorProperties.FontContainer),
drawBrush, drawBrush,
backgroundRectangle, backgroundRectangle,
numberStringFormat); numberStringFormat);

8
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs

@ -312,6 +312,7 @@ namespace ICSharpCode.TextEditor
float fontHeight = Font.GetHeight(g); float fontHeight = Font.GetHeight(g);
// bool gotNonWhitespace = false; // bool gotNonWhitespace = false;
curTabIndent = 0; curTabIndent = 0;
FontContainer fontContainer = TextEditorProperties.FontContainer;
foreach (TextWord word in line.Words) { foreach (TextWord word in line.Words) {
switch (word.Type) { switch (word.Type) {
case TextWordType.Space: case TextWordType.Space:
@ -331,7 +332,7 @@ namespace ICSharpCode.TextEditor
// gotNonWhitespace = true; // gotNonWhitespace = true;
// curTabIndent += TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' '); // curTabIndent += TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' ');
// } // }
SizeF drawingSize = g.MeasureString(word.Word, word.Font, new SizeF(maxWidth, fontHeight * 100), printingStringFormat); SizeF drawingSize = g.MeasureString(word.Word, word.GetFont(fontContainer), new SizeF(maxWidth, fontHeight * 100), printingStringFormat);
Advance(ref xPos, ref yPos, maxWidth, drawingSize.Width, fontHeight); Advance(ref xPos, ref yPos, maxWidth, drawingSize.Width, fontHeight);
break; break;
} }
@ -346,6 +347,7 @@ namespace ICSharpCode.TextEditor
// bool gotNonWhitespace = false; // bool gotNonWhitespace = false;
curTabIndent = 0 ; curTabIndent = 0 ;
FontContainer fontContainer = TextEditorProperties.FontContainer;
foreach (TextWord word in line.Words) { foreach (TextWord word in line.Words) {
switch (word.Type) { switch (word.Type) {
case TextWordType.Space: case TextWordType.Space:
@ -365,8 +367,8 @@ namespace ICSharpCode.TextEditor
// gotNonWhitespace = true; // gotNonWhitespace = true;
// curTabIndent += TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' '); // curTabIndent += TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' ');
// } // }
g.DrawString(word.Word, word.Font, BrushRegistry.GetBrush(word.Color), xPos + margin.X, yPos); g.DrawString(word.Word, word.GetFont(fontContainer), BrushRegistry.GetBrush(word.Color), xPos + margin.X, yPos);
SizeF drawingSize = g.MeasureString(word.Word, word.Font, new SizeF(margin.Width, fontHeight * 100), printingStringFormat); SizeF drawingSize = g.MeasureString(word.Word, word.GetFont(fontContainer), new SizeF(margin.Width, fontHeight * 100), printingStringFormat);
Advance(ref xPos, ref yPos, margin.Width, drawingSize.Width, fontHeight); Advance(ref xPos, ref yPos, margin.Width, drawingSize.Width, fontHeight);
break; break;
} }

87
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs

@ -33,14 +33,14 @@ namespace ICSharpCode.TextEditor
{ {
int fontHeight; int fontHeight;
//Hashtable charWitdh = new Hashtable(); //Hashtable charWitdh = new Hashtable();
StringFormat measureStringFormat = (StringFormat)StringFormat.GenericTypographic.Clone(); //StringFormat measureStringFormat = (StringFormat)StringFormat.GenericTypographic.Clone();
Highlight highlight; Highlight highlight;
int physicalColumn = 0; // used for calculating physical column during paint int physicalColumn = 0; // used for calculating physical column during paint
public void Dispose() public void Dispose()
{ {
measureCache.Clear(); measureCache.Clear();
measureStringFormat.Dispose(); //measureStringFormat.Dispose();
} }
public Highlight Highlight { public Highlight Highlight {
@ -101,11 +101,11 @@ namespace ICSharpCode.TextEditor
public TextView(TextArea textArea) : base(textArea) public TextView(TextArea textArea) : base(textArea)
{ {
measureStringFormat.LineAlignment = StringAlignment.Near; /*measureStringFormat.LineAlignment = StringAlignment.Near;
measureStringFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | measureStringFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces |
StringFormatFlags.FitBlackBox | StringFormatFlags.FitBlackBox |
StringFormatFlags.NoWrap | StringFormatFlags.NoWrap |
StringFormatFlags.NoClip; StringFormatFlags.NoClip;*/
base.Cursor = Cursors.IBeam; base.Cursor = Cursors.IBeam;
OptionsChanged(); OptionsChanged();
@ -113,8 +113,9 @@ namespace ICSharpCode.TextEditor
static int GetFontHeight(Font font) static int GetFontHeight(Font font)
{ {
int h = font.Height; int height1 = TextRenderer.MeasureText("_", font).Height;
return (h < 16) ? h + 1 : h; int height2 = (int)Math.Ceiling(font.GetHeight());
return Math.Max(height1, height2) + 1;
} }
float spaceWidth; float spaceWidth;
@ -145,9 +146,9 @@ namespace ICSharpCode.TextEditor
public void OptionsChanged() public void OptionsChanged()
{ {
this.lastFont = TextEditorProperties.Font; this.lastFont = TextEditorProperties.FontContainer.RegularFont;
this.fontHeight = GetFontHeight(lastFont); this.fontHeight = GetFontHeight(lastFont);
// use mininum width - in some fonts, space has no width but kerning is used instead // use minimum width - in some fonts, space has no width but kerning is used instead
// -> DivideByZeroException // -> DivideByZeroException
this.spaceWidth = Math.Max(GetWidth(' ', lastFont), 1); this.spaceWidth = Math.Max(GetWidth(' ', lastFont), 1);
// tab should have the width of 4*'x' // tab should have the width of 4*'x'
@ -162,7 +163,7 @@ namespace ICSharpCode.TextEditor
} }
// Just to ensure that fontHeight and char widths are always correct... // Just to ensure that fontHeight and char widths are always correct...
if (lastFont != TextEditorProperties.Font) { if (lastFont != TextEditorProperties.FontContainer.RegularFont) {
OptionsChanged(); OptionsChanged();
base.TextArea.BeginInvoke(new MethodInvoker(base.TextArea.Refresh)); base.TextArea.BeginInvoke(new MethodInvoker(base.TextArea.Refresh));
} }
@ -307,11 +308,11 @@ namespace ICSharpCode.TextEditor
g.FillRectangle(backgroundBrush, rect); g.FillRectangle(backgroundBrush, rect);
physicalColumn += text.Length; physicalColumn += text.Length;
g.DrawString(text, DrawString(g,
textArea.Font, text,
BrushRegistry.GetBrush(drawSelected ? selectionColor.Color : Color.Gray), textArea.Font,
rect, drawSelected ? selectionColor.Color : Color.Gray,
measureStringFormat); rect.X, rect.Y);
g.DrawRectangle(BrushRegistry.GetPen(drawSelected ? Color.DarkGray : Color.Gray), rect.X, rect.Y, rect.Width, rect.Height); g.DrawRectangle(BrushRegistry.GetPen(drawSelected ? Color.DarkGray : Color.Gray), rect.X, rect.Y, rect.Width, rect.Height);
// Bugfix for the problem - of overdrawn right rectangle lines. // Bugfix for the problem - of overdrawn right rectangle lines.
@ -411,6 +412,7 @@ namespace ICSharpCode.TextEditor
TextWord currentWord; TextWord currentWord;
TextWord nextCurrentWord = null; TextWord nextCurrentWord = null;
FontContainer fontContainer = TextEditorProperties.FontContainer;
for (int wordIdx = 0; wordIdx < currentLine.Words.Count; wordIdx++) { for (int wordIdx = 0; wordIdx < currentLine.Words.Count; wordIdx++) {
currentWord = currentLine.Words[wordIdx]; currentWord = currentLine.Words[wordIdx];
if (currentWordOffset < startColumn) { if (currentWordOffset < startColumn) {
@ -534,7 +536,7 @@ namespace ICSharpCode.TextEditor
float wordWidth = DrawDocumentWord(g, float wordWidth = DrawDocumentWord(g,
currentWord.Word, currentWord.Word,
new Point((int)physicalXPos, lineRectangle.Y), new Point((int)physicalXPos, lineRectangle.Y),
currentWord.Font, currentWord.GetFont(fontContainer),
wordForeColor, wordForeColor,
wordBackBrush); wordBackBrush);
wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, wordWidth, lineRectangle.Height); wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, wordWidth, lineRectangle.Height);
@ -598,12 +600,12 @@ namespace ICSharpCode.TextEditor
g.FillRectangle(backBrush, //num == 0 ? Brushes.LightBlue : num == 1 ? Brushes.LightGreen : Brushes.Yellow, g.FillRectangle(backBrush, //num == 0 ? Brushes.LightBlue : num == 1 ? Brushes.LightGreen : Brushes.Yellow,
new RectangleF(position.X, position.Y, (float)Math.Ceiling(wordWidth + 1), FontHeight)); new RectangleF(position.X, position.Y, (float)Math.Ceiling(wordWidth + 1), FontHeight));
g.DrawString(word, DrawString(g,
font, word,
BrushRegistry.GetBrush(foreColor), font,
position.X, foreColor,
position.Y, position.X,
measureStringFormat); position.Y);
return wordWidth; return wordWidth;
} }
@ -625,15 +627,15 @@ namespace ICSharpCode.TextEditor
} }
} }
Dictionary<WordFontPair, float> measureCache = new Dictionary<WordFontPair, float>(); Dictionary<WordFontPair, int> measureCache = new Dictionary<WordFontPair, int>();
// split words after 1000 characters. Fixes GDI+ crash on very longs words, for example // split words after 1000 characters. Fixes GDI+ crash on very longs words, for example
// a 100 KB Base64-file without any line breaks. // a 100 KB Base64-file without any line breaks.
const int MaximumWordLength = 1000; const int MaximumWordLength = 1000;
float MeasureStringWidth(Graphics g, string word, Font font) int MeasureStringWidth(Graphics g, string word, Font font)
{ {
float width; int width;
if (word == null || word.Length == 0) if (word == null || word.Length == 0)
return 0; return 0;
@ -659,15 +661,12 @@ namespace ICSharpCode.TextEditor
// txt.GetPositionFromCharIndex(txt.SelectionStart) // txt.GetPositionFromCharIndex(txt.SelectionStart)
// (Verdana 10, highlighting makes GetP... bold) -> note the space between 'x' and '(' // (Verdana 10, highlighting makes GetP... bold) -> note the space between 'x' and '('
// this also fixes "jumping" characters when selecting in non-monospace fonts // this also fixes "jumping" characters when selecting in non-monospace fonts
Rectangle rect = new Rectangle(0, 0, 32768, 1000); width = TextRenderer.MeasureText(g, word, font, new Size(short.MaxValue, short.MaxValue), textFormatFlags).Width;
CharacterRange[] ranges = { new CharacterRange(0, word.Length) };
Region[] regions = new Region[1];
measureStringFormat.SetMeasurableCharacterRanges (ranges);
regions = g.MeasureCharacterRanges (word, font, rect, measureStringFormat);
width = regions[0].GetBounds(g).Right;
measureCache.Add(new WordFontPair(word, font), width); measureCache.Add(new WordFontPair(word, font), width);
return width; return width;
} }
const TextFormatFlags textFormatFlags = TextFormatFlags.NoPadding | TextFormatFlags.NoPrefix;
#endregion #endregion
#region Conversion Functions #region Conversion Functions
@ -803,7 +802,7 @@ namespace ICSharpCode.TextEditor
paintPos += (column - oldColumn) * spaceWidth; paintPos += (column - oldColumn) * spaceWidth;
break; break;
default: default:
paintPos += GetWidth(ch, TextEditorProperties.Font); paintPos += GetWidth(ch, TextEditorProperties.FontContainer.RegularFont);
++column; ++column;
break; break;
} }
@ -877,7 +876,7 @@ namespace ICSharpCode.TextEditor
paintPos += (column - oldColumn) * WideSpaceWidth; paintPos += (column - oldColumn) * WideSpaceWidth;
break; break;
default: default:
paintPos += GetWidth(ch, TextEditorProperties.Font); paintPos += GetWidth(ch, TextEditorProperties.FontContainer.RegularFont);
++column; ++column;
break; break;
} }
@ -905,6 +904,7 @@ namespace ICSharpCode.TextEditor
if (words == null) return 0; if (words == null) return 0;
int wordCount = words.Count; int wordCount = words.Count;
int wordOffset = 0; int wordOffset = 0;
FontContainer fontContainer = TextEditorProperties.FontContainer;
for (int i = 0; i < wordCount; i++) { for (int i = 0; i < wordCount; i++) {
TextWord word = words[i]; TextWord word = words[i];
if (wordOffset >= end) if (wordOffset >= end)
@ -924,7 +924,7 @@ namespace ICSharpCode.TextEditor
int wordStart = Math.Max(wordOffset, start); int wordStart = Math.Max(wordOffset, start);
int wordLength = Math.Min(wordOffset + word.Length, end) - wordStart; int wordLength = Math.Min(wordOffset + word.Length, end) - wordStart;
string text = Document.GetText(currentLine.Offset + wordStart, wordLength); string text = Document.GetText(currentLine.Offset + wordStart, wordLength);
drawingPos += MeasureStringWidth(g, text, word.Font ?? TextEditorProperties.Font); drawingPos += MeasureStringWidth(g, text, word.GetFont(fontContainer) ?? fontContainer.RegularFont);
break; break;
} }
wordOffset += word.Length; wordOffset += word.Length;
@ -1023,7 +1023,7 @@ namespace ICSharpCode.TextEditor
drawingPos += CountColumns(ref column, foldEnd, f.StartColumn, f.StartLine, g); drawingPos += CountColumns(ref column, foldEnd, f.StartColumn, f.StartLine, g);
foldEnd = f.EndColumn; foldEnd = f.EndColumn;
column += f.FoldText.Length; column += f.FoldText.Length;
drawingPos += MeasureStringWidth(g, f.FoldText, TextEditorProperties.Font); drawingPos += MeasureStringWidth(g, f.FoldText, TextEditorProperties.FontContainer.RegularFont);
} }
drawingPos += CountColumns(ref column, foldEnd, logicalColumn, logicalLine, g); drawingPos += CountColumns(ref column, foldEnd, logicalColumn, logicalLine, g);
g.Dispose(); g.Dispose();
@ -1038,33 +1038,38 @@ namespace ICSharpCode.TextEditor
g.DrawRectangle(Pens.Blue, rect); g.DrawRectangle(Pens.Blue, rect);
} }
void DrawString(Graphics g, string text, Font font, Color color, float x, float y)
{
TextRenderer.DrawText(g, text, font, new Point((int)x, (int)y), color, textFormatFlags);
}
void DrawInvalidLineMarker(Graphics g, float x, float y) void DrawInvalidLineMarker(Graphics g, float x, float y)
{ {
HighlightColor invalidLinesColor = textArea.Document.HighlightingStrategy.GetColorFor("InvalidLines"); HighlightColor invalidLinesColor = textArea.Document.HighlightingStrategy.GetColorFor("InvalidLines");
g.DrawString("~", invalidLinesColor.Font, BrushRegistry.GetBrush(invalidLinesColor.Color), x, y, measureStringFormat); DrawString(g, "~", invalidLinesColor.GetFont(TextEditorProperties.FontContainer), invalidLinesColor.Color, x, y);
} }
void DrawSpaceMarker(Graphics g, Color color, float x, float y) void DrawSpaceMarker(Graphics g, Color color, float x, float y)
{ {
HighlightColor spaceMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("SpaceMarkers"); HighlightColor spaceMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("SpaceMarkers");
g.DrawString("\u00B7", spaceMarkerColor.Font, BrushRegistry.GetBrush(color), x, y, measureStringFormat); DrawString(g, "\u00B7", spaceMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y);
} }
void DrawTabMarker(Graphics g, Color color, float x, float y) void DrawTabMarker(Graphics g, Color color, float x, float y)
{ {
HighlightColor tabMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("TabMarkers"); HighlightColor tabMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("TabMarkers");
g.DrawString("\u00BB", tabMarkerColor.Font, BrushRegistry.GetBrush(color), x, y, measureStringFormat); DrawString(g, "\u00BB", tabMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y);
} }
float DrawEOLMarker(Graphics g, Color color, Brush backBrush, float x, float y) float DrawEOLMarker(Graphics g, Color color, Brush backBrush, float x, float y)
{ {
float width = GetWidth('\u00B6', TextEditorProperties.Font); HighlightColor eolMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("EOLMarkers");
float width = GetWidth('\u00B6', eolMarkerColor.GetFont(TextEditorProperties.FontContainer));
g.FillRectangle(backBrush, g.FillRectangle(backBrush,
new RectangleF(x, y, width, fontHeight)); new RectangleF(x, y, width, fontHeight));
HighlightColor eolMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("EOLMarkers"); DrawString(g, "\u00B6", eolMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y);
g.DrawString("\u00B6", eolMarkerColor.Font, BrushRegistry.GetBrush(color), x, y, measureStringFormat);
return width; return width;
} }

16
src/Libraries/ICSharpCode.TextEditor/Project/Src/Util/RtfWriter.cs

@ -51,7 +51,7 @@ namespace ICSharpCode.TextEditor.Util
static void BuildFontTable(IDocument doc, StringBuilder rtf) static void BuildFontTable(IDocument doc, StringBuilder rtf)
{ {
rtf.Append(@"{\fonttbl"); rtf.Append(@"{\fonttbl");
rtf.Append(@"{\f0\fmodern\fprq1\fcharset0 " + FontContainer.DefaultFont.Name + ";}"); rtf.Append(@"{\f0\fmodern\fprq1\fcharset0 " + doc.TextEditorProperties.Font.Name + ";}");
rtf.Append("}"); rtf.Append("}");
} }
@ -107,28 +107,28 @@ namespace ICSharpCode.TextEditor.Util
escapeSequence = true; escapeSequence = true;
} }
if (oldItalic != word.Font.Italic) { if (oldItalic != word.Italic) {
if (word.Font.Italic) { if (word.Italic) {
rtf.Append(@"\i"); rtf.Append(@"\i");
} else { } else {
rtf.Append(@"\i0"); rtf.Append(@"\i0");
} }
oldItalic = word.Font.Italic; oldItalic = word.Italic;
escapeSequence = true; escapeSequence = true;
} }
if (oldBold != word.Font.Bold) { if (oldBold != word.Bold) {
if (word.Font.Bold) { if (word.Bold) {
rtf.Append(@"\b"); rtf.Append(@"\b");
} else { } else {
rtf.Append(@"\b0"); rtf.Append(@"\b0");
} }
oldBold = word.Font.Bold; oldBold = word.Bold;
escapeSequence = true; escapeSequence = true;
} }
if (firstLine) { if (firstLine) {
rtf.Append(@"\f0\fs" + (FontContainer.DefaultFont.Size * 2)); rtf.Append(@"\f0\fs" + (textArea.TextEditorProperties.Font.Size * 2));
firstLine = false; firstLine = false;
} }
if (escapeSequence) { if (escapeSequence) {

2
src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkNode.cs

@ -133,7 +133,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
xPos += DrawDocumentWord(g, xPos += DrawDocumentWord(g,
word.Word, word.Word,
new PointF(xPos, yPos), new PointF(xPos, yPos),
word.Font.Style == FontStyle.Bold ? BoldMonospacedFont : MonospacedFont, word.Bold ? BoldMonospacedFont : MonospacedFont,
GetTextColor(state, word.Color) GetTextColor(state, word.Color)
); );
logicalX += word.Word.Length; logicalX += word.Word.Length;

10
src/Main/Base/Project/Src/TextEditor/Gui/Dialogs/ExportProjectToHtmlDialog.cs

@ -248,16 +248,16 @@ namespace ICSharpCode.SharpDevelop.Gui
Color c = word.Color; Color c = word.Color;
string colorstr = c.R + ", " + c.G + ", " + c.B; string colorstr = c.R + ", " + c.G + ", " + c.B;
if (word.Font.Italic) { if (word.Italic) {
colorstr = "i" + colorstr; colorstr = "i" + colorstr;
} }
if (word.Font.Bold) { if (word.Bold) {
colorstr = "b" + colorstr; colorstr = "b" + colorstr;
} }
if (Spans[colorstr] == null) { if (Spans[colorstr] == null) {
Spans[colorstr] = "span" + ++curSpanNumber; Spans[colorstr] = "span" + ++curSpanNumber;
} }
bool newColor = c != curColor || oldItalic != word.Font.Italic || oldBold != word.Font.Bold; bool newColor = c != curColor || oldItalic != word.Italic || oldBold != word.Bold;
if (newColor) { if (newColor) {
if (!firstSpan) { if (!firstSpan) {
curFileStream.Write("</span>" ); curFileStream.Write("</span>" );
@ -271,8 +271,8 @@ namespace ICSharpCode.SharpDevelop.Gui
if (newColor) { if (newColor) {
curColor = c; curColor = c;
oldItalic = word.Font.Italic; oldItalic = word.Italic;
oldBold = word.Font.Bold; oldBold = word.Bold;
} }
break; break;
} }

22
src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextEditorProperties.cs

@ -17,20 +17,20 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
{ {
public class SharpDevelopTextEditorProperties : ITextEditorProperties public class SharpDevelopTextEditorProperties : ITextEditorProperties
{ {
static static Properties properties;
Properties properties; static FontContainer fontContainer;
static SharpDevelopTextEditorProperties() static SharpDevelopTextEditorProperties()
{ {
Properties properties2 = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties())); Properties properties2 = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties()));
FontContainer.DefaultFont = FontContainer.ParseFont(properties2.Get("DefaultFont", ResourceService.DefaultMonospacedFont.ToString())); fontContainer = new FontContainer(FontContainer.ParseFont(properties2.Get("DefaultFont", ResourceService.DefaultMonospacedFont.ToString())));
properties2.PropertyChanged += new PropertyChangedEventHandler(CheckFontChange); properties2.PropertyChanged += new PropertyChangedEventHandler(CheckFontChange);
} }
static void CheckFontChange(object sender, PropertyChangedEventArgs e) static void CheckFontChange(object sender, PropertyChangedEventArgs e)
{ {
if (e.Key == "DefaultFont") { if (e.Key == "DefaultFont") {
FontContainer.DefaultFont = FontContainer.ParseFont(e.NewValue.ToString()); fontContainer.DefaultFont = FontContainer.ParseFont(e.NewValue.ToString());
} }
} }
@ -274,11 +274,21 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
public Font Font { public Font Font {
get { get {
return FontContainer.DefaultFont; return fontContainer.DefaultFont;
} }
set { set {
properties.Set("DefaultFont", value.ToString()); properties.Set("DefaultFont", value.ToString());
FontContainer.DefaultFont = value; fontContainer.DefaultFont = value;
}
}
FontContainer ITextEditorProperties.FontContainer {
get {
return fontContainer;
}
}
public static FontContainer FontContainer {
get {
return fontContainer;
} }
} }

Loading…
Cancel
Save