SharpDx:设置字符宽度
SharpDx: Setting character width
我正在使用 SharpDX 编写 C# Direct2D 应用程序,但是我可以理解 answers/examples C++ 中提供的内容。
我想渲染文本并更改某些字符的宽度以使其看起来像图片:
字母B扩大到200%,字母D缩小到50%
在下面的代码中,我绘制了字形的几何图形
所以可以改变几何体的宽度
但这不是一个好的解决方案,因为几何绘图会像您在图片中看到的那样模糊。
总结起来有两个问题:
如何改变字符的宽度?
如何在不模糊的情况下绘制字母的几何形状。 (可以用 ClearType 渲染几何图形吗?)
private void RenderGlyphRun1(FontFace1 fontFace)
{
var Offsets = new List<GlyphOffset>();
var fontEmSize_ = 12;
GlyphRun glyphRun = new GlyphRun();
glyphRun.FontFace = fontFace;
glyphRun.FontSize = fontEmSize_;
glyphRun.BidiLevel = 1;
var left = 650f;
var top = 50f;
var baseLine = (float)(fontFace.Metrics.LineGap + fontFace.Metrics.Ascent) /
fontFace.Metrics.DesignUnitsPerEm * glyphRun.FontSize;
string textToDraw = "ABCDE";
foreach (char letter in textToDraw)
{
Offsets.Add(new GlyphOffset());
}
var charArr = textToDraw.Select(x => (int)x).ToArray();
glyphRun.Indices = fontFace.GetGlyphIndices(charArr);
var metrics = fontFace.GetDesignGlyphMetrics(glyphRun.Indices, false);
glyphRun.Advances = metrics.Select(x => (float)x.AdvanceWidth /
fontFace.Metrics.DesignUnitsPerEm * glyphRun.FontSize).ToArray();
glyphRun.Offsets = Offsets.ToArray();
RenderTarget2D.BeginDraw();
RenderTarget2D.Clear(SharpDX.Color.White);
RenderTarget2D.DrawGlyphRun(new Vector2(left, top),
glyphRun, new SharpDX.Direct2D1.SolidColorBrush(RenderTarget2D, SharpDX.Color.Black),
MeasuringMode.Natural);
top += baseLine;
var pathGeometry = new PathGeometry(Factory2D);
var geometrySink = pathGeometry.Open();
fontFace.GetGlyphRunOutline(glyphRun.FontSize, glyphRun.Indices,
glyphRun.Advances, glyphRun.Offsets, glyphRun.IsSideways,
glyphRun.BidiLevel % 2 != 0, geometrySink);
geometrySink.Close();
geometrySink.Dispose();
fontFace.Dispose();
var matrix = new Matrix3x2()
{
M11 = 1,
M12 = 0,
M21 = 0,
M22 = 1,
M31 = left,
M32 = top
};
var transformedGeometry = new TransformedGeometry(Factory2D, pathGeometry, matrix);
var brushColor = (Color4)SharpDX.Color.Black;
var brush = new SolidColorBrush(RenderTarget2D, brushColor);
RenderTarget2D.FillGeometry(transformedGeometry, brush);
pathGeometry.Dispose();
transformedGeometry.Dispose();
brush.Dispose();
RenderTarget2D.EndDraw();
}
Direct2D
文本呈现功能分两部分提供:
1) DrawText
和 DrawTextLayout
方法,使调用者能够传递字符串和格式化参数,或传递多种格式的 DWrite 文本布局对象。这应该适合大多数来电者。
2) 第二种方式是渲染文本,公开为DrawGlyphRun
方法,为已经知道他们想要渲染的字形位置的客户提供光栅化。以下两条通用规则有助于提高在 Direct2D 中绘图时的文本性能。
我现在看到您使用的是第二种方法,但是在第一种方法中,您可以将渲染设置为 ClearType
:
RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
我不确定如何将它包含在您的示例中,但 Sharp DX 示例如下所示:
using System;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DirectWrite;
using SharpDX.Samples;
using TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode;
namespace TextRenderingApp
{
public class Program : Direct2D1DemoApp
{
public TextFormat TextFormat { get; private set; }
public TextLayout TextLayout { get; private set; }
protected override void Initialize(DemoConfiguration demoConfiguration)
{
base.Initialize(demoConfiguration);
// Initialize a TextFormat
TextFormat = new TextFormat(FactoryDWrite, "Calibri", 128) {TextAlignment = TextAlignment.Center, ParagraphAlignment = ParagraphAlignment.Center};
RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
// Initialize a TextLayout
TextLayout = new TextLayout(FactoryDWrite, "SharpDX D2D1 - DWrite", TextFormat, demoConfiguration.Width, demoConfiguration.Height);
}
protected override void Draw(DemoTime time)
{
base.Draw(time);
// Draw the TextLayout
RenderTarget2D.DrawTextLayout(new Vector2(0,0), TextLayout, SceneColorBrush, DrawTextOptions.None );
}
[STAThread]
static void Main(string[] args)
{
Program program = new Program();
program.Run(new DemoConfiguration("SharpDX DirectWrite Text Rendering Demo"));
}
}
}
样本取自:https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/Direct2D1/TextRenderingApp
由于有些字母应该是窄的,有些是正常的,有些是宽的,你不能使用一个 GlyphRun
,而必须创建 3 个不同的 GlyphRun
.
要使任何 GlyphRun
的所有字母变宽或变窄:
- 将
Transform
配置为RenderTarget
- 绘制
GlyphRun
- Return原
Transform
宽变换:RenderTarget2D.Transform = new SharpDX.Mathematics.Interop.RawMatrix3x2(1.5f, 0, 0, 1, 0, 0);
窄变换:RenderTarget2D.Transform = new SharpDX.Mathematics.Interop.RawMatrix3x2(0.5f, 0, 0, 1, 0, 0);
采用此解决方案后,您无需将 GlyphRun
转换为 geometry
并混淆模糊字母。
我正在使用 SharpDX 编写 C# Direct2D 应用程序,但是我可以理解 answers/examples C++ 中提供的内容。
我想渲染文本并更改某些字符的宽度以使其看起来像图片:
字母B扩大到200%,字母D缩小到50%
在下面的代码中,我绘制了字形的几何图形 所以可以改变几何体的宽度 但这不是一个好的解决方案,因为几何绘图会像您在图片中看到的那样模糊。
总结起来有两个问题:
如何改变字符的宽度?
如何在不模糊的情况下绘制字母的几何形状。 (可以用 ClearType 渲染几何图形吗?)
private void RenderGlyphRun1(FontFace1 fontFace) { var Offsets = new List<GlyphOffset>(); var fontEmSize_ = 12; GlyphRun glyphRun = new GlyphRun(); glyphRun.FontFace = fontFace; glyphRun.FontSize = fontEmSize_; glyphRun.BidiLevel = 1; var left = 650f; var top = 50f; var baseLine = (float)(fontFace.Metrics.LineGap + fontFace.Metrics.Ascent) / fontFace.Metrics.DesignUnitsPerEm * glyphRun.FontSize; string textToDraw = "ABCDE"; foreach (char letter in textToDraw) { Offsets.Add(new GlyphOffset()); } var charArr = textToDraw.Select(x => (int)x).ToArray(); glyphRun.Indices = fontFace.GetGlyphIndices(charArr); var metrics = fontFace.GetDesignGlyphMetrics(glyphRun.Indices, false); glyphRun.Advances = metrics.Select(x => (float)x.AdvanceWidth / fontFace.Metrics.DesignUnitsPerEm * glyphRun.FontSize).ToArray(); glyphRun.Offsets = Offsets.ToArray(); RenderTarget2D.BeginDraw(); RenderTarget2D.Clear(SharpDX.Color.White); RenderTarget2D.DrawGlyphRun(new Vector2(left, top), glyphRun, new SharpDX.Direct2D1.SolidColorBrush(RenderTarget2D, SharpDX.Color.Black), MeasuringMode.Natural); top += baseLine; var pathGeometry = new PathGeometry(Factory2D); var geometrySink = pathGeometry.Open(); fontFace.GetGlyphRunOutline(glyphRun.FontSize, glyphRun.Indices, glyphRun.Advances, glyphRun.Offsets, glyphRun.IsSideways, glyphRun.BidiLevel % 2 != 0, geometrySink); geometrySink.Close(); geometrySink.Dispose(); fontFace.Dispose(); var matrix = new Matrix3x2() { M11 = 1, M12 = 0, M21 = 0, M22 = 1, M31 = left, M32 = top }; var transformedGeometry = new TransformedGeometry(Factory2D, pathGeometry, matrix); var brushColor = (Color4)SharpDX.Color.Black; var brush = new SolidColorBrush(RenderTarget2D, brushColor); RenderTarget2D.FillGeometry(transformedGeometry, brush); pathGeometry.Dispose(); transformedGeometry.Dispose(); brush.Dispose(); RenderTarget2D.EndDraw(); }
Direct2D
文本呈现功能分两部分提供:
1) DrawText
和 DrawTextLayout
方法,使调用者能够传递字符串和格式化参数,或传递多种格式的 DWrite 文本布局对象。这应该适合大多数来电者。
2) 第二种方式是渲染文本,公开为DrawGlyphRun
方法,为已经知道他们想要渲染的字形位置的客户提供光栅化。以下两条通用规则有助于提高在 Direct2D 中绘图时的文本性能。
我现在看到您使用的是第二种方法,但是在第一种方法中,您可以将渲染设置为 ClearType
:
RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
我不确定如何将它包含在您的示例中,但 Sharp DX 示例如下所示:
using System;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DirectWrite;
using SharpDX.Samples;
using TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode;
namespace TextRenderingApp
{
public class Program : Direct2D1DemoApp
{
public TextFormat TextFormat { get; private set; }
public TextLayout TextLayout { get; private set; }
protected override void Initialize(DemoConfiguration demoConfiguration)
{
base.Initialize(demoConfiguration);
// Initialize a TextFormat
TextFormat = new TextFormat(FactoryDWrite, "Calibri", 128) {TextAlignment = TextAlignment.Center, ParagraphAlignment = ParagraphAlignment.Center};
RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
// Initialize a TextLayout
TextLayout = new TextLayout(FactoryDWrite, "SharpDX D2D1 - DWrite", TextFormat, demoConfiguration.Width, demoConfiguration.Height);
}
protected override void Draw(DemoTime time)
{
base.Draw(time);
// Draw the TextLayout
RenderTarget2D.DrawTextLayout(new Vector2(0,0), TextLayout, SceneColorBrush, DrawTextOptions.None );
}
[STAThread]
static void Main(string[] args)
{
Program program = new Program();
program.Run(new DemoConfiguration("SharpDX DirectWrite Text Rendering Demo"));
}
}
}
样本取自:https://github.com/sharpdx/SharpDX-Samples/blob/master/Desktop/Direct2D1/TextRenderingApp
由于有些字母应该是窄的,有些是正常的,有些是宽的,你不能使用一个 GlyphRun
,而必须创建 3 个不同的 GlyphRun
.
要使任何 GlyphRun
的所有字母变宽或变窄:
- 将
Transform
配置为RenderTarget
- 绘制
GlyphRun
- Return原
Transform
宽变换:RenderTarget2D.Transform = new SharpDX.Mathematics.Interop.RawMatrix3x2(1.5f, 0, 0, 1, 0, 0);
窄变换:RenderTarget2D.Transform = new SharpDX.Mathematics.Interop.RawMatrix3x2(0.5f, 0, 0, 1, 0, 0);
采用此解决方案后,您无需将 GlyphRun
转换为 geometry
并混淆模糊字母。