Macos 为什么';CGContextShowGlyphsAtPositions()工作,当CGContextShowGlyphsAtPoint()工作时?
我已经使用Xcode 4.2为MacOSX(10.7)编写了一个简单的Cocoa应用程序。该应用程序所做的只是创建一个窗口,其中包含可滚动的子视图数组,每个子视图代表一个页面,可以在非常低的级别上绘制内容。子视图的isFlipped方法提供YES,因此每个子视图的原点位于左上角。使用各种核心图形例程,我能够成功地画线、填充路径和所有有趣的后期脚本 这是从给定字体绘制的字形,让我感到困惑 下面是子视图的-drawRect:方法的完整代码,从程序中剪切粘贴-- 让我毛骨悚然的是,使用CGContextShowGlyphsAtPoint()的前两个glyph绘制调用工作正常,但使用CGContextShowGlyphsAtPositions()的第三次尝试从未绘制任何内容。因此,页面上只有两个@符号,而不是三个。这种行为上的差异并不取决于我以前是否使用过CGContextSetFont()或CGContextSelectFont() 这两个几乎完全相同的核心图形字形绘制例程,一定是状态发生了一些隐藏的变化,或者是在引擎盖下发生了一些非常不同的事情,但我所有的实验都没有证明这可能是什么 唉。我只想在视图中相应的位置数组中高效地绘制一个glyph数组Macos 为什么';CGContextShowGlyphsAtPositions()工作,当CGContextShowGlyphsAtPoint()工作时?,macos,cocoa,scrollview,glyph,Macos,Cocoa,Scrollview,Glyph,我已经使用Xcode 4.2为MacOSX(10.7)编写了一个简单的Cocoa应用程序。该应用程序所做的只是创建一个窗口,其中包含可滚动的子视图数组,每个子视图代表一个页面,可以在非常低的级别上绘制内容。子视图的isFlipped方法提供YES,因此每个子视图的原点位于左上角。使用各种核心图形例程,我能够成功地画线、填充路径和所有有趣的后期脚本 这是从给定字体绘制的字形,让我感到困惑 下面是子视图的-drawRect:方法的完整代码,从程序中剪切粘贴-- 让我毛骨悚然的是,使用CGContex
你知道我弄错了什么吗?一种可能是,从
CGContextShowGlyphsAtPositions
文档中:
每个字形的位置在文本空间中指定,因此,通过文本矩阵将转换为用户空间
是上下文的单独属性,与图形状态的当前转换矩阵不同
它没有说关于CGContextShowGlyphsAtPoint
:
此函数在用户空间的指定位置显示一组图示符
(两个引号中都添加了强调。)
因此,当从单个点显示图示符时,实际上不使用文本矩阵
但是,当您在一组位置上显示图示符时,就会使用它,并且您会看到错误矩阵的症状。具体来说,矩阵试图以另一种方式翻转文本是错误的:它将坐标系翻转过来。您正在视图外部绘制
(尝试将其设置为缩放0.5而不是-1,您将了解我的意思。)
我的建议是拿出你的
CGContextSetTextMatrix
电话。经过多次实验,彼得·霍西的回答让我头晕目眩(尽管其中有些不太正确,非常感谢!),下面是我困惑的根源,我很确定这一解释是正确的(不管怎样,代码正在做我期望的事情)
在通常的高级PostScript路径/绘制模型中,绘制一个字符会将当前点(路径端点)更新到下一个字符可能出现的位置,使当前用户空间变换保持不变。但是在引擎盖下,文本矩阵变换会根据字形的宽度进行转换(或者更准确地说,通过前进向量),以便下一个要绘制的字符可以从新文本原点开始,或者相对于新文本原点开始。文本矩阵的比例因子在转换后保持不变
因此,对CGContextSetTextMatrix()
的初始设置调用仍然需要翻转文本矩阵的垂直方向(如果用户空间也同样翻转),因为否则,无论文本图形从何处开始或使用哪种绘图例程,两个glyph集合绘图例程都将使用r/t路径绘图将glyph倒置绘制
两个glyph集合绘图例程都不会影响当前路径。它们的级别比当前路径低。我发现我可以在路径构造调用中穿插这两个例程,而不会影响路径的位置或形状
在上面发布的代码中,CGContextShowGlyphsAtPositions()的位置数据
用于绘制glyph集合的所有字符都是相对于当前文本矩阵原点对应的用户空间点的字符,该点被转换到先前绘制的“@”字形的右侧。因为我使用的字体太大,位置[0]
导致下一个“@”字形在视图边界之外绘制,因此它不可见,但正在绘制
但这两个例程之间仍然存在一些细微差别。CGContextShowGlyphsAtPositions()
永远不能用于将标志符号放置在任何绝对用户空间位置。那么如何告诉它从何处开始呢?答案(或至少一个答案)是CGContextShowGlyphsAtPoint()
将文本矩阵的原点更新到给定的用户空间点,即使没有要绘制的glyph。并且CGContextShowGlyphsAtPoint()
必须在绘制每个glyph之后转换文本矩阵,因为绘制整个glyph集合的点(可以说)是什么
因此,可以使用符号计数为0的CGContextShowGlyphsAtPoint()
将其“移动”到用户空间中的非路径点,然后可以使用位置向量调用CGContextShowGlyphsAtPositions()
(任意次数),每个位置向量都将相对于文本矩阵的原点进行处理当CGContextShowGlyphsAtPositions()
返回时,根本不更新文本矩阵原点(或者实际上是对应的用户空间点)
最后,请注意,提供给
CGContextShowGlyphsAtPositions()
的位置数据是在用户空间坐标中。苹果头文件中对这些例程的注释明确指出了这一点。谢谢。您建议修改文本
- (void)drawRect:(NSRect)dirtyRect
{
// Start with background color for any part of this view
[[NSColor whiteColor] set];
NSRectFill( dirtyRect );
// Drop down to Core Graphics world, ensuring there's no side-effects
context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(context);
{
//CGFontRef theFont = CGFontCreateWithFontName(CFSTR("American Typewriter"));
//CGContextSetFont(context, theFont);
CGContextSelectFont(context, "American Typewriter", 200, kCGEncodingMacRoman);
CGContextSetFontSize(context, 200);
// Adjust the text transform so the text doesn't draw upside down
CGContextSetTextMatrix(context, CGAffineTransformScale(CGAffineTransformIdentity, 1, -1));
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
CGContextSetRGBFillColor(context, 0.0, .3, 0.8, 1.0);
// Find the center of view's (not dirtyRect's) bounds
// View is 612 x 792 (nominally 8.5" by 11")
CGPoint centerPoint;
CGRect bds = [self bounds];
centerPoint.x = bds.origin.x + bds.size.width / 2;
centerPoint.y = bds.origin.y + bds.size.height / 2;
// Create arrays to hold glyph IDs and the positions at which to draw them.
#define glyphCount 1 // For now, just one glyph
CGGlyph glyphs[glyphCount];
CGPoint positions[glyphCount];
glyphs[0] = 40; // Glyph ID for '@' character in above font
positions[0] = centerPoint;
// Draw above center. This works.
CGContextShowGlyphsAtPoint(context, centerPoint.x, centerPoint.y - 200.0, glyphs, glyphCount);
// Draw at center. This works.
CGContextShowGlyphsAtPoint(context, positions[0].x, positions[0].y, glyphs, glyphCount);
// Draw below center. This fails (draws nothing). Why?
positions[0].y += 200.0;
CGContextShowGlyphsAtPositions(context, glyphs, positions, glyphCount);
}
CGContextRestoreGState(context);
}