2011-10-20 1 views
3

System.Drawing.Font을 사용하면 글꼴 크기를 변경할 수있는 것처럼 문자 간격을 변경할 수 있습니까?System.Drawing.Font - 문자 간격을 변경 하시겠습니까?

특정 너비에 맞게 글자 간격을 늘리려합니다.

이렇게 할 수 없다면 원하는 효과를 얻을 수있는 대안이 있습니까? 예를 들어, 내 특정 너비에 맞게 여러 그래픽을 쉽게 사용할 수 있습니까?

+0

어디에서이 글꼴을 사용하고 있습니까? 무엇을 사용하고 있습니까? – musefan

+0

'Graphics.DrawString()'이있는 GDI + 이미지에서 사용 중임 – Curt

+0

'System.Drawing'에 조정 된 문자 간격으로 텍스트를 그리는 기본 제공 메커니즘이 없습니다. 이를 위해 코드를 직접 작성해야합니다. 'MeasureCharacterRanges'를보고 시작하십시오. –

답변

4

DrawString을 사용하면 문자 사이의 간격을 상세하게 지정할 수는 없지만 원하는 너비를 기준으로 간격을 계산 한 다음 각 문자를 그려 넣는 도우미 함수를 만들 것이라고 생각합니다.

당신은 아마 문자 당 MeasureString에 하나의 호출을이를 최적화 할 수

public void DrawSpacedText(Graphics g, Font font, Brush brush, PointF point, string text, int desiredWidth) 
    { 
     //Calculate spacing 
     float widthNeeded = 0; 
     foreach (char c in text) 
     { 
      widthNeeded += g.MeasureString(c.ToString(), font).Width; 
     } 
     float spacing = (desiredWidth - widthNeeded)/(text.Length - 1); 

     //draw text 
     float indent = 0; 
     foreach (char c in text) 
     { 
      g.DrawString(c.ToString(), font, brush, new PointF(point.X + indent, point.Y)); 
      indent += g.MeasureString(c.ToString(), font).Width + spacing; 
     } 
    } 

...이 시도하고 당신이 얼마나 참조하십시오.

public void DrawSpacedText(Graphics g, Font font, Brush brush, PointF point, string text, int desiredWidth) 
    { 
     //Calculate spacing 
     float widthNeeded = 0; 
     Region[] regions = g.MeasureCharacterRanges(text, font, new RectangleF(point, new SizeF(desiredWidth, font.Height + 10)), StringFormat.GenericDefault); 
     float[] widths = new float[regions.Length]; 
     for(int i = 0; i < widths.Length; i++) 
     { 
      widths[i] = regions[i].GetBounds(g).Width; 
      widthNeeded += widths[i]; 
     } 
     float spacing = (desiredWidth - widthNeeded)/(text.Length - 1); 

     //draw text 
     float indent = 0; 
     int index = 0; 
     foreach (char c in text) 
     { 
      g.DrawString(c.ToString(), font, brush, new PointF(point.X + indent, point.Y)); 
      indent += widths[index] + spacing; 
      index++; 
     } 
    } 
+2

+1 이것은 좋은 방법입니다. 그러나 일정한 간격의 나사를 사용하면 [텍스트 커닝] (http://en.wikipedia.org/wiki/Kerning)을 제대로 수행하기가 어렵습니다. 다시 말해 위키 피 디아를 인용하기 위해 적절한 커닝을 한 것처럼 결과가 시각적으로 만족스럽지 않을 것입니다. – Groo

+0

이것은 한 문자 === glyph로 가정 할 때 다소 순진한 접근법입니다. 아니 bidi, 아니 ligatures 등등. ASCII 테이블의 아래쪽 절반 만. – olegz

0

이 코드는에 새로운 라인을 지원 ... 여기에 대신 MeasureCharacterRanges를 사용하는 예는 다음과 같습니다 심지어 (I 어쨌든 더 정확 생각) 배열

편집를 얻을 수 MeasureCharacterRanges를 사용 텍스트를 반환하고 Image 객체를 반환합니다.

public static Image ConvertTextToImage(String text, Font font, Color textColor, int spacing = 0) 
{ 
    var textParts = SplitOnBreakLines(text); 
    // dummy image, just create drawing 
    var img = new Bitmap(1, 1); 
    var drawing = Graphics.FromImage(img); 
    // calculate width, height 
    var width = 0.0F; 
    foreach (char c in text) 
    { 
     width += drawing.MeasureString(c.ToString(), font).Width; 
    }   
    width = (width + spacing * (ClearBreakLines(text).Length - 1))/textParts.Length; 
    if (width <= 0) 
     width = 1; 
    var height = font.Height * textParts.Length; 
    // clear and create new objects 
    img.Dispose(); 
    drawing.Dispose(); 

    img = new Bitmap((int)width, (int)height); 
    drawing = Graphics.FromImage(img); 

    //Adjust for high quality 
    drawing.CompositingQuality = CompositingQuality.HighQuality; 
    drawing.InterpolationMode = InterpolationMode.HighQualityBilinear; 
    drawing.PixelOffsetMode = PixelOffsetMode.HighQuality; 
    drawing.SmoothingMode = SmoothingMode.HighQuality; 
    drawing.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; 

    //paint the background 
    drawing.Clear(Color.Transparent); 

    //create a brush for the text 
    var textBrush = new SolidBrush(textColor); 
    //write text 
    var indent = 0.0F; 
    var point = new Point();    
    foreach (var textPart in textParts) 
    { 
     foreach (char c in textPart) 
     { 
      drawing.DrawString(c.ToString(), font, textBrush, new PointF(point.X + indent, point.Y)); 
      indent += drawing.MeasureString(c.ToString(), font).Width + spacing; 
     } 
     indent = 0.0F; 
     point.Y += font.Height; 
    } 
    drawing.Save(); 
    textBrush.Dispose(); 
    drawing.Dispose(); 
    return img;   
} 

public static string ClearBreakLines(string s) 
{ 
    return Regex.Replace(s, @"\r\n?|\n", string.Empty); 
} 

public static string[] SplitOnBreakLines(string s) 
{ 
    return Regex.Split(s, @"\r\n?|\n");   
}