상세 컨텐츠

본문 제목

플래시 액션스크립트 폰트 관련 폰트 임베디드 폰트 안티앨리어싱 등등,..

ADOBE/ ActionScript

by AlrepondTech 2013. 3. 14. 22:19

본문

반응형

 

 

=================================

=================================

=================================

 

 

출처: http://blog.jidolstar.com/247

 

폰트를 런타임(run time)시 동적으로 불러와서 적용하는 방법은 쉽지는 않다.
왜냐하면 학습할 자료 많지 않기 때문에... 그렇다. 자료가 많지 않는 것이 가장 흠이 아닐까? 


(기초)메인 어플리케이션에 폰트 Embed해서 적용하기


Flex를 처음할 때 쯤(2007년 1월 초)에 Label과 같은 control 컴포넌트에 올라간 글자가 회전될 때 안보여지는 현상을 해결할려고 별짓을 다할때가 생각난다. 이때 TTF 폰트를 Embed

(컴파일시 메인 프로그램에 포함한다는 말이다.)

해서 사용 방법을 터득하게 되어 글자를 회전시킬 수 있었다. 그때 만든 것이 "천문노트 별자리판(Planisphere)" 였다. 

 


천문노트 별자리판 - 폰트 Embed 적용 결과물

폰트를 Embed하면 메인 어플리케이션의 실행파일 자체는 커지지만 안정적으로 폰트를 적용시킬 수 있는 장점이 있다. 그러므로 여러폰트를 적용할 필요가 없는 경우에는 폰트 Embed하는 방법도 좋다.

폰트를 Embed하는 방법은 아주 쉽다.

C:\windows\Fonts

에 있는 TTF 파일의 경로만 연결시키면 된다. 아니면 웹서핑을 통해 TTF파일을 얼마든지 구할 수 있겠다.

 

폰트 Embed 하기 (Language : css)
@font-face {
    src:url("C:\\windows\\Fonts\\ahn_m.ttf");
    fontFamily: "_AhnM";
    advancedAntiAliasing: true;
}
 

이 CSS를 컴파일하면 Flex 컴파일러는 내부적으로 Font.registerFont()를 실행하여 _AhnM 이라는 이름의 폰트를 Embed하게 되는 것이다.(사실, 그냥 그럴 것 같다는 생각이 듬 ㅋ) 
일반 @font-face에 대한 문법은 Using embedded fonts에서 알 수 있다.

CSS를 만든 뒤 아래처럼 사용하면 끝이다.

Embed한 폰트 사용하기 (Language : xml)
<mx:TextArea id="textArea" fontFamily="_AhnM"/>

너무 쉬운 방법이므로 더 자세한 설명이 필요치 않을 것이라 생각한다.

아래 파일은 폰트를 Embed하는 예제이다. 
다음부터 나올 예제도 이것을 기반으로 만들 것이므로 소스를 미리 봐둘 필요가 있을 것이다.

 

ExFontEmbed.zip
다운로드

 

 



위 프로그램은 Font 2개를 Embed했기 때문에 전체 프로그램용량이 무려 3.50 MB이다. 처음 사용하는 사람에게는 프로그램 로딩 압박이 조금 걸려올 것이다. 물론 내 서버도... ㅡㅡ; 만약 Font를 10개 이상 사용하는 경우가 발생할 때는 10MB도 훨씬 넘을 수 있겠다. 바로 사용자를 전혀 고려하지 않는 설계가 되는 것이다.

폰트를 선택(ComboBox, DataGrid)도 해보고 TextArea를 회전도 해보길 바란다. Embed된 폰트를 선택하면 TextArea에 바로 폰트가 적용되는 것을 확인할 수 있을 것이다. 회전할때 Embed된 폰트가 적용된 TextArea는 글자가 깨지지 않는다. 

Font를 Embed해서 사용할때 편한 점은 보안정책에 전혀 개의치 않고 코딩해도 된다는거... 하지만 또 한가지 단점을 말한다면... 컴파일 때 압박이 장난 아니라는거... ㅡㅡ; 그래서 폰트는 1개 정도 Embed할때가 가장 좋은 것 같다는 생각이 든다.


 

(본론)폰트(Font)를 런타임(run time)시 동적으로 로드해서 적용하기

난 여기서 2가지 방법을 말하고자 한다.

  1. CSS기반 SWF 동적폰트 
    css를 swf를 만들어 StyleManager.loadStyleDeclarations()를 이용해 Style Sheet를 등록하는 방법
  2. ActionScript기반 SWF 동적폰트 
    따로 ActionScript 프로젝트를 만들어 Class객체로 Embed한 SWF를 만들고 이것을 로드하여 Font.registerFont()로 등록하는 방법

동적으로 폰트를 로드한다고 해서 Embed하지 않는 것은 아니다. 똑같이 Embed하지만 단지 Embed한 부분이 메인 어플리케이션에 포함되는가 아닌가의 차이를 가진다. 그러므로 다음에 나올 2가지 방법도 기본적으로 Embed하는 방법을 이용한다고 생각해야한다.

 

1. CSS기반 SWF 동적폰트 만들기

 


이 방법은 몇일전에 쓴 [Flex] 런 타임(run-time)시 Style sheets 불러오기를 읽어보면 기본은 공부할 수 있다. 
기본적으로 위 예제에서 Embed할 때 쓰인 2개의 css파일을 이용한다. assets/runtime/ 폴더에 styleFontAhnM.css와 styleFontHYBDAL.css는 각각 @font-face를 이용해 ahn_m.ttf와 HYBDAL.TTF를 사용한다. 이때 이름은 각각 _AhnM과 _HYBDAL로 지정했다.

/assets/realtime/styleFontHYBDAL.css (Language : css)
@font-face {
    src:url("../HYBDAL.TTF");
    fontFamily: "_HYBDAL";
    advancedAntiAliasing: true;
}
 

두 CSS파일을 아래와 같은 방법으로 Compile CSS to SWF 를 체크하도록 한다. 그럼 메인 어플리케이션을 컴파일 할때 이 CSS파일을 자동적으로 bin/assets/realtime 폴더에 SWF파일로 만들어 준다.

 

 


css를 swf로 컴파일하는 방법

 


아래는 Embed했던 위의 예제에서 <mx:Style source=""/>를 빼고, Script부분만 약간 수정된 소스다.




아래는 위 소스에서 Script 일부이다.

 

CSS기반 SWF 폰트 적용법 (Language : java)
private function init():void
{
    acFontList.addItem( {label:"default", data:""} );
    acFontList.addItem( {label:"안상수2006중간", data:"_AhnM"} );
    acFontList.addItem( {label:"HY바다L", data:"_HYBDAL"} );
    loadFont("assets/realtime/styleFontAhnM.swf");
    loadFont("assets/realtime/styleFontHYBDAL.swf");
    //loadFont("http://localhost/styleFontAhnM.swf");
    //loadFont("http://localhost/styleFontHYBDAL.swf");
    viewFontList();  
}

private function loadFont(url:String):void
{
    trace("loadFont::url="+url);
    try
    {
        var event:IEventDispatcher = StyleManager.loadStyleDeclarations( url, truefalse );
        event.addEventListener( Event.COMPLETE, fontLoaded );
    }
    catch(e:Event)
    {
        mx.controls.Alert.show("loadFont::url="+url +", error="+e.toString());
    }
}

private function fontLoaded(event:Event):void
{
    //등록된 폰트를 보여줌
    viewFontList();       
}   

두개의 CSS기반 SWF파일을 loadFont()함수에 url을 넘겨주면 StyleManager.loadStyleDeclarations() 함수를 사용해서 로딩하게 된다. 로드가 완료되면 StyleManager에 위에서 지정한 font를 아래와 같은 방법으로 사용할 수 있다.

CSS기반 SWF파일을 등록한 후 폰트를 사용하는 예 (Language : java)
textArea.setStyle("fontFamily""_AhnM");

만약 웹에서 사용할 것이라면 위코드의 init()에서 주석처리된 것을 풀고 바로 위에 loadFont() 2개는 주석처리한다. 컴파일 한 다음, 메인 어플리케이션과 해당 CSS기반 SWF파일을 동일한 도메인의 웹서버에 올려서 사용하면 되겠다. 

