Tistory View

Android Develop/Font

안드로이드 폰트 아웃라인을 Path로 만들기

God Dangchy What should I do? 2019. 9. 6. 01:44

폰트파일은 아웃라인정보만을 가지고 있다. 이 아웃라인정보의 내부를 채운 것이 보통 글자이다.

폰트의 아웃라인 직선과 Bezier 커브로 그리는 정보가 들어있다. 이 정보를 가지고 화면에 글자를 찍는 방식이다.

이 직선과 Bezier 커브를 안드로이드 Path에서 그대로 지원하기 때문에 폰트의 Outline을 Path객체로 복사해 올 수가 있다.

 

 

Path로 받을 수 있어 Path에서 지원하는 모든 함수를 사용하여 가공할 수 있다. 특히 Affine 2D Matrix를 이용할 수 있다는 장점이 있다.

 

 

Path로 만들기

폰트의 글자들을 Path로 빼는 것은 아주 간단하다.

String sSampleText = "SAMPLE TEXT";

Path  path  = new Path(); // 받을 Path
Paint paint = new Paint();

paint.setTextSize( 100.0F );
paint.getTextPath( sSampleText, 0, sSampleText.length(), 0.0f, paint.getFontSpacing(), path );

canvas.drawPath( path, paint ); // 그리기

Paint의 getTextPath함수로 간단히 처리가 가능하다.  getTextPath의 x, y파리미터는 기준점으로 y값은 baseline을 의미한다. x값은 "0"을 넣었지만 기준점을 실제 0부터 outline을 만들려면 다른 값을 넣어줘야 한다.

 

 

baseline의 정확한 내용을 알고 싶은 독자는 다음의 포스트를 참고하기 바란다.

 

안드로이드 FontMetrics

 

안드로이드 FontMetrics

안드로이드 Canvas에 글자를 쓰려면 우선 서체가 어떻게 생겼는지를 알아야 한다. 다행히도 안드로이드는 이 부분을 Paint class를 통하여 바로 처리할 수 있게 되어 있다. 실제 이 것을 지원해 주지 않는다면 폰..

jamssoft.tistory.com

x값에 어떤 값을 넣어야 하는 지는 다음의 포스트를 참고하기 바란다.

https://jamssoft.tistory.com/143

 

안드로이드 Paint getTextBounds와 정렬

이 글을 읽기전에 우선 다음의 포스트를 읽고 오세요. https://jamssoft.tistory.com/141 안드로이드 FontMetrics 안드로이드 Canvas에 글자를 쓰려면 우선 서체가 어떻게 생겼는지를 알아야 한다. 다행히도 안드..

jamssoft.tistory.com

Path 객체를 바로 이용할 수 있기 때문에, x,y값을 아무값이나 넣고 다음의 방법으로 0.0위치로 Path전체를 바꿀 수도 있다. 하지만 많은 양의 정보를 처리해야 될 경우가 대부분이므로 퍼포먼스문제가 발생하니, 필자는 권장하지 않는다.

 

Path를 (0,0)점으로 옮기는 코드는 다음과 같다.

String sSampleText = "SAMPLE TEXT";

RectF  bounds = new RectF();  // 글자들의 bound
Matrix mat    = new Matrix(); // 변환용 Matrix
Path   path   = new Path();   // 받을 Path
Paint  paint  = new Paint(Paint.ANTI_ALIAS_FLAG);


paint.setTextSize(100.0f);
// outline가져오기 // x y 값은 그냥 아무거나 넣는다.
paint.getTextPath( sSampleText, 0, sSampleText.length(), 0.0f, 0.0f, path );

// bound구하기
path.computeBounds( bounds, true );

// 왼쪽상단기준으로 0으로 이동
mat.postTranslate( -bounds.left, -bounds.top );
path.transform( mat );

//그리기
canvas.drawPath( path, paint );

 

 

Path를 이용하기 때문에 자유로운 변형이 가능하다.

예제코드

String sSampleText = "A";

RectF  bounds = new RectF();  // 글자들의 bound
Matrix mat    = new Matrix(); // 변환용 Matrix
Path   path   = new Path();   // 받을 Path
Paint  paint  = new Paint(Paint.ANTI_ALIAS_FLAG);


paint.setTextSize(100.0f);
// outline가져오기 // x y 값은 그냥 아무거나 넣는다.
paint.getTextPath( sSampleText, 0, sSampleText.length(), 0.0f, 0.0f, path );

// bound구하기
path.computeBounds( bounds, true );

// 왼쪽상단기준으로 0으로 이동
mat.preTranslate( -bounds.left, -bounds.top );

// 화면의 가운데로 이동
mat.preTranslate( canvasW / 2.0f, canvasH / 2.0f );
mat.postRotate( 45.0f, canvasW / 2.0f, canvasH / 2.0f );
mat.preScale( 1.0f, 4.0f );

path.transform( mat );

canvas.drawPath( path, paint );

 

 

 

String sSampleText = "ABCD";

RectF  bounds = new RectF();  // 글자들의 bound
Matrix matN   = new Matrix(); // 변환용 Matrix
Matrix matS   = new Matrix(); // 변환용 Matrix
Paint  paint  = new Paint(Paint.ANTI_ALIAS_FLAG);

Path   path       = new Path();   // 받을 Path
Path   p = new Path();

paint.setTextSize(100.0f);
// outline가져오기 // x y 값은 그냥 아무거나 넣는다.
paint.getTextPath( sSampleText, 0, sSampleText.length(), 0.0f, 0.0f, path );



// bound구하기
path.computeBounds( bounds, true );

// 왼쪽상단기준으로 0으로 이동
matN.preTranslate( -bounds.left, -bounds.top );


//mat.reset();
// 화면의 가운데로 이동
matN.preTranslate( canvasW / 2.0f, canvasH / 2.0f );


matS = new Matrix( matN );
matS.preScale( 1.0f, 0.5f );
matS.preSkew( -1.0f, 0.0f );

path.transform(matS, p );
canvas.drawPath( p, paint );



path.transform(matN, p );
paint.setColor( 0xff000000 );
paint.setStrokeWidth( 2.0f );
paint.setStyle(Paint.Style.STROKE );
canvas.drawPath( p, paint );


paint.setColor( 0xffffffff );
paint.setStyle(Paint.Style.FILL );
canvas.drawPath( p, paint );

 

 

 

결과는 Canvas를 이용하여 처리 할 수 있지만, Canvas로 할 수 없는 작업또한 가능하다.

 

Replies
Reply Write