zoukankan      html  css  js  c++  java
  • 让基于DirectFB的Mozilla支持透明图

    让基于DirectFBMozilla支持透明图

     

    转载时请注明出处和作者联系方式

    作者联系方式:李先静 <xianjimli at hotmail dot com>

     

    Mozilla是个庞然大物,把Mozilla移植到GTK+/DirectFB上可不是件容易的事,所幸上次从网上找到了基于GTK+/DirectFBMozilla,经过一段时间的努力,最终成功的编译出minimo,为我省了不少时间。之后让它支持安装功能,方便以后扩展; 又对速度做了优化,现在十秒之内就可以运行起来。不过,虽然可以用了,还是有些美中不足,问题之一就是它不支持透明图。

     

    移植者去年曾经声明当时还不支持透明图,今天到mozilla的网站上看了一下,还是没有任何更新,看来不能指望他们了。GTK+/DirectFB对透明图的支持非常完善,为什么mozilla不能显示透明图呢?

     

    使用1bitalpha值的图片会触发gdkgc-directfb.c中的一个断言,不过这个断言无关紧要,直接注释掉就行了。

     

    nsImageGTK.cppMozillaGTK关于图象处理的衔接部分,移植者修改了不少代码,里面也有对alpha通道的处理,没有发现什么线索。我开始怀疑是gfxImageFramensPNGDecoder没有把alpha数据送过来,经过跟踪发现,alpha数据是正确的,也设置到GdkGC里去了,难道是GDK-DirectFB中没有使用它吗?

     

    跟踪到gdk_directfb_draw_drawable函数,发现的确如此,values.clip_mask是正常的,但没有人使用它。本来只要修改gdk_directfb_draw_drawable函数即可,问题是DirectFB没有提供mask方式的透明处理,自己写代码进行转换吧,又可能会造成严重的性能下降。考虑到一般情况下,被maskpixel都是0,所以我先做了个简化处理,它在大多数情况下正常的,极少情况会显示有误,以后再改进吧。修改后的代码如下:

    static void 
    gdk_directfb_draw_drawable (GdkDrawable *drawable,
                                GdkGC       *gc,
                                GdkDrawable *src,
                                gint         xsrc,
                                gint         ysrc,
                                gint         xdest,
                                gint         ydest,
                                gint         width,
                                gint         height)
    {
      GdkDrawableImplDirectFB *impl;
      GdkDrawableImplDirectFB *src_impl;
      GdkRegion               *clip;
      GdkRectangle             dest_rect = { xdest,
                                             ydest,
                                             xdest + width,
                                             ydest + height };
      GdkGCValues values = {0};
      gdk_gc_get_values(gc, &values);

      DFBRectangle rect = { xsrc, ysrc, width, height };
      gint i;

      impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);

      if (!impl->surface)
        return;

      if (GDK_IS_PIXMAP (src))
        src_impl = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_PIXMAP_OBJECT (src)->impl);
      else if (GDK_IS_WINDOW (src))
        src_impl = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (src)->impl);
      else if (GDK_IS_DRAWABLE_IMPL_DIRECTFB (src))
        src_impl = GDK_DRAWABLE_IMPL_DIRECTFB (src);
      else 
        return;

      clip = gdk_directfb_clip_region (drawable, gc, &dest_rect);

      for (i = 0; i < clip->numRects; i++)
        {
          DFBRegion reg = { clip->rects[i].x1,     clip->rects[i].y1,
                            clip->rects[i].x2 - 1, clip->rects[i].y2 - 1 };

          impl->surface->SetClip (impl->surface, &reg);

          if(values.clip_mask != NULL)
          {
            GdkDrawableImplDirectFB* mask = GDK_DRAWABLE_IMPL_DIRECTFB(values.clip_mask);

            impl->surface->SetBlittingFlags(impl->surface, DSBLIT_SRC_COLORKEY);
            impl->surface->SetSrcColorKey(impl->surface, 0, 0, 0);
            impl->surface->Blit (impl->surface, src_impl->surface, &rect,
                               xdest, ydest);
          }
          else 
          {
            impl->surface->Blit (impl->surface, src_impl->surface, &rect,
                               xdest, ydest);
          }
        }
      impl->surface->SetClip (impl->surface, NULL);

      gdk_directfb_update_region (impl, clip);
      gdk_region_destroy (clip);
    }

     

    试了几个网页,1bitalpha值处理正常了,但又发现8bitalpha还是不对。用gdb跟踪了一下,发现8bitalpha是在nsImageGTK.cpp中处理的。透明部分是随机数据,花花绿绿的。又在DrawComposited16发现背景数据不对,我猜测是nsImageFramensRenderingContextGTKnsDrawingSurfaceGTK中的问题,大概是没有初始化背景图象吧,又花了几个小时去读代码和调试,结果证实这部分代码没有任何问题。

     

    奇怪了,再回到nsImageGTK.cpp中,发现背景数据是从windowing_data中读出来的,感觉这个变量名有点怪,查了一下GDK-DirectFB的代码,从下面的代码中我们可以看到,windowing_data果然不是我们期望的:

    nsImageGTK.cpp: windowing_data->mem
    static void 
    gdk_image_init (GdkImage *image)
    {
      image->windowing_data = g_new0 (GdkImageDirectFB, 1);
      image->mem = NULL;

      image_list = g_list_prepend (image_list, image);
    }

     

    GdkImageDirectFB结构怎么会是pixel数据呢?明显是不对的。但不是windowing_data又是哪个变量呢?从下面这个函数,我们可以确认应该使用mem而不是windowing_data

     

    guint32
    gdk_image_get_pixel (GdkImage *image,
                         gint      x,
                         gint      y)
    {        
      guint32 pixel = 0;

      g_return_val_if_fail (GDK_IS_IMAGE (image), 0);

      if (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
        return 0;

      if (image->depth == 1)
        pixel = (((guchar *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
      else 
        {
          guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;

          switch (image->bpp)
            {
            case 1:
              pixel = *pixelp;
              break;

            case 2:
              pixel = pixelp[0] | (pixelp[1] << 8);
              break;

            case 3:
              pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
              break;

            case 4:
              pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
              break;
            }
        }

      return pixel;
    }          

     

    nsImageGTK.cpp中,把windowing_data替换成mem,编译后重新运行,界面清新多了。

     

    ~~end~~

     
  • 相关阅读:
    django-模板之extends(三)
    django-模板之模板变量(二)
    django-模板之自定义模板路径(一)
    django-Views之类视图 (六)
    django-Views之使用视图渲染模板(五)
    django-Views之装饰器(四)
    django-Views之常见的几种错误视图代码(三)
    用nginx搭建http/rtmp/hls协议的MP4/FLV流媒体服务器
    通过nginx搭建hls流媒体服务器
    ffmpeg解码RTSP/TCP视频流H.264(QT界面显示视频画面)
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167701.html
Copyright © 2011-2022 走看看