在我的应用程序(cairo
和X11
)中,用户可以发出一个命令,从而放大绘图。为了能够将整个绘图作为图案抓取,我放大了绘图表面以匹配当前比例(绘图只是一个图形,因此就内存而言可以提供)。但是,从一定的比例开始,X11 窗口拒绝刷新,直到它得到一个事件(例如失去焦点,这在我的应用程序中甚至没有处理)。
我尝试使用 XFlush()
和 XSync()
刷新窗口。
这看起来像是窗口系统中的错误吗?如果没有,我该怎么办?一切都可以在较小的规模下完美运行。
编辑1:经过大量gdb
工作,我发现问题不在于窗口不刷新。相反,在某个点上,对XNextEvent()
的调用会导致窗口全黑。
编辑2:看起来调用XNextEvent()
实际上会导致窗口刷新!以下是导致问题的代码:
struct PatternLock {
PatternLock(Graphics &g)
: g_(g) {
p_ = cairo_get_source(g_.cr);
cairo_pattern_reference(p_);
}
~PatternLock() {
// The commented lines caused the problem. How come?
// cairo_set_source_rgb(g_.cr, 0, 0, 0);
// cairo_paint(g_.cr);
cairo_set_source(g_.cr, p_);
cairo_paint(g_.cr);
cairo_pattern_destroy(p_);
}
private:
Graphics &g_;
cairo_pattern_t *p_;
};
假设我们有以下代码来移动绘图:
{
PatternLock lock{g};
... // Change of transformation matrix
}
不知何故,PatternLock
析构函数中注释行的效果变得可见(因此出现黑屏),但以下行的效果却不可见。我意识到注释的代码实际上是不需要的。但是,这是怎么发生的呢?
如果我没记错的话,可绘制对象(例如 Windows 和 Pixmap)的限制为 4096x4096 像素。您应该检查调用 XCreatePixmap() 等的返回值。
无论哪种方式,只是放大像素图来绘制你的绘图都是糟糕的设计(tm),并且不可避免地会导致一个非常缓慢的程序。了解如何处理缩放和平移(提示:从视口中心而不是角落开始工作)。假设您的绘图是基于矢量的(即直线和曲线),则可以在高缩放系数下优化大量绘画。
如果必须以大于 4096 像素的分辨率抓取完整的图形,则必须实现平铺,如果您已经具有缩放和平移功能,这并不难。