`
hgfghww6
  • 浏览: 40328 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

flex动态生成矢量swf字体--java动态生成swf文件

 
阅读更多

  前言 相信很多在线设计的前端WEB应用会用到字体作为素材的案例,丰富多样的字体一般是部署在服务器端让用户去选择,而且能动态部署,使用客户端字体显然是不可取的;
  现状
  然而中文字体动不动就几个M,做过flash的同学应该知道嵌入字体是怎么回事,假如嵌入字体会使得swf整个体积变大,而flex目前容易做到的是整个字体文件编译成swf格式来动态加载。假如需要根据用户输入的文字动态的加载该如何做呢?
  最简单的方案是后台根据字体生产位图,这不能满足我的要求,1,位图拉伸后有锯齿2,大一点的位图文件很占空间,前台设计需要至少1000×1000以上才能保证清晰度,这么一张图动不动就大于100K。
  目的
  最完美的一个方案,是能让我的用户输入文字后,生成一个对应字体仅仅包含这几个文字的swf资源文件,这个swf占的空间很小并且在flex中用就可以加载。
  阿里妈妈bannermaker是有这个方案的,但是商业机密没有公开出来,可以肯定的是一定在后台端生成swf,至于怎么产生,目前也没找到过现成方案。只能自己研究了,经过一段时间实践,结合java动态生成swf的一个框架,终于成功了,20个文字的矢量图,10K不到,而且矢量图和字体大小无关,随便前端怎么拉伸无锯齿。
  首先,重述下动态矢量swf字体是什么含义呢?
  用户-》选择1字体并输入'abc'-》后台生成一个swf,这个swf仅仅包含1字体中abc三个字符并且是矢量的。
  类似于flash IDE里的这个功能:
  
  嵌入字体并导出资源swf图像。
  遗憾的是IDE不容易和应用整合,如何用代码来实现呢?
  实现的核心:java登场了,感谢anotherbigidea大师的开放和分享
  http://www.anotherbigidea.com/javaswf/
  这已经是anotherbigidea大师03年时候的杰作了,用java io操作 根据flash 6字节位组织方式可以从swf 1中提取任何的元素再去动态生成swf 2的内容。
  因此,一个想法诞生了,后台放置一个字体a的全量swf1文件,java端获取到用户输入的文字后动态的从swf1拷贝那几个图形文字生成一个 swf2 不就ok了么。 果然,如我所料:
  1,全量的swf字库怎么做?
  可依照上图,在本地安装字体后,嵌入所有字符导出一个swf,最好是swf 6.0格式。(flex和flash共享资源文件目前都用6)
  2,怎么用java动态生成swf?
  /**
  * 简单测试
  */
  package test;
  import java.io.BufferedInputStream;
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.io.StringReader;
  import java.util.HashMap;
  import com.anotherbigidea.flash.movie.Font;
  import com.anotherbigidea.flash.movie.FontDefinition;
  import com.anotherbigidea.flash.movie.FontLoader;
  import com.anotherbigidea.flash.movie.Frame;
  import com.anotherbigidea.flash.movie.Movie;
  import com.anotherbigidea.flash.movie.Text;
  import com.anotherbigidea.flash.movie.Font.NoGlyphExcepti on;
  import com.anotherbigidea.flash.structs.Color;
  /**
  * @author jianwen
  * @email  wen2375160@163.com  
  *
  */
  public class Testtxt {
  /**
  * @param args
  * @throws IOException 
  * @throws NoGlyphException 
  */
  public static void main(String[] args) throws IOException, NoGlyphException {
  //--Load a font from another movie.  That movie should contain only an
  // edit field that is specified to include all the glyphs in the
  // appropriate font.
  // Font definitions can be referenced by multiple fonts (for example if
  // there is a font used for a text block and another font used with an
  // edit field which restricts the allowable characters).
  //初始化 加载全量字库
  java.awt.Font nf = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FO NT, new FileInputStream("c://mnjmb.ttf"));
  //第一步,输入文字
  String instr = "文字这个的房贷首付第三方第三方\n\n\n地方地方haha牛x第三方我祖国好地方\n地方\ndfdfdsf";
  //第二步:选择/导入字库
  /////////避免重复加载
  String fontpath = "ccxkt";
  HashMap fonts = new HashMap();
  FontDefinition fontdef = fonts.get(fontpath);
  System.out.println("当前使用内存:"+(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024/1024);
  if(fontdef==null){
  //导入swf格式的文字类库,注意路径
  fontdef = FontLoader.loadFont( "c://"+fontpath+".swf" ); //导入全量的字库,我这里有很多个,为了测试性能,发现一个中文字体要占30M左右的内存
  fonts.put(fontpath, fontdef);
  }
  //  File f = new File("c://ch");
  //  System.out.println("一共"+f.list().length+"个中文字体");
  //  for (String s :f.list()){
  //   System.out.print(s);
  //   fonts.put(s,FontLoader.loadFont("c://ch//"+s));
  //   System.out.println(":"+(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024/1024);
  //  }
  //  System.out.println("加载中文字体后内存2:"+(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024/1024);
  //  f = new File("c://en");
  //  System.out.println("一共"+f.list().length+"个英文字体");
  //  for (String s :f.list()){
  //   System.out.print(s);
  //   fonts.put(s,FontLoader.loadFont("c://en//"+s));
  //   System.out.println(":"+(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024/1024);
  //  }
  //  System.out.println("加载所有字体后内存3:"+(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024/1024);
  /////下面是动态生成文字对应的swf部分,性能很不错,io操作由于是内存拷贝,奇快无比,比后台动态用flex sdk编译方式还要快
  //初始化参数
  int fontsize = 100;//默认字体大小,由于矢量格式,大小没关系(swf文件大小不受此参数影响)
  Color c = new Color(0,0,0);//文字颜色
  //--Create a text object with a default transform
  Text text = new Text(null);
  //--The font references the Font Definition and pulls over only the 
  // glyph definitions that are required for any text referencing the font
  System.out.println("len1:"+fontdef.getGlyphList(). size());
  Font font = new Font( fontdef );
  //第四步:
  /////处理输入字符串,支持回车多行解析
  StringReader re = new StringReader(instr);
  BufferedReader bf = new BufferedReader(re);
  String s =  bf.readLine();
  int i=0;
  while(s!=null){
  //多行间必须使用空格
  if(s.length()==0){s = " ";}
  //--Add a row of characters - specify the starting (x,y) within the text symbol
  try {
  text.addRow(font.chars(s, fontsize), c, 0, fontsize * i + 5,true, true);
  } catch (NoGlyphException e) {
  // 某文字没有该对应字体,忽略
  }
  s = bf.readLine();
  i++;
  }
  /////解析完毕
  //--Add another row - different color, no (x,y) specified so the chars will
  // flow immediately after the preceding chars.
  // text.row( font.chars( "2我来无敌", 25), new Color(255,0,255),0,0,false,false);
  //计算文本框大小,重要,必须在movie初始化前 这是我改造的代码,先计算大小
  text.measureRect(null, null, font, false);
  //默认文字x=0, 推算出中文宽度需要多加一个单位的fontsize,偶也不知道为什么,加了没坏处
  Movie movie = new Movie( (int)text.maxX+fontsize,(int)(text.maxY-text.minY) ,12,5,null);
  Frame frame = movie.appendFrame();
  //--instantiate the text
  frame.placeSymbol( text, 0, -((int) text.minY ));//让文本框显示在0,0坐标
  //--save the movie
  movie.write( "c://output.swf",true );
  //输出到流
  //movie.write( OutputStream out, boolean compressed )
  }
  }
  最后,大师提供了一个基础,优化需继续
  这种方式生成的swf比通过flexsdk动态编译生成swf要快而且文件要小,精简,很多无用信息都不会生成。
  不过也有几个局限:
  1,字体swf必须导出flash 6格式, 只能提供了简单的动画接口。 
  2,后台导入的是一个全量swf库,占用静态内存极大,要部署50套字体的话 2G内存都不够;动态加载全量字体的话也是不可行的,因为加载一个全量字体花费极大,可考虑拆分部署,或者按字体文字的字节流引入数据库,再或者可按字体分布多个服务器部署。
  这个库已经很久没人更新了,里面的代码逻辑看得一头雾水,虽然功能和性能都通过了,但是基于继续大师的优化工作还有待继续前行。
  参考文献:
  http://www.anotherbigidea.com/javaswf/
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics