首頁 > FLEX, 程式設計 > FLEX 動態更換中文字型 ( 非嵌入方式 )

FLEX 動態更換中文字型 ( 非嵌入方式 )

2009年3月6日  瀏覽次數 : 4,754

今天的習題又是由我們最受歡迎的♣梅干桑♣所出的啦,因為它秘密進行的專案需要用到讓使用者輸入字型,但是卻只能使用細明體阿,標楷體,對於學視覺傳達的他來說就是覺得超級醜啦,這樣怎麼能接受呢,但是要在 FLASH 放入中文字型,可是非常可怕的哩,光光兩個字型就可能暴增到 15 mb 呢,在[Fx]讀取本機字型與嵌入字型解決文字鋸齒這邊文章可以看到他測試的結果,好消息是今天有了振奮人心的消息。

image

這個方式是♣梅干桑♣在網海上看到的資料,來源是 tka實驗室 » 即時flash嵌入中文字型 ,不過原作者給的資料似乎不夠多,下載回來的原始檔少了很多東西,怎麼 RUN 就是跑不起來,所以我把整個流程跟大家說清楚一點吧。

flow 感謝 ♣梅問題‧教學網【Minwt】♣ 贈流程圖

當使用者按下變換資料,FLEX 會把字串丟向 SERVER 端的 PHP,並且利用 swfmill 編譯成 SWF 檔,再用 haxe 轉成 FONT CLASS ,再將 SWF 檔交給 FLEX 引入,這樣在 FLASH 就可以看到即時編譯出來的字型了。

我有將原作者的資料再稍微修正一下,不過至於寫法我就沒有更動了,所以應該還是要詢問原作者,不過基本上我都有註釋的蠻清楚了,但是有幾點問題就是,第一,swfmill 我只有看到 for Windows 的版本,但是卻又用是 PHP 來執行,等於 WEB 與作業系統有一點衝突,第二點,就是如果這個方式要在虛擬主機上執行,但是一般虛擬主機是不允許 PHP 去 Call EXE 檔案執行的,因為可能會造成他們系統不穩定,或是其他的狀況發生,所以也是蠻麻煩的,要使用這個解決方案可能自己要有架 SERVER 或是可以執行那兩隻軟體的能力。或是希望拋磚引玉,看有沒有人知道其他方法。

PS:我是使用 xampp windows 平台完成這個範例,swfmill & haxe 均下載 windows 執行版本。

因為這次檔案很多包含許多安裝檔以及字型檔因此提供連結下載[原始檔下載] 18.8mb

embedFont.mxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	width="100%"
	height="100%"
	>
	<mx:Script>
		<![CDATA[
			import flash.net.navigateToURL;
		private static var EMBEDDED_FONT:String;
		public var arial_font:Class;
		import flash.display.*;
		import mx.controls.*;
		import flash.net.URLRequest;
		import mx.managers.SystemManager;
		import flash.text.TextFormat;
		import mx.core.*;
 
		private function loadfont(fontFamily:int):void{
			var ldr:Loader = new Loader();
			var ldrContext:LoaderContext = new LoaderContext(false, new ApplicationDomain());
			ldr.contentLoaderInfo.addEventListener(Event.INIT,setFont);
			var url:String = "getEmbedFont.php?font="+fontFamily.toString()+"&str="+encodeURIComponent(mytextarea.text);
			var urlReq:URLRequest = new URLRequest(url);
			//navigateToURL(urlReq);
			ldr.load(urlReq,ldrContext);
 
		}
 
		private function setFont(event:Event):void{
			Alert.show('loaded');
			var loader:Loader = (event.currentTarget as LoaderInfo).loader;
			loader.contentLoaderInfo.removeEventListener(Event.INIT,setFont);
			var FontLibrary:Class = Class(loader.contentLoaderInfo.applicationDomain.getDefinition('MyFont'));
 
			if(FontLibrary == null){
				Alert.show('null font');
			}
			Font.registerFont(FontLibrary);
			mytextarea2.setStyle('fontFamily',"MyFont");
			mytextarea2.text=mytextarea.text;
		}
		]]>
	</mx:Script>
	<mx:Text width="100%" text="上邊框輸入文字並點選字後,下方框會出現載入字型的結果" textAlign="center" fontSize="18"/>
	<mx:TextArea id="mytextarea" text="測試ABCDEFGHIJKL" fontSize="24" width="500" height="300" />
	<mx:HBox>
		<mx:Button label="注音體 1" click="loadfont(0)" fontSize="16"/>
		<mx:Button label="注音體 2" click="loadfont(1)" fontSize="16"/>
		<mx:Button label="簡字體" click="loadfont(2)" fontSize="16"/>
	</mx:HBox>
	<mx:TextArea id="mytextarea2" text="" fontSize="24" width="500" height="300"/>
	<!-- <mx:Button id="set" label="set font" click="setfont()" fontSize="36"/>-->
</mx:Application>

getEmbedFont.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?
$fonts=array("./wp010-05.ttf","./wp010-08.ttf","./wts11.ttf");
$tmp_dir="tmp";
$str=$_GET['str'];
$font=empty($fonts[$_GET['font']])?$fonts[0]:$fonts[$_GET['font']];
$id='ef_'.md5($str.$font);
 
if(!file_exists('tmp/'.$id.'.swf')){
	//建立 MXML 檔案
	$mxml='<?xml version="1.0" encoding="utf-8" ?><movie version="9"><background color="#ffffff"/><frame><library><font name="MyFont" id="MyFont" import="'.$font.'" glyphs="'.addslashes($str).'"/></library></frame></movie>';
	file_put_contents('tmp/'.$id.'.xml', $mxml);
	//轉換 SWF
	exec('swfmill simple tmp/'.$id.'.xml tmp/'.$id.'_font.swf');
	//編譯 SWF LIB
	exec('haxe -swf9 tmp/'.$id.'.swf -swf-lib  tmp/'.$id.'_font.swf Test');
}
 
header('Content-Type: application/x-shockwave-flash');
$swf=file_get_contents("$tmp_dir/$id.swf");
header('Content-Length: '.strlen($swf));
echo $swf;
 
?>

Random Posts

Loading…

:: 把這篇好文推到書籤網站與更多人分享吧 ::
  • funp
  • Hemidemi
  • YahooKimo
  • Google
  • udn
  • Haohao
  • Live

相關文章 :

Ausir FLEX, 程式設計 , , , , ,

  1. 2009年3月6日20:19 | #1

    真是太感謝啦!!流程式正在繪製中了~~
    但要在虛擬主機中執行exe,
    似乎是沒辦法~~
    但有這方法也解決了一大半的問題,
    比先前把文子嵌入好太多了~~

    你的站不錯喔~
    每天都開紅盤喔!

  2. 2009年3月10日13:08 | #2

    其實Flex本來就可以動態改變與讀入Style,你們在上課的時候我就有Demo過了,不需要這麼麻煩. (要使用Flex 2.1以後的版本)

  3. 2009年3月10日13:18 | #3

    老師~可是我們在實測的時候,雖然可以動態讀入的測試
    雖然本機的字型檔都抓得出來
    但是在載入的時候並不是全部的字型都可以用
    中文字也是都沒辦法用
    所以才會在網路上找到這個方法

  4. 2009年3月17日18:21 | #4

    感謝 Ausir 的方案。之前我採用的方式是直接跑 action 把font存成6萬多個 swf,然後去動態呼叫。 GD因為沒有 antialias。所以 try 了一下就不考慮了。之前聽說有高手去修改 php ming 庫來達成動態呼叫中文。不過因為懶的動手,所以也沒有去實作。

  5. 2009年3月17日18:25 | #5

    @野部
    不過這個方法也是硬幹的~

    我覺得還稱不上是好的解決方案~

    待研究! 少字的話還可以用~~字多的話就頭痛嚕!!

  6. 2009年3月18日01:48 | #6

    用這種方法要注意字型的版權歐,就我所知華康是不願意讓人這樣使用,文鼎的話要談年約授權,都是很麻煩的狀況…..

  7. 2009年3月18日04:49 | #7

    老方法的確是硬幹。
    現在都是用我寫在部落格的方法。
    Flex 中文字型包解決技術 at MacroViz
    http://blog.macroviz.com/archives/282
    原文所指的 Embeded Fonts 是在 Flash 8 下內嵌,非 Flex。
    實際上還是執行時期動態掛載的,而且不用算字碼或安裝 Library 在主機上。
    至於字型,我建議是用 open source 的字型。

  8. 2009年3月18日07:53 | #8

    其實目前的方法看來都是一樣的呀,都是利用 flash中的 DefineFont3 來實現嵌入字型的功能,只是負責嵌入動作是 Flash IDE, flex sdk , swfmill 三者之中哪一個而已。所以當有大量不同的字要嵌入時,整個字型的大小還是會大到不行。至於 DefineFont4 我還沒有時間去看它到底可以做到什麼程度,根據spec說他是 OpenType CFF font,這就令人有無限想像呀,只要整體字型大小可以縮小到 Google Droid的大小,就一切都解決了。至於用swfmill+haxe硬幹,主要是因為我當初想要做到類似 sIFR 的功能 請參考http://www.tkalu.com/blog/2009/01/02/53/,所以能夠高速的動態產生便十分重要了

  9. 2009年3月18日10:06 | #9

    tka :

    用這種方法要注意字型的版權歐,就我所知華康是不願意讓人這樣使用,文鼎的話要談年約授權,都是很麻煩的狀況…..

    看來開放授權的字型會比較適合使用~@@

    野部 :

    老方法的確是硬幹。
    現在都是用我寫在部落格的方法。
    Flex 中文字型包解決技術 at MacroViz
    http://blog.macroviz.com/archives/282
    原文所指的 Embeded Fonts 是在 Flash 8 下內嵌,非 Flex。
    實際上還是執行時期動態掛載的,而且不用算字碼或安裝 Library 在主機上。
    至於字型,我建議是用 open source 的字型。

    我也來看一下這個做法~

    tka :

    其實目前的方法看來都是一樣的呀,都是利用 flash中的 DefineFont3 來實現嵌入字型的功能,只是負責嵌入動作是 Flash IDE, flex sdk , swfmill 三者之中哪一個而已。所以當有大量不同的字要嵌入時,整個字型的大小還是會大到不行。至於 DefineFont4 我還沒有時間去看它到底可以做到什麼程度,根據spec說他是 OpenType CFF font,這就令人有無限想像呀,只要整體字型大小可以縮小到 Google Droid的大小,就一切都解決了。至於用swfmill+haxe硬幹,主要是因為我當初想要做到類似 sIFR 的功能 請參考http://www.tkalu.com/blog/2009/01/02/53/,所以能夠高速的動態產生便十分重要了

    不過如果一次多字的話也是會要 LOAD 很久~
    不過如果每次的字串都很少~
    到不失為一個解決方案~
    缺點是要自己架 SERVER @@” 虛擬主機的話就麻煩大條了

    呵呵~

  10. 2009年3月18日12:17 | #10

    能和各位高手在此討論真是過癮。

    虛擬主機上,目前至少做到多 SWF Application 能共用 Client 端字型包,已經滿足了。雖然第一次 Client 都要 Load 比較久。

    除非真的自己架設一個 Font Server 來取代客戶端共用字型。其實真的是有這樣做過,不過覺得很危險…頻寬、主機穩定度、運作成本等都還是要列入考量。而且自己掛,所有客戶就一起掛。

    理想上還是希望 Flash Player 能夠把 TTF 當作 DB,直接撈取,而非一次整個一起下載。目前是有看到有人寫 Java Applet 達成這樣的目標的。不知道 Flash Player 是否會內建這樣的功能。

  11. 2009年3月18日12:26 | #11

    @野部
    我的站 才開了一個月~
    不過我很愛到處在網路上找資料

    承蒙大家賞臉~@@”
    給個面子 到我家坐坐~~
    我常常會無聲無息到到人家玩 ( 偷東西嗎?! )

    不過言歸正傳

    這個問題也不只在 FLASH 發生啦~
    基本上網頁 HTML 製作也是這樣~
    所以文字一般來說還是細明體獲勝
    不然就是要把所有文字轉成圖片
    但是這樣在 SEO 上面就問題了~
    用了 FLEX 或是 FLASH 基本上也早就放棄 SEO 的問題了
    但是字型這個問題還是沒有辦法解決 >”<

    不過這樣說也對~
    我們應該不能要求 FLASH 就內建字型
    因為就好像我們用 PS 做了很美的字型跟排版~ 也不會跟著保留下來
    所以應該是由 SERVER 端 把字型編譯成 SWF 的曲線向量檔再丟給 USER
    所以還是得架一台 FONT SERVER 唯一網路穩定的情況下可能得架個主機代管
    不過這樣自己用的成本就高了
    但是誰會來用這又是另一個問題了
    還有字型授權的問題~~

    不知道未來會不會有這樣的服務出現

  12. 2009年3月18日16:59 | #12

    其實網頁動態內嵌字型的方案很多年前已經出現了。如微軟的 WEFT,配合 Open Type 中文字型,可以動態產生文字。效果和 sIFR 一樣。

    WEFT 的 EOT 檔案,除了 IE 以外,Firefox 3 也支援了。好處是 SEO 方面不影響,美中不足的是 AntiAlias 只有 IE 支援。

    所以目前只有拿來動態產生產品條碼,並無進一步應用。

  13. 2009年3月18日17:05 | #13

    唉~~

    沒有個甚麼好方法 = =
    看來得用微軟正黑體或是新細明體撐著了~

  14. 2009年3月23日16:12 | #14

    很好很强大!很有才,学习了!

  15. 2009年3月23日16:14 | #15

    @ibio

    謝謝~

    您的網站禁止訪問耶~~ 流量破表了

    您的站台應該經營得有聲有色吧~@@ 很想看看

  16. 2009年3月26日16:35 | #16

    YO~ 解決 需要呼叫 haxe+swfmill 的問題了
    同時也不需要每次都下載完整的字型了
    有興趣的話,請參考http://www.tkalu.com/blog/2009/03/26/77/

  17. 2009年3月26日18:04 | #17

    @tka

    來研究研究~

  18. mimo
    2009年11月25日12:07 | #18

    最近遇到內嵌字體的問題,
    剛好參考到你的範例,
    我是用.NET+Flex開發,
    所以將php的頁面改寫成aspx,
    不過想請問一下,
    大大有沒有遇到過字體經過動態字型取得之後英數字符號會轉成全形產生,
    PS 我是用秀風體

  19. 2009年11月26日10:53 | #19

    @mimo

    這只是測試模擬
    實機應該還會有其他問題發生
    可以參考其他留言的資料 ^^

  1. 本篇文章目前尚無任何 trackbacks 和 pingbacks。