新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   >>中国XML论坛<<     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论WAP/WML, XMPP, Mobile Web Service, Windows Mobile, Symbian, PalmOS, Android, 嵌入式数据库, 无线搜索等移动嵌入式软硬件开发技术
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - 高级XML应用『 XML 与 移动嵌入式开发 』 → [分享] 一篇关于JSR-226的入门文章 -- J2ME移动2D图形快速入门 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 10928 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [分享] 一篇关于JSR-226的入门文章 -- J2ME移动2D图形快速入门 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     enyaxp 帅哥哟,离线,有人找我吗?巨蟹座1984-7-4
      
      
      威望:2
      等级:计算机学士学位(版主)
      文章:350
      积分:2433
      门派:XML.ORG.CN
      注册:2007/12/11

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给enyaxp发送一个短消息 把enyaxp加入好友 查看enyaxp的个人资料 搜索enyaxp在『 XML 与 移动嵌入式开发 』 的所有贴子 点击这里发送电邮给enyaxp  引用回复这个贴子 回复这个贴子 查看enyaxp的博客楼主
    发贴心情 [分享] 一篇关于JSR-226的入门文章 -- J2ME移动2D图形快速入门


    绪论

        这篇文章将介绍可升级2D矢量图形API(Scalable 2D Vector Graphics API),它是J2ME的一个可选包。这些API非常易于使用,它们可以用来渲染和转换体积小和伸缩性好的二维(2D)图形,这个可选包在Java社区进程(JCP)中以JSR-226开发。我将会给出API的总括,并且突出典型的用户案例,使用代码演示这些案例。
    总括

        JSR-226将渲染和重放矢量2D图形引入到Java语言的移动应用中。由Nokia领导的专家组,是由移动行业的主要厂商组成,他们都很有兴趣将矢量多媒体内容引入到他们的设备中。在写这篇文章时,这个规范刚刚被核准,大家正在热切期待着一个参考实现。
    矢量图对移动开发者来说,有两大好处:占用空间小和伸缩性好。考虑下面这个简单的图像:


    此主题相关图片如下:
    按此在新窗口浏览图片

    图1 一个简单的示例图像

        使用GIF格式,这个图片的大小会达到7386字节。使用向量格式,大小仅仅为693字节,不到十分之一。这种减少是如何发生的呢?

        以光栅为基础的图像格式,像GIF,对组成图像的矩形区域中的每一个像素的色彩内容进行编码。而矢量图,仅仅包含决定像素应该如何被着色的绘画指令。一个图像的向量表示法可以更大程度上进行压缩,这对资源受限的移动设备是一个很大的有利因素。

        伸缩性好是另外一个重要的优点。矢量图可以很清楚的进行变换,因为它们的绘画指令是和分辨率无关的。图2显示前一张图片进行等比例缩小、翻转和旋转后的图像。


    此主题相关图片如下:
    按此在新窗口浏览图片

    图2 示例图片的变换

        矢量图的度量单位是任意的和相对的,它们可以被一些常量因子乘或除,以变换图像从而适应特定设备的屏幕。通过对这个坐标系统使用简单的数学操作,你可以创造出无限的效果,包括翻转、旋转、拉伸和扭曲。使用矢量图像,应用程序开发者不再需要为图像和图标创建不同的集合,来支持不同的屏幕分辨率。

        矢量图的简洁和伸缩性在动画领域大放异彩。以光栅为基础的动画,像网页中的GIF和MIDP游戏中的精灵,在动画的每一个帧中包含整个图片都很费力。与之相比,以矢量为基础的动画仅仅包含一些指令,而这些指令规定了当需要改变动画时的图像哪些元素应该如何改变。如果矢量图的大小比它们相对应的光栅图小一个数量级,那么矢量动画的大小就比他们相对应的光栅动画小两个数量级,这使得它们成为在移动设备上变换和展示多媒体内容的理想选择。

        当以私有的Macromedia Flash播放器为基础的矢量图和矢量动画变得流行时,可升级矢量图形(Scalable Vector Graphics,SVG)文件格式以开放的标准和免费的专利权,成为业界的另外一个选择。它由W3C标准化。SVG-Tiny提供了SVG全部功能的一个子集,适合在移动设备上使用。JSR-226采用SVG-Tiny的1.1版本作为J2ME矢量图形的官方文件格式。W3C称SVG-Tiny为一个“Profile”,但是为了避免和J2ME的Profile混淆,我称之为“格式”。

        SVG-Tiny标准也可以支持动画。图像文件内部的指令可以自己修改图像元素的位置和属性,来回应时钟事件和用户输入。

        为了更加复杂的交互,JSR-226引入了兼容microDOM的API,microDOM是SVG1.2完整的文档对象模型(DOM)的一个子集。

        SVG是一种可扩展标记语言(XML)格式,它使用一个公共的Schema充分的注释和系统化。SVG-Tiny可能很小,但是它们仍然是SVG文件,仍然包含XML。下面是代表一个“brave world”图像的完整的SVG-Tiny文件:

    <?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN"
        "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
    <svg preserveAspectRatio="xMidYMid meet"
            viewbox="10 10 130 55" width="150.0" height="75.0">
        <rect x="25" y="25" transform="translate(75 36.375)
            rotate(15) translate(-70 -35.375)" fill="#00007E"
            width="100" height="22.75" stroke="#000000" stroke-width=".5"/>
        <rect x="25" y="25" fill="#FF9800" width="108.5"
            height="22.75" stroke="#000000" stroke-width=".5"/>
        <text x="30" y="40" fill="#00007E" stroke="#FFFFFF"
            stroke-width=".33" xml:space="preserve">Hello brave world.</text>
    </svg>

        这个文档声明了两个矩形和一些文字。第一个矩形绕它的中心旋转15度,这一系列的转换都包含在rect标记的转换属性中。第二个矩形在第一个之上绘制,然后文本在第二个矩形之上绘制。

        即时未经修饰的文本不是一个特别的简洁格式,这个文档仍旧比一个压缩的光栅图像小的多,并且易于人工导入。因为XML文本可以充分地压缩,所以SVG在应用程序的JAR文件中就占用相对较少的空间。JSR-226要求支持SVG文档的实现使用gzip格式压缩。后缀名.svgz表示gzip压缩的文档。

    Mobile 2D API

        JSR-226的一个主要的目的就是定义移动2D图形(Mobile 2D Graphics,M2G)API,这个API是一小组和SVG-Tiny格式功能结合很紧密的类。它没有被规定为普通的2D图形绘制工具箱,就像J2SE的Graphics2D类提供的那样。M2G API很清楚地定位于播放和在运行期操纵SVG内容。

        M2G由高级类和低级类组成,高级类用来创建和渲染矢量图形,而低级类负责以DOM树的部分来操纵一个矢量图形的XML成分。矢量图形是ScalableImage的实例,你可以通过这个的静态createImage()方法获得它们。你使用ScalableGraphics的一个实例将ScalableImages绘制到一个MIDP图形上下文中。SVGImage是ScalableImage的一个子类,它提供事件处理和底层DOM文档访问之间的联系。

        为了使渲染动画SVG内容的普通情况更加方便,这个API提供了SVGAnimator类。对MIDP应用程序,SVGAnimator创建和控制一个Canvas对象,这个对象自动处理屏幕更新,以回应动画事件和对这个图像的计划性的修改。SVGAnimator提供一个类似播放器接口来控制动画的播放。

        这些类都定义在javax.miroedition.m2g和org.w3c.dom.svg包中,在表1中进行了总结,并且在JSR-226规范中也作了充分的注释。SVG DOM是在标准的org.w3c.dom和org.w3c.dom.events包中定义DOM类和接口的扩展。


    此主题相关图片如下:
    按此在新窗口浏览图片

    创建M2G应用程序

        为了创建一个M2G应用程序,你需要可以工作的JSR-226实现。在写这篇文章时,这个规范才刚刚被定案;没有设备实现它,并且没有官方的参考实现可用。你可以下载一个有限的、实现的实现,作为mpowerplayer开发者工具箱的附加包。

        你还需要一些SVG-Tiny内容。这篇文章是用上面的“brave world”图像,但是更多的SVG-Tiny示例可以从移动开发工具制造者TinyLine上获得。你也可以使用一个商用Java应用程序创建自己的内容,这个应用程序被称为Sketsa,它可以像一个插图工具一样工作,并且使用SVG作为它的文件格式。

        只有很少的方法用来将你的SVG内容绘制到屏幕上。最简单的是为你的图像创建一个SVGAnimator,然后把它Canvas放到屏幕上。另外一个方法是创建一个ScalableImage的实例,然后使用ScalableGraphics的实例将它绘制到你自己的Canvas或者CustomItem的图形上下文中。你将会获得除了展现外的更多控制,但是你必须负责处理输入事件,并且为动画效果或者用户交互进行重绘。

    使用一个SVGAnimator显示2D图像

        你可以通过SVGAnimator的静态方法createAnimator()获得一个它的实例,需要提供你自己的图像。使用SVGAnimator是一个不错的选择,因为它处理所有的用户交互,和动态内容的动画。play()、pause()、stop()和setTimeIncrement()方法会给你除了重放之外的对动画的可编程控制。实现可能提供一个本地用户接口,可以同样的处理动态行为。

        一旦你获得SVGAnimator,就可以很容易的将它嵌入到你的应用程序中。调用getTargetComponent()会一个Canvas实例,它可以被放置在屏幕上。下面是一个例子:

    public void animationTest()
        {
            // create an animator to load the content
            SVGAnimator animator =
       SVGAnimator.createAnimator( image );
                
            // add our custom event listener
            animator.setEventListener(
       new CustomEventListener( animator ) );
            
            // get the Canvas for this player; requires a cast
            Canvas canvas = (Canvas) animator.getTargetComponent();
            
            // add a "back" command
            canvas.addCommand( backCommand );
            canvas.setCommandListener( this );
            
            // show it
            Display.getDisplay(this).setCurrent( canvas );
            
            // start it
            animator.play();
        }

        在MIDP环境中,从getTargetComponent()返回的值是一个MIDP Canvas。在非MIDP环境中,返回值将适合本地窗口系统,例如在AWT环境中,返回值是Component。如果当前环境拥有一个以上的可用的选择,那么就提供需要的类型的名字作为createAnimator()的第二个参数。

        图3显示了运行时结果。根据不同的实现,和笔触设备的可用性,动画绘制器可能允许用户和动画内容进行交互。在“brave world”例子中没有动态的内容,但是文本是可选的。


    此主题相关图片如下:
    按此在新窗口浏览图片

    图3 由SVGAnimator控制的Canvas

    和动画绘制器交互

        尽管“brave world”图像不是一个动画,一些程序设计还是可以增加交互的。

        JSR-226的DOM支持一个程序改变一个图像的结构。和任何其他的XML文档一样,一个SVGImage可以用一个DOM对象树代表。M2G API允许你使用类似熟悉的XML处理技术来修改图像。树中的每一个节点是一个SVGElement,提供操纵临近的父节点和子节点的方法。你可以通过添加和删除子节点修改节点,或者转换成一个合适的元素类,然后调用那个类的方法进行改变。

        SVGEventListener结构使你的应用程序可以从SVGAnimator的Canvas接收用户的输入事件。这个例子是用DOM API来等比例变化和旋转这个图像,用户可以通过箭头键输入:

    {
        int gameAction = canvas.getGameAction( keyCode );
        switch ( gameAction )
        {
            case Canvas.UP:
                scale( 0.10f );
                break;
            case Canvas.LEFT:
                rotate( -10.0f );
                break;
            case Canvas.DOWN:
                scale( -0.10f );
                break;
            case Canvas.RIGHT:
                rotate( 10 );
                break;
            default:
                // leave unchanged
        }
    }

    private void rotate( final float delta )
    {
        // put ourselves on the animator's thread
        animator.invokeLater( new Runnable()
        {
            public void run()
            {
                // execute the transformation
                Document document = svgImage.getDocument();
                SVGSVGElement root = (SVGSVGElement)
        document.getDocumentElement();
                root.setCurrentRotate( root.getCurrentRotate() + delta );
            }
        } );
    }

    private void scale( final float delta )
    {
        // put ourselves on the animator's thread
        animator.invokeLater( new Runnable()
        {
            public void run()
            {
                // execute the transformation
                Document document = svgImage.getDocument();
                SVGSVGElement root = (SVGSVGElement)
        document.getDocumentElement();
                root.setCurrentScale( root.getCurrentScale() + delta );
            }
        } );
    }

        SVGImage.getDocument()提供了动画绘制器渲染的文档的引用。因为这个播放器可能正在运行一个或者更新一个动态的内容,所以你必须小心地将你的变化和动画线程同步,否则将会发生不可确定的错误。SVGAnimator's invokeAndWait() 和invokeLater()方法就像它们的AWT副本一样,可以保证你的代码在动画线程上运行。
    直接渲染2D内容

        如果你想除了你的SVG图像在哪里和怎样被渲染外获得完全的控制,你可以使用ScalableGraphics类直接绘制一个ScalableImage到Graphics对象之上,这个Graphics对象被传递到Canvas、Layer或者CustomItem实例的paint()方法中。

        你通过调用ScalableGraphics的静态createInstance()方法创建一个它的实例。在绘制之前,你必须首先使用bindTarget()方法将ScalableGraphics实例和传递到绘制方法中的Graphics对象绑定。在完成以后,请调用releaseTarget()。一旦建立绑定,你就可以使用render()方法绘制你的每一个图像。

        这个例子以不同的大小重复绘制“brave world”图像,例子通过在每一次调用render()方法前调用setViewportHeight()和setViewportWidth()方法改变图像大小:

    private static class M2GCanvas extends Canvas
    {
        // retain a reference the specified image
        ScalableImage scalableImage;
         
        // retain an instance of a scalable graphics
        ScalableGraphics scalableGraphics;
        
        public M2GCanvas( ScalableImage inImage )
        {
            scalableImage = inImage;

            // create the scalable graphics instance
            scalableGraphics = ScalableGraphics.createInstance();
        }

        public void paint( Graphics g )
        {
            // clear the display
            g.setColor( 255, 255, 255 );
            g.fillRect( 0, 0, getWidth(), getHeight() );
            
            // bind our scalable graphics to the given graphics
            scalableGraphics.bindTarget( g );

            // render at fixed position and size
            scalableImage.setViewportWidth( 50 );
            scalableImage.setViewportHeight( 75 );
            scalableGraphics.render( 5, 50, scalableImage );

            // again at different position and size
            scalableImage.setViewportWidth( 100 );
            scalableImage.setViewportHeight( 150 );
            scalableGraphics.render( 80, 5, scalableImage );

            // again at size that varies with the canvas size
            scalableImage.setViewportWidth( getWidth()-20 );
            scalableImage.setViewportHeight( getHeight()-20 );
            scalableGraphics.render( 0, 0, scalableImage );

            // release the graphics context
            scalableGraphics.releaseTarget();
        }
    }

        Canvas的子类在不同的位置以不同的大小显示这个图像三次。在第三次,图像填满了这个画布。在支持可重设屏幕大小的设备上,图像可以适当的等比例变化。图4显示了画布的效果。在这个实现中,较大的图像在窗口大小被重置时等比例得到。


    此主题相关图片如下:
    按此在新窗口浏览图片

    图4 在一个Canvas上等比例变换ScalableImages

        如果你正在渲染的图像是动态的,你应该允许用户和他们交互。当你不用SVGAnimator渲染时,你需要检测用户指针事件,得到图像是否和在何处被点击,然后在SVGImage上调用dispatchMouseEvent()方法,触发脚本定义好的动作。对一个CustomItem,表单移动应该允许激活和焦点导航,通过图像中的元素,分别使用SVGImage的activate() 和focusOn()方法。

        你的程序不仅仅可以操纵一个已经存在的SVGImage的DOM,也可以从头建立一个图像。SVGImage的静态方法createEmptyImage()返回一个具有空文档的图像,这个文档的架构可以有程序创建的代表形状和变换的SVGElement填充。这种可以和ScalableGraphics联合使用,实现一个普通的2D绘制工具箱,但是正像我前面提到的那样,这样用法不是最初的意向,不推荐使用。

    总结

        J2ME的可升级2D矢量图形API提供了渲染和操作以矢量为基础的图像和动画的能力。矢量图像的占用空间小和伸缩性好使得它天生的适合移动应用程序。JSR-226的移动2D图形API使应用程序能够使用MIDP和AWT工具箱创建、显示和修改SVG内容。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------

    I'M BACK, NEVER GO AWAY.

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/3/18 1:32:00
     
     GoogleAdSense巨蟹座1984-7-4
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 XML 与 移动嵌入式开发 』 的所有贴子 点击这里发送电邮给Google AdSense  访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2022/11/29 15:18:39

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    62.500ms