프로그램을 실행하면 아래 화면이 나온다. 화면구성은 폰트를 Embed할 때와 완전히 똑같다.
다른 점은 폰트가 로딩되는 시점이다. 메인 어플리케이션이 로딩된 뒤에야 폰트를 로딩하게 된다.
메인 어플리케이션 프로그램 크기(240KB)도 Embed 할 때(3.5MB)와 비교가 안될 정도로 작아졌다. 
(아래 소스에서 동작폰트 로드하기 위한 서버가 없어 버그처럼 보입니다. 소스를 다운받아 테스트하세요. 2009.11.13)

  



2. ActionScript 기반 SWF 동적폰트 만들기

이미지를 Embed해서 사용할 때, 우리는 다음과 같은 방법 많이 사용한다.


이미지를 Embed해서 Style적용하기 예제 (Language : java)
Embed(source="이미지명");
private var img1:Class
btn1.setStyle("upSkin", img1);

<mx:Button id="btn1"/>



폰트도 이와 같은 방법으로 Embed해서 사용할 수 있다.

ActionScript에서 폰트를 Embed해서 사용하기 (Language : java)
[Embed(source="ahn_m.ttf", fontName="_안상수2006중간", mimeType='application/x-font')]
public var FontClass:Class

Font.registerFont( FontClass );

textArea.setStyle("fontFamily","_안상수2006중간");

<mx:TextArea id="textArea"/>


별로 어렵지 않다는 것을 알 수 있다. Font.registerFont()는 Embed된 폰트 Class를 매개변수로 넘겨주면 자동적으로  Font에 등록시켜주는 역할을 한다. 앞서 직접 코드에 CSS Embed방법과 CSS기반 SWF방법도 내부적으로는 이 Font.registerFont()가 호출될 것이다. 표현방법만 다양할 뿐인 것이다.

어쨌든 위 코드에서는 fontFamily가 "_안상수2006중간"이라는 이름으로 Font에 등록되었다. 등록된 Font는 Font.enumerateFonts()를 이용해 Array 형태로 List해보고 확인할 수 있다. 첨부된 메인 어플리케이션 코드에이를 구현한 viewFontList() 함수가 있으니 확인 바란다.


위의 소스를 다운로드 받아 압축을 풀면 FontAhnM과 FontHYBDAL 폴더가 있을 것이다. 이것은 동적으로 로드할 2개의 폰트를 위한 것으로 ActionScript 프로젝트로 작성된 것이다. 폴더 안에는 TTF파일과 메인 소스가 있다. FontAhnM.as만 보면 다음과 같다.


FontAhnM.as (Language : java)
package 
{
    import flash.display.Sprite;
    
    public class FontAhnM extends Sprite
    {
        [Embed(source="ahn_m.ttf", fontName="_안상수2006중간", mimeType='application/x-font')]
        public static var FontClass:Class
        
        public static var fontName:String="_안상수2006중간"
    }
}


잘보면 금방 언급했던 코드와 동일하다. 단지 fontName이라는 String형태의 이름을 지어줬는데, 이것은 메인 어플리케이션을 보면 이유를 알 수 있을 것이다. 물론 중요한 것은 아니므로 필요시에는 생략해도 무방하겠다.

또 중요한 점은 2변수 모두 static이라는 것이다. 즉, Sprite를 확장한 FontAhnM이지만 그것을 그리 중요하지 않다는 것이다. 즉, 객체 생성없이 FontAhnM.FontClass와 FontAhnM.fontName 을 직접 접근할 수 있겠다.

이것 자체가 완전한 코드라서 컴파일하면 bin폴더에 FontAhnM.swf 파일이 나온다. 동일한 방법으로 FontHYBDAL에 있는 것도 컴파일해서 FontHYBDAL.swf을 얻을 수 있다.
이 2개 파일을 메인 어플리케이션의 /assets/realtime/에 복사한다.(이미 복사되어 있다.)
이렇게 만든 것은 앞으로 ActionScript기반 SWF라 부르겠다.

메인 어플리케이션의 Script만 보면 다음과 같다.


ActionScript기반 SWF를 이용하여 동적으로 폰트를 방법 (Language : java)
[Bindable]
private var acFontList:ArrayCollection = new ArrayCollection();

private function init():void
{
    acFontList.addItem( {label:"default", data:""} );
    loadFont("assets/realtime/FontAhnM.swf");
    loadFont("assets/realtime/FontHYBDAL.swf");
    //loadFont("http://localhost/FontAhnM.swf");
    //loadFont("http://localhost/FontHYBDAL.swf");
    viewFontList();
}

private function loadFont(url:String):void
{
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener( Event.COMPLETE, fontLoaded );
    loader.load(new URLRequest(url));
}

private function fontLoaded(event:Event):void
{
    try
    {
        //url로 부터 로드되는 폰트의 폰트Clash명을 읽어옴
        //단, 제작한 .swf의 파일명과 Class명이 같아야 한다.
        var url:String = event.target.url;
        var fontClassName:String;
        var pattern:RegExp = /\\/g;
        url = url.replace(pattern,"/");
        url = url.substr( url.lastIndexOf("/")+1 );
        fontClassName = url.substr( 0, url.lastIndexOf(".swf"));
        
        //Class를 얻어옴
        var FontLibrary:Class = event.target.applicationDomain.getDefinition(fontClassName) as Class;

        //폰트 등록
        Font.registerFont( FontLibrary.FontClass );

        //System에서 사용하는 폰트 이름과 일반적 폰트 명칭 
        var fontObject:Object = new Object();
        fontObject.label = FontLibrary.fontName;
        fontObject.data = FontLibrary.fontName;
        acFontList.addItem( fontObject );

        //등록된 폰트를 보여줌
        viewFontList();
    } 
    catch( e:Error)
    {
        mx.controls.Alert.show("fontLoaded : "+ e.toString());
    }
}



조금 복잡해보이는 듯하지만 기본은 같다. Loader()클래스를 이용해 이미 만든 두개의 ActionScript기반 SWF를 불러온다. 언제 Load가 완료되었는지 확인하기 위해 Event.COMPLTE 이벤트를 Listen한다. ActionScript 기반 SWF을 성공적으로 읽어오면 fontLoaded()메소드가 호출되고 해당 폰트를 등록하게 된다.

주의해서 볼 사항은 event.target.applicationDomain.getDefinition() 이다. 이것은 지정된 어플리케이션 도메인으로부터 정의된 클래스,네임스페이스, 메소드등의 정의를 읽어오는 역할을 담당한다. 이것을 이용해 앞서 정의한 두개의 클래스 FontAhnM과 FontHYBDAL 클래스 정의를 읽어올 수 있다. 

이 방법은 여기 예제에서 font에만 적용되는 것뿐 아니라 한개의 메인 어플리케이션으로 구성되던 것을 여러개의 SWF 모듈로 분리해서 사용할 때 매우 유용할 수 있겠다. 가령, 글쓰기모듈, 글읽기모듈, 글보기 모듈등을 다 SWF파일로 만들어서 메인 어플리케이션에서 이들 모듈을 동적으로 로드에서 사용할 수 있게 만들 수 있다. 뭐... 이건 그냥 빈말이였고...

Font.registorFont()에 의해 Font가 등록되었으므로 textArea.setStyle("fontFamily", "_안상수2006중간"); 식으로 만들어 사용할 수 있겠다. 

이로써 ActionScript를 이용해 폰트정보를 담은 SWF를 만들고 그것을 동적으로 읽어와 적용하는 방법을 알아보았다.



어떤 방법이 좋을까?

개인마다 다를 것이라 생각한다. 사용하는 난이도도 둘다 비슷하기 때문이다. 하지만 처음 프로젝트를 시작하는 것이라면 아무래도 CSS기반 SWF를 사용하는게 편할것이다. 그러나 무엇을 선택하든지 그것은 프로그래머의 몫이다.


추가사항

이 글을 쓰고 메일을 받았다. Embed하지 않고 시스템에 있는 기본폰트를 적용할 수 없는가였다.
물론 된다. 하지만 Embed할때와는 기본적인 차이가 있다. 
먼저 Embed하는 폰트의 이점과 제한에 대해서 이해해볼 필요가 있을 것이다.

폰트를 Embed할 때 이점을 먼저 언급해보면...
1. 클라이언트 환경에서 폰트 설치가 필요없다.
2. Embed된 폰트는 안티-알리어스(anti-aliased:경계선부분을 부드럽게함)가 된다. 그래서 글자가 더 부드럽게 되고 읽기가 쉬워진다. 이것은 특별히 텍스트 이미지가 커질때 나타난다.
3. Embed된 폰트는 부분적으로나 전체적으로 투명하게 할 수 있다.
4. Embed된 폰트는 회전시킬 수 있다.
5. Embed된 폰트는 줌을 할 때 좀 더 부드럽게 볼 수 있다.
6. Embed된 폰트를 사용할때 Text가 기대한 것대로 정확하게 나타난다. 
7. 폰트를 Embed할때 추가적인 고급 안티-알리어스 정보를 사용할 수 있다. 이에 대해서는 Embedding fonts in ActionScript의 Using advanced anti-aliasing 를 참고한다.

Embed된 폰트의 제한점은 다음과 같다.
1. Embed폰트는 트루타입(TrueType) 폰트만 가능하다. 자세한 정보는 Embedding fonts from SWF files를 참고한다.
2. Embed된 폰트는 메인 어플리케이션의 파일 사이즈를 증가시킨다. 왜냐하면 문서안에 폰트정보가 포함되기 때문이다. 이 결과 사용자는 프로그램을 실행하기 위해 다운로드 시간이 길어질 수 밖에 없다.
3. Ebmed된 폰트는 일반적으로 10pt보다 더 작은 텍스트에 대해서는 가독성이 떨어진다. Embed된 폰트는 안티-알리어스가 적용되기 때문에 작은 사이즈의 텍스트는 희미하고 불명료한 글자로 보일 수 있다. 이것을 피하기 위해 고급 안티-알리어싱을 사용해야한다. 이에 대해서는 Embedding fonts in ActionScript의 Using advanced anti-aliasing 를 참고한다.
4. 어떤 경우에는 Embed된 폰트는 비주얼 컴포넌트 안에서 잘려보일 수 있다. 이러한 경우에는 padding관련 속성을 조정하여 방지할 수 있다. 흔이 있는 경우는 아니다.

이러한 Embed되는 폰트의 특성을 잘 알면 폰트를 Embed해야할지 말아야할지 판단할 수 있을 것이다.
그럼 이러한 경우에 어떨까? 가령, 이미지 에디터에 쓰이는 말풍선에 사용자 System에 있는 font를 적용하고 싶을때는 어떻게 해야할까? 이러한 경우에는 Embed폰트를 사용하지 않는 것이 원칙이겠다. 
http://www.na4.com/ver2/home.htm에 이미지 에디터가 바로 그것인데, 말풍선을 그림에 올려 폰트를 바꾸면 아주 잘 적용된다. 하지만 내가 위에서 든 예제에서는 어떤 폰트는 잘 적용되지 않는 것을 확인할 수 있었다.
아직도 해결되지 않은 점이며 이 글을 읽으시고 어떻게 구현했는지 아시는 분이 있으시면 함께 공유했으면 한다.


참고사이트

AS3 Runtime Font Loading
Runtime Font Embedding in AS3. There is no need to embed the entire fontset anymore  
런타임시 Style Sheet 불러오기 
ApplicationDomain 클래스 
getDefinition() 메소드  
Using Fonts - Flex 3
한글폰트 입력이 가능한 회전하는 TextArea 컴포넌트 만드는 방법
Label위에 올라온 한글 폰트 회전 시키기
회전하는 컴포넌트 위에 글자가 사라지지 않게 하는 방법
천문노트 별자리판(Planisphere)

글쓴이 : 지돌스타(http://blog.jidostar.com/247)

글 쓰는거 힘들다...

 

 

=================================

=================================

=================================

 

 

 

 

 

 

반응형


관련글 더보기

댓글 영역