20220509 Fontmetrics
title: "Fontmetrics 살펴 보기" date: "2022-05-09"
modified: "2022-05-11"
tl;dr
폴트 설정에 따라 차지하는 실제 공간을 확인해 볼 수 있는 토이 사이트를 개발하고 배포하였다. https://cute-starship-fdd1ab.netlify.app
svelte 공부겸... 소스는 여기있다. https://github.com/taroguru/showfontmetrics
폰트는 얼마의 공간을 차지할까?
웹/앱/프로그램의 핵심은 글을 얼마나 효과적으로 표현하는가 하는 문제이다. 예를 들어 글자 크기를 10px로 설정하였다고 하자. 10px은 어디서 어디까지 일까? 알파벳을 기준으로 대문자의 위부터 아래까지? 아니면 소문자 q같이 아래쪽으로 빠지는(descent) 글자의 아래까지를 다 커버하는 높이일까? 10px이라는 스타일을 지정하면 패딩과 마진을 제외한 순수 폰트는 정확히 10px의 높이로 화면에 표시가 될까? 액센트가 있는 프랑스어는 어떻게 대응하여야 할까? 대문자 위에 액센트가 붙으면 같은 10px인데 영어와 불어는 다른 공간을 차지할까 같은 공간을 차지할까? 이를 위하여 많은 프레임워크에서는 글자의 배치를 표현하기 위하여 폰트매트릭스(FontMetrics) 혹은 그에 준하는 구현을 이용한다. 물논 환경(프레임워크, 라이브러리, 런타임, 브라우저..)마다 미묘하게 베이스라인이 다를 수 있긴하지만 만들려고 만들려는 화면과 개발하는 화면이 틀어질 때
Glyph
폰트의 형태 혹은 개별 심볼의 형태. 보통 폰트라고 하면 이걸 의미한다. https://en.wikipedia.org/wiki/Glyph#Typography
FontMetric에서 주요 속성의 의미
주요 속성은 다음과 같다.
Baseline
폰트의 중심이 되는 선. 알파벳 A를 기준으로 아래에 맞물리는 부분
Ascent
베이스라인으로부터 폰트 최상단까지의 거리. 알파벳 A를 기준으로 위에 맞물리는 부분. 윗첨자까지 커버하여야하지만 오래된 폰트의 경우 폰트 파일에 따라서 ascent가 윗첨자를 커버하지 못하는 경우가 있다. 불어의 경우 액센트 표시가 붙는데 1) 액센트에 대한 높이가 고려되지 않거나 2) 액센트가 이중(!)으로 붙는 경우에 대한 커버가 되지 않거나하는 다양한 예외케이스가 존재할 수 있다. ascent값이 맞지 않는 경우 1) 프로그램으로 다이나믹하게 거리를 조절하거나 2) 폰트 파일을 직접 열어서 높이 값 조절이 필요하다.만. 월드와이드하게 잘 쓰고 있는 폰트는 수정해서 자체 배포하기 보다는 배치(margin, padding, align, line-spacing...)를 잘 바꿔보자.
Descent
베이스라인으로부터 폰트 최하단까지의 거리. 예를 들어 알파벳의 경우 소문자 q의 하단까지 거리. Ascent와 달리 비교적 예외가 적다
Height
Ascent - Descent. 폰트를 10px이라고 설정하고 height값을 땡겨보면 실제로 10px인 경우는 거의 없다. 생각해보면 1) 서체(glyph)마다 형태가 다른데 같은 크기로 구겨서 그릴까? 아니다. 타임스 뉴 로만과 고딕은 실제 화면에 그려지는 글자 크기가 다르다. 스타일로 일반과 굵은 글씨도 높이가 다르다. 굵은 글씨로 처리를 하면 크기를 살짝 줄여서 굵게하는게 아니라 같은 크기의 폰트를 굵게하므로 전체 높이가 높아진다. Height를 픽셀단위로 정확하게 뽑아서 외부 컨테이너 사이즈(ex. div)를 잡으려는 시도는 다국어 적용시 반드시 추가적인 처리를 필요로 한다. linespacing에 자체 마진이 있으니 Height를 픽셀단위로 정확하게 뽑아서 외부 컨테이너 사이즈(ex. div)를 잡으려는 시도는 다국어 적용시 반드시 추가적인 처리를 필요로 한다. linespacing을 잡을 때 보기 좋은 선에서 최대한 벌려두면 다국어 적용시 재앙을 피할 수 있다. 딱 떨어지는게 이쁘다고 생각하고 붙였는데 다국어 대응을 하면 언어마다 벌려야한다. 뽀짝 긴장하자.
TOP
ascent보다 더 위?
Bottom
descent보다 더 아래?
폰트 크기 단위
단위는 뭐가 있을까
px
픽셀
em
상대 크기. 부모
rem
부모 픽셀 기준의 1폰트
ShowFontMetrics
개발 - Show me the Fontmetrics
Fontmetrics를 확인하고, 메트릭(속성)들을 조절하며 화면에 어떻게 표시되는지 간단하게 표시하는 사이트를 만들어보자.
문제들
개발하면서 풀었던 문제들을 정리한다.
getBoundingClientRect is not a function Error in JS
- getBoundingClientRect()는 element에서 얻어올 수 있다.
- return값이 rect이다. 리턴값을 잘 파악하자.
https://bobbyhadz.com/blog/javascript-getboundingclientrect-is-not-a-function
on:bind이용시 변수 변경이 dom 갱신까지 반영된 이후 함수 수행
on:bind를 이용하여 값을 화면에 갱신할 경우, 값을 변경하자 마자 dom이 갱신되지 않는다.
<script>let origin = 1;let element;function changeValue(){origin = 2;console.log(element.textContext); //1출력. 돔갱신 안됨.}</script><div bind:this={element}>{origin}</div><button on:click={changeValue}>변경</button>
돔 갱신 후 갱신된 돔의 값을 땡기려면 어떻게 해야할까?
화면 갱신 틱 이후 값을 땡겨오면 됨
<script>import tick from 'svelte';let origin = 1;let element;async function changeValue(){origin = 2;await tick(); //화면 갱신을 기다림console.log(element.textContext); //2출력. 돔갱신 후 호출.}</script><div bind:this={element}>{origin}</div><button on:click={changeValue}>변경</button>
https://linguinecode.com/post/3-methods-to-run-code-after-dom-update-in-svelte