KJAVA虚拟机Hack笔记-用GTK+实现绘图操作
转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>
绘 图操作是在mutable image上进行的,也就是画在GdkPixmap上的,由于GdkPixmap没有画圆和椭圆的函数,我选择用cairo来实现。大部分函数的实现很直 观,调用cairo相应的函数就行了,gxpport_draw_arc比较麻烦一点,因为gxpport_draw_arc支持画椭圆,而cairo没 有函数直接对应,我们可以通过cairo的变换函数来实现:
void gxpport_draw_arc(
jint pixel, const jshort *clip,
gxpport_mutableimage_native_handle dst,
int dotted, int x, int y, int width, int height,
int startAngle, int arcAngle)
{
cairo_t* cr = gxpport_get_dst_cairo(dst);
double start = ANGLE_FROM_DEGREE(startAngle);
double arc = ANGLE_FROM_DEGREE(arcAngle);
cairo_init_style(cr, pixel, clip, dotted);
cairo_save (cr);
cairo_translate (cr, x + width / 2.0, y + height / 2.0);
cairo_scale (cr, width / 2.0, height / 2.0);
cairo_arc(cr, 0.0, 0.0, 1., start, arc);
cairo_restore (cr);
cairo_stroke (cr);
return;
}
其它函数的实现类似,这里不再重复了。另外有两个问题值得一提:
o 目标pixmap可能为空,这时要画在当前的窗口上,我们调用自己实现的lfpport_get_active_screen来获得当前窗口。
o其次是与GTK的绘制机制有关。要往GdkWinow上绘制东西,只能在expose消息里做,在expose之前GTK会clear窗口上的内 容,之后才把绘制的内容刷新到屏幕上。而JAVA的绘制操作显然不是在expose消息里执行的。为了解决这个问题,我们需要建立另外一个 pixmap,JAVA先绘制到这个pixmap上,而在expose消息里从这个pixmap拷过去。
我们这样处理窗口的expose事件:
static gboolean frame_on_expose_event (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
int w = 0;
int h = 0;
(void)event;
(void)user_data;
GdkDrawable* drawable = GDK_DRAWABLE(widget->window);
GdkDrawable* back_buffer = g_object_get_data(G_OBJECT(drawable), "back_buffer");
GdkGC* gc = gdk_gc_new(drawable);
if(back_buffer != NULL)
{
gdk_drawable_get_size(drawable, &w, &h);
gdk_draw_drawable(drawable, gc, back_buffer, 0, 0, 0, 0, w, h);
}
g_object_unref(G_OBJECT(gc));
return TRUE;
}
欢迎到Linux mobile development上交流