转载时请注明出处和作者联系方式
文章出处: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上交流

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