CSS 글꼴 로딩 모듈 레벨 3

W3C 작업 초안,

이 문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2023/WD-css-font-loading-3-20230406/
최신 게시 버전:
https://www.w3.org/TR/css-font-loading/
편집자 초안:
https://drafts.csswg.org/css-font-loading/
이전 버전:
히스토리:
https://www.w3.org/standards/history/css-font-loading-3
피드백:
CSSWG 이슈 저장소
명세 내 인라인
편집자:
Tab Atkins Jr. (Google)
이전 편집자:
(Mozilla)
이 명세에 대한 편집 제안:
GitHub 편집자

요약

이 CSS 모듈은 글꼴 리소스를 동적으로 로딩하는 데 사용되는 이벤트와 인터페이스를 설명합니다.

CSS는 구조화된 문서(HTML, XML 등)의 렌더링을 화면, 인쇄물 등에서 설명하기 위한 언어입니다.

이 문서의 상태

이 섹션은 문서가 발행된 시점의 상태를 설명합니다. W3C의 최신 발행 목록과 이 기술 보고서의 최신 개정본은 W3C 기술 보고서 색인 https://www.w3.org/TR/에서 확인할 수 있습니다.

이 문서는 CSS 작업 그룹에서 작업 초안으로 권고안 경로를 사용하여 발행되었습니다. 작업 초안으로 발행되었다고 해서 W3C 및 회원의 승인을 의미하지는 않습니다.

이 문서는 초안이며 언제든지 다른 문서로 업데이트, 대체 또는 폐기될 수 있습니다. 진행 중인 작업 외의 용도로 이 문서를 인용하는 것은 적절하지 않습니다.

피드백은 GitHub에 이슈 등록(권장)으로 보내주시고, 제목에 명세 코드 “css-font-loading”을 포함해 주세요. 예시: “[css-font-loading] …의견 요약…”. 모든 이슈와 코멘트는 아카이브됩니다. 또는 (아카이브) 공개 메일링 리스트 www-style@w3.org로 피드백을 보낼 수 있습니다.

이 문서는 2021년 11월 2일 W3C 프로세스 문서의 적용을 받습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C는 그룹의 산출물과 관련해 공개된 특허 공개 목록을 유지하고 있습니다; 해당 페이지에는 특허 공개 방법도 안내되어 있습니다. 개별적으로 필수 청구(Essential Claim(s))가 포함된 특허를 알고 있다면, W3C 특허 정책 6절에 따라 공개해야 합니다.

1. 소개

CSS는 작성자가 @font-face 규칙을 통해 웹에서 커스텀 글꼴을 로드할 수 있도록 합니다. 스타일시트 저작 시에는 사용이 쉽지만, 스크립트를 통해 동적으로 사용하기는 훨씬 더 어렵습니다.

또한, CSS는 사용자 에이전트가 실제로 글꼴을 로드하는 시점을 선택할 수 있게 합니다; 글꼴 페이스가 현재 페이지의 어떤 요소에서도 사용되지 않는 경우, 대부분의 사용자 에이전트는 해당 파일을 다운로드하지 않습니다. 이는 나중에 글꼴 페이스를 사용할 때 사용자 에이전트가 사용을 감지하고 글꼴 파일을 다운로드 및 파싱하기 시작하면서 지연이 발생함을 의미합니다.

이 명세는 CSS의 글꼴 페이스를 위한 스크립팅 인터페이스를 정의하여, 글꼴 페이스를 쉽게 생성(FontFace 인터페이스 사용) 및 스크립트에서 로드(document.fonts 사용)할 수 있게 합니다. 또한 개별 글꼴의 로딩 상태나 전체 페이지의 모든 글꼴의 로딩 상태를 추적하는 방법을 제공합니다.

이 명세의 여러 항목은 일반 ES 객체를 사용하여 동작을 정의하며, 다양한 내부 Promise 사용이나 FontFaceSet의 내부 Set 사용 등이 있습니다. 여기서의 의도는 이러한 객체(및 프로토타입 체인)가 순수하게, 작성자가 한 어떠한 작업에도 영향을 받지 않도록 하는 것입니다. 이것이 좋은 의도일까요? 그렇다면 명세에서 어떻게 표시해야 할까요?

1.1.

이 명세는 Promise를 사용합니다. Promise는 ECMAScript 6에서 정의되어 있습니다. MDN에는 Promise에 대한 좋은 튜토리얼이 있습니다.

1.2. 작업 소스

이 명세가 작업을 큐에 추가할 때마다, "글꼴 로딩" 작업 소스에 작업을 큐에 추가합니다.

2. FontFace 인터페이스

FontFace 인터페이스는 단일로 사용 가능한 글꼴 페이스를 나타냅니다. CSS의 @font-face 규칙은 FontFace 객체를 암묵적으로 정의하거나, url 또는 바이너리 데이터로 수동 생성할 수 있습니다.

typedef (ArrayBuffer or ArrayBufferView) BinaryData;

dictionary FontFaceDescriptors {
  CSSOMString style = "normal";
  CSSOMString weight = "normal";
  CSSOMString stretch = "normal";
  CSSOMString unicodeRange = "U+0-10FFFF";
  CSSOMString variant = "normal";
  CSSOMString featureSettings = "normal";
  CSSOMString variationSettings = "normal";
  CSSOMString display = "auto";
  CSSOMString ascentOverride = "normal";
  CSSOMString descentOverride = "normal";
  CSSOMString lineGapOverride = "normal";
};

enum FontFaceLoadStatus { "unloaded", "loading", "loaded", "error" };

[Exposed=(Window,Worker)]
interface FontFace {
  constructor(CSSOMString family, (CSSOMString or BinaryData) source,
                optional FontFaceDescriptors descriptors = {});
  attribute CSSOMString family;
  attribute CSSOMString style;
  attribute CSSOMString weight;
  attribute CSSOMString stretch;
  attribute CSSOMString unicodeRange;
  attribute CSSOMString variant;
  attribute CSSOMString featureSettings;
  attribute CSSOMString variationSettings;
  attribute CSSOMString display;
  attribute CSSOMString ascentOverride;
  attribute CSSOMString descentOverride;
  attribute CSSOMString lineGapOverride;

  readonly attribute FontFaceLoadStatus status;

  Promise<FontFace> load();
  readonly attribute Promise<FontFace> loaded;
};

"문서"에 대한 모든 언급을 명확히 하여, 객체가 문서 간 이동할 수 있으므로 어떤 문서를 참조하는지 분명하게 해야 합니다.

family, 타입 CSSOMString
style, 타입 CSSOMString
weight, 타입 CSSOMString
stretch, 타입 CSSOMString
unicodeRange, 타입 CSSOMString

이 속성들은 글꼴 페이스의 해당 특성을 나타내며, CSS의 @font-face 규칙에서 정의된 디스크립터와 같습니다. 해당 @font-face 디스크립터와 동일하게 파싱됩니다. 글꼴 매칭 알고리즘에서 사용되며, 그 외에는 영향을 주지 않습니다.

예를 들어, FontFace 객체의 style 값이 "italic"인 경우 기울임꼴 글꼴 페이스를 나타내지만; 해당 글꼴 페이스를 실제로 기울임꼴로 만드는 것은 아닙니다.

가져올 때는 이 속성에 연결된 문자열을 반환합니다.

설정할 때는, 해당 @font-face 디스크립터의 문법에 따라 파싱합니다. 문법에 맞지 않으면, SyntaxError를 발생시킵니다; 맞으면 파싱된 값을 직렬화하여 속성에 설정합니다.

variant, 타입 CSSOMString
featureSettings, 타입 CSSOMString
variationSettings, 타입 CSSOMString
display, 타입 CSSOMString
ascentOverride, 타입 CSSOMString
descentOverride, 타입 CSSOMString
lineGapOverride, 타입 CSSOMString

이 속성들은 같은 의미를 가지며, CSS의 @font-face 규칙의 해당 디스크립터와 동일하게 파싱됩니다.

지원하는 글꼴에서 특정 기능을 켜거나 끕니다. 이전 속성과 달리, 이 속성들은 실제로 글꼴 페이스에 영향을 줍니다.

가져올 때는 이 속성에 연결된 문자열을 반환합니다.

설정할 때는, 해당 @font-face 디스크립터의 문법에 따라 파싱합니다. 문법에 맞지 않으면, SyntaxError를 발생시킵니다; 맞으면 파싱된 값을 직렬화하여 속성에 설정합니다.

status, 타입 FontFaceLoadStatus, 읽기 전용

이 속성은 글꼴 페이스의 현재 상태를 반영합니다. 새로 생성된 FontFace에서는 "unloaded"여야 합니다.

작성자가 글꼴 페이스의 로드를 명시적으로 요청하거나, load() 메서드나 FontFace에서 요청할 때, 또는 사용자 에이전트가 화면에 텍스트를 그릴 때 해당 글꼴 페이스가 필요함을 감지해 암묵적으로 상태가 변경될 수 있습니다.

loaded, 타입 Promise<FontFace>, 읽기 전용

이 속성은 해당 글꼴 페이스의 [[FontStatusPromise]]를 반영합니다.

모든 FontFace 객체는 내부적으로 [[FontStatusPromise]] 슬롯을 가지며, 글꼴의 상태를 추적합니다. 시작 시에는 pending이며, 글꼴이 성공적으로 로드 및 파싱되거나 오류가 발생하면 fulfill 또는 reject됩니다.

모든 FontFace 객체는 내부적으로 [[Urls]][[Data]] 슬롯도 포함하며, 둘 중 하나는 null이고 다른 하나는 null이 아닙니다(생성자에서 전달된 데이터에 따라 설정됨).

2.1. 생성자

FontFace는 글꼴 페이스 파일을 가리키는 URL이나, 글꼴 페이스의 바이너리 표현이 담긴 ArrayBuffer (또는 ArrayBufferView) 를 통해 생성할 수 있습니다.

FontFace(family, source, descriptors) 메서드가 호출되면, 다음 단계를 실행합니다:

  1. font face를 새로운 FontFace 객체로 생성합니다. font facestatus 속성을 "unloaded"로 설정하고, 내부 [[FontStatusPromise]] 슬롯을 새로운 pending Promise 객체로 설정합니다.

    파싱 family 인자와 descriptors 인자의 멤버들을 CSS @font-face 규칙의 해당 디스크립터 문법에 따라 파싱합니다. source 인자가 CSSOMString일 경우, CSS src 디스크립터 문법에 따라 파싱합니다. 파싱이 실패하면, font face[[FontStatusPromise]] 를 "SyntaxError" 이름의 DOMException으로 reject하고, 해당 속성들을 빈 문자열로 설정하며, font facestatus 속성을 "error"로 설정합니다. 성공하면 파싱된 값을 직렬화하여 속성에 설정합니다.

    참고: source 인자로 url만 전달하면 동작하지 않습니다. 반드시 url() 함수로 감싸야 하며, 예시: "url(http://example.com/myFont.woff)". 이 불편함을 통해 여러 대체 글꼴 지정, 각 대체 글꼴의 타입 지정, 로컬 글꼴 참조가 가능합니다.

    base url 정의 필요. 상대 URL을 해석할 때 문서의 URL을 사용할지, 워커에서는 워커의 url을 사용할지, 항상 정의되는지 검토 필요.

    font face를 반환합니다. 만약 font facestatus 가 "error"라면 알고리즘을 종료하고, 그렇지 않으면 나머지 단계는 비동기적으로 완료합니다.

  2. source 인자가 CSSOMString일 경우, font face의 내부 [[Urls]] 슬롯을 해당 문자열로 설정합니다.

    source 인자가 BinaryData일 경우, font face의 내부 [[Data]] 슬롯을 해당 인자로 설정합니다.

  3. font face[[Data]] 슬롯이 null이 아니면, 다음 단계를 동기적으로 실행하는 작업을 큐에 추가합니다:

    1. font facestatus 속성을 "loading"으로 설정합니다.

    2. font face가 포함된 각 FontFaceSet에 대해:

      1. FontFaceSet[[LoadingFonts]] 리스트가 비어 있으면, FontFaceSet을 loading 상태로 전환합니다.

      2. font faceFontFaceSet[[LoadingFonts]] 리스트에 추가합니다.

    비동기적으로, 데이터를 글꼴로 파싱을 시도합니다. 완료되면(성공 또는 실패), 다음 단계를 동기적으로 실행하는 작업을 큐에 추가합니다:

    1. 로드가 성공하면 font face가 파싱된 글꼴을 나타내며, font face[[FontStatusPromise]]font face로 fulfill하고, status 속성을 "loaded"로 설정합니다.

      font face가 포함된 각 FontFaceSet에 대해:

      1. font faceFontFaceSet[[LoadedFonts]] 리스트에 추가합니다.

      2. font faceFontFaceSet[[LoadingFonts]] 리스트에서 제거합니다. 만약 font가 마지막 아이템이었다면(리스트가 비어 있으면), FontFaceSet을 loaded 상태로 전환합니다.

    2. 그 외에는, font face[[FontStatusPromise]] 를 "SyntaxError" 이름의 DOMException으로 reject하고, status 속성을 "error"로 설정합니다.

      font face가 포함된 각 FontFaceSet에 대해:

      1. font faceFontFaceSet[[FailedFonts]] 리스트에 추가합니다.

      2. font faceFontFaceSet[[LoadingFonts]] 리스트에서 제거합니다. 만약 font가 마지막 아이템이었다면(리스트가 비어 있으면), FontFaceSet을 loaded 상태로 전환합니다.

참고: 새로 생성된 FontFace 객체는 문서 또는 워커 쓰레드의 컨텍스트와 연결된 FontFaceSet에 자동으로 추가되지 않습니다. 즉, 새로 생성된 글꼴을 미리 로드할 수 있지만, FontFaceSet에 명시적으로 추가되지 않으면 실제로 사용할 수 없습니다. FontFaceSet에 대한 자세한 설명은 다음 섹션을 참고하세요.

2.2. load() 메서드

load() 메서드는 FontFace에서 url 기반 글꼴 페이스의 데이터를 요청하고 로드하도록 강제합니다. 바이너리 데이터로 생성된 글꼴이나 이미 로딩 중이거나 로드된 글꼴에는 아무런 동작을 하지 않습니다.

load() 메서드가 호출되면, 다음 단계를 실행합니다:

  1. font face를 이 메서드가 호출된 FontFace 객체로 설정합니다.
  2. font face[[Urls]] 슬롯이 null이거나, status 속성이 "unloaded"가 아니라면, font face[[FontStatusPromise]] 를 반환하고, 이후 단계는 중단합니다.
  3. 그렇지 않으면, font facestatus 속성을 "loading"으로 설정하고, font face[[FontStatusPromise]] 를 반환하며, 나머지 알고리즘을 비동기적으로 계속 실행합니다.
  4. font face[[Urls]] 슬롯 값을 사용하여 [CSS-FONTS-3]에 정의된 대로 글꼴을 로드 시도합니다. 이는 @font-face 규칙의 src 디스크립터 값처럼 동작합니다.
  5. 로드 작업이 완료되면(성공 또는 실패), 다음 단계를 동기적으로 실행하는 작업을 큐에 추가합니다:
    1. 로드가 실패하면, font face[[FontStatusPromise]] 를 "NetworkError" 이름의 DOMException으로 reject하고, status 속성을 "error"로 설정합니다.

      font face가 포함된 각 FontFaceSet에 대해:

      1. font faceFontFaceSet[[FailedFonts]] 리스트에 추가합니다.

      2. font faceFontFaceSet[[LoadingFonts]] 리스트에서 제거합니다. 만약 font가 마지막 아이템이었다면(리스트가 비어 있으면), FontFaceSet을 loaded 상태로 전환합니다.

    2. 그 외에는 font face가 로드된 글꼴을 나타내며, font face[[FontStatusPromise]]font face로 fulfill하고, status 속성을 "loaded"로 설정합니다.

      font face가 포함된 각 FontFaceSet에 대해:

      1. font faceFontFaceSet[[LoadedFonts]] 리스트에 추가합니다.

      2. font faceFontFaceSet[[LoadingFonts]] 리스트에서 제거합니다. 만약 font가 마지막 아이템이었다면(리스트가 비어 있으면), FontFaceSet을 loaded 상태로 전환합니다.

사용자 에이전트는 페이지에 글꼴 페이스가 필요하다고 판단하는 시점에 자체적으로 글꼴 로드를 시작할 수 있습니다. 이 경우, 해당 FontFaceload() 메서드를 호출한 것처럼 동작해야 합니다.

참고: 일부 UA는 "글꼴 캐시"를 사용하여, 동일한 글꼴을 한 페이지 또는 동일 origin의 여러 페이지에서 여러 번 다운로드하지 않도록 합니다. 여러 FontFace 객체가 글꼴 캐시의 동일 항목에 매핑될 수 있으며, 이는 FontFace 객체가 FontFaceSet에 속하지 않아도, 동일한 글꼴 데이터를 가리키는 다른 FontFace 객체(다른 페이지에 존재할 수도 있음!)가 이미 로드되었을 경우 예기치 않게 로딩이 시작될 수 있음을 의미합니다.

2.3. CSS의 @font-face 규칙과의 상호작용

CSS @font-face 규칙은 해당하는 FontFace 객체를 자동으로 정의하며, 규칙이 파싱될 때 해당 객체는 문서의 font source에 자동으로 배치됩니다. 이 FontFace 객체는 CSS-연결됨 상태입니다.

@font-face 규칙에 대응하는 FontFace 객체는 family, style, weight, stretch, unicodeRange, variant, featureSettings 속성이 @font-face 규칙의 해당 디스크립터 값과 동일하게 설정됩니다. 두 객체는 양방향으로 연결되어 있습니다: @font-face 디스크립터가 변경되면 즉시 해당 FontFace 속성에도 반영되며, 그 반대도 마찬가지입니다.

FontFace가 문서 간 이동되면 더 이상 CSS-연결됨이 아닙니다.

FontFace 객체의 내부 [[Urls]] 슬롯은 @font-face 규칙의 src 디스크립터 값으로 설정되며, src 디스크립터가 변경되면 해당 값도 반영됩니다.

그 밖에 CSS @font-face 규칙으로 생성된 FontFace 객체는 수동으로 생성한 것과 동일합니다.

@font-face 규칙이 문서에서 제거되면, 해당 FontFace 객체는 더 이상 CSS-연결됨 상태가 아닙니다. 이 연결은 어떤 방법으로도 복원되지 않습니다 (하지만 @font-face를 스타일시트에 다시 추가하면 새로운 FontFace 객체가 생성되어 CSS-연결됨 상태가 됩니다).

@font-face 규칙의 src 디스크립터가 새 값으로 변경되면, 원래 연결된 FontFace 객체는 더 이상 CSS-연결됨이 아닙니다. 새로운 FontFace 객체가 변경된 src를 반영하도록 생성되고 CSS-연결됨 상태가 됩니다. (이 작업은 기존 객체를 제거하고 새 객체를 font sources에 추가합니다.)

2.4. 글꼴 정보 탐색

FontFace 객체에는 글꼴 파일의 내용에 관한 다양한 읽기 전용 정보가 포함됩니다.

[Exposed=(Window,Worker)]
interface FontFaceFeatures {
  /* The CSSWG is still discussing what goes in here */
};

[Exposed=(Window,Worker)]
interface FontFaceVariationAxis {
  readonly attribute DOMString name;
  readonly attribute DOMString axisTag;
  readonly attribute double minimumValue;
  readonly attribute double maximumValue;
  readonly attribute double defaultValue;
};

[Exposed=(Window,Worker)]
interface FontFaceVariations {
  readonly setlike<FontFaceVariationAxis>;
};

[Exposed=(Window,Worker)]
interface FontFacePalette {
  iterable<DOMString>;
  readonly attribute unsigned long length;
  getter DOMString (unsigned long index);
  readonly attribute boolean usableWithLightBackground;
  readonly attribute boolean usableWithDarkBackground;
};

[Exposed=(Window,Worker)]
interface FontFacePalettes {
  iterable<FontFacePalette>;
  readonly attribute unsigned long length;
  getter FontFacePalette (unsigned long index);
};

partial interface FontFace {
  readonly attribute FontFaceFeatures features;
  readonly attribute FontFaceVariations variations;
  readonly attribute FontFacePalettes palettes;
};

참고: 이 읽기 전용 데이터는 작성자가 font-feature-settings, font-variation-settings, @font-palette-values에 어떤 값이 허용되는지 알 수 있도록 돕기 위한 것입니다.

3. FontFaceSet 인터페이스

dictionary FontFaceSetLoadEventInit : EventInit {
  sequence<FontFace> fontfaces = [];
};

[Exposed=(Window,Worker)]
interface FontFaceSetLoadEvent : Event {
  constructor(CSSOMString type, optional FontFaceSetLoadEventInit eventInitDict = {});
  [SameObject] readonly attribute FrozenArray<FontFace> fontfaces;
};

enum FontFaceSetLoadStatus { "loading", "loaded" };

[Exposed=(Window,Worker)]
interface FontFaceSet : EventTarget {
  constructor(sequence<FontFace> initialFaces);

  setlike<FontFace>;
  FontFaceSet add(FontFace font);
  boolean delete(FontFace font);
  undefined clear();

  // events for when loading state changes
  attribute EventHandler onloading;
  attribute EventHandler onloadingdone;
  attribute EventHandler onloadingerror;

  // check and start loads if appropriate
  // and fulfill promise when all loads complete
  Promise<sequence<FontFace>> load(CSSOMString font, optional CSSOMString text = " ");

  // return whether all fonts in the fontlist are loaded
  // (does not initiate load if not available)
  boolean check(CSSOMString font, optional CSSOMString text = " ");

  // async notification that font loading and layout operations are done
  readonly attribute Promise<FontFaceSet> ready;

  // loading state, "loading" while one or more fonts loading, "loaded" otherwise
  readonly attribute FontFaceSetLoadStatus status;
};
ready, 타입 Promise<FontFaceSet>, 읽기 전용

이 속성은 FontFaceSet[[ReadyPromise]] 슬롯을 반영합니다.

Promise 및 사용 방법에 대한 자세한 내용은 § 3.4 ready 속성을 참고하세요.

FontFaceSet(initialFaces)

FontFaceSet 생성자가 호출되면, initialFaces 인자를 반복하여 각 값을 set entries에 추가해야 합니다.

반복 순서

반복 시, 모든 CSS-연결됨 FontFace 객체가 먼저 나오며, 연결된 @font-face 규칙의 문서 순서에 따릅니다. 그 다음에는 CSS-연결되지 않은 FontFace 객체가 삽입 순서대로 나옵니다.

set entries

FontFaceSetfont source라면, set entries§ 4.2 CSS의 @font-face 규칙과의 상호작용에 명시된 대로 초기화됩니다.

그 밖에는 set entries가 처음엔 비어 있습니다.

add(font)

add() 메서드가 호출되면, 다음 단계를 실행합니다:

  1. font가 이미 FontFaceSetset entries에 존재하면, 즉시 알고리즘의 마지막 단계로 이동합니다.

  2. fontCSS-연결됨이면, InvalidModificationError 예외를 throw하고 즉시 이 알고리즘을 종료합니다.

  3. font 인자를 FontFaceSetset entries에 추가합니다.

  4. fontstatus 속성이 "loading"이면:

    1. FontFaceSet[[LoadingFonts]] 리스트가 비어 있으면, FontFaceSet을 loading 상태로 전환합니다.

    2. fontFontFaceSet[[LoadingFonts]] 리스트에 추가합니다.

  5. FontFaceSet를 반환합니다.

delete(font)

delete() 메서드가 호출되면, 다음 단계를 실행합니다:

  1. fontCSS-연결됨이면, false를 반환하고 즉시 알고리즘을 종료합니다.

  2. deletedfontFontFaceSetset entries에서 제거한 결과로 설정합니다.

  3. fontFontFaceSet[[LoadedFonts]] 또는 [[FailedFonts]] 리스트에 존재하면, 해당 리스트에서 제거합니다.

  4. fontFontFaceSet[[LoadingFonts]] 리스트에 존재하면, 해당 리스트에서 제거합니다. font가 마지막 아이템이었다면(리스트가 비어 있으면), FontFaceSet을 loaded 상태로 전환합니다.

  5. deleted를 반환합니다.

clear()

clear() 메서드가 호출되면, 다음 단계를 실행합니다:

  1. FontFaceSetset entries, [[LoadedFonts]] 리스트, [[FailedFonts]] 리스트에서 모든 CSS-연결되지 않은 항목을 제거합니다.

  2. FontFaceSet[[LoadingFonts]] 리스트가 비어 있지 않으면, 모든 항목을 제거하고, FontFaceSet을 loaded 상태로 전환합니다.

FontFaceSet 객체는 내부적으로 [[LoadingFonts]], [[LoadedFonts]], [[FailedFonts]] 슬롯을 가지며, 모두 빈 리스트로 초기화되고, [[ReadyPromise]] 슬롯을 가지며, 이는 새로운 pending Promise로 초기화됩니다.

글꼴 패밀리는 실제로 사용될 때만 로드되므로, 콘텐츠는 글꼴 로딩 시점을 알 필요가 있습니다. 작성자는 여기 정의된 이벤트와 메서드를 활용해 특정 글꼴의 사용 가능 여부에 따라 동작을 더 세밀하게 제어할 수 있습니다.

FontFaceSet 객체는 아래 중 하나라도 참이면 환경에서 pending 상태입니다:

참고: FontFaceSet환경에서 pending 상태가 아니게 되면, 문서의 상태가 더 이상 변하지 않는 한, 작성자는 치수/위치 등이 "정확하다"고 믿을 수 있습니다. 위 조건이 이 보장을 충분히 설명하지 못한다면, 조건을 더 보완해야 합니다.

3.1. 이벤트

글꼴 로드 이벤트를 통해 문서 전체의 글꼴 로딩 동작에 쉽게 대응할 수 있으며, 개별 글꼴마다 직접 감시할 필요가 없습니다. loading 이벤트는 문서가 글꼴을 로드하기 시작할 때 발생하며, loadingdoneloadingerror 이벤트는 문서의 글꼴 로딩이 완료되었을 때 각각 성공적으로 로드된 글꼴과 로드에 실패한 글꼴을 담아 발생합니다.

아래는 FontFaceSet 객체가 IDL 속성으로 반드시 지원해야 하는 이벤트 핸들러(및 대응 이벤트 타입) 목록입니다:

이벤트 핸들러 이벤트 핸들러 이벤트 타입
onloading loading
onloadingdone loadingdone
onloadingerror loadingerror

폰트 로드 이벤트를 발생시키다는 것은 e라는 이름의 이벤트를 FontFaceSet target에 선택적으로 font faces와 함께 발생시키는 것을 의미하며, 단순 이벤트를 발생시키는 것과 동일하나 FontFaceSetLoadEvent 인터페이스를 사용하며 아래 조건을 만족해야 합니다:

  1. fontfaces 속성은 font facestarget에 포함된 FontFace 객체만 필터링한 결과로 초기화됩니다.

특정 FontFaceSet에 대해 FontFaceSet을 loading 상태로 전환 요청이 들어오면, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. font face set을 해당 FontFaceSet으로 설정합니다.
  2. font face setstatus 속성을 "loading"으로 설정합니다.
  3. font face set[[ReadyPromise]] 슬롯이 이미 fulfill된 promise를 가지고 있다면, 새 pending promise로 교체합니다.
  4. loading 이벤트를 font face set발생시키는 작업을 큐에 추가합니다.

특정 FontFaceSet에 대해 FontFaceSet을 loaded 상태로 전환 요청이 들어오면, 사용자 에이전트는 다음 단계를 실행해야 합니다:

  1. font face set을 해당 FontFaceSet으로 설정합니다.

  2. font face set환경에서 pending 상태라면, 환경에서 멈춤 상태로 표시하고, 이 알고리즘을 종료합니다.

  3. font face setstatus 속성을 "loaded"로 설정합니다.

  4. font face set[[ReadyPromise]] 값을 font face set으로 fulfill합니다.

  5. 아래 단계를 동기적으로 실행하는 작업을 큐에 추가합니다:

    1. loaded fontsfont face set[[LoadedFonts]] 슬롯의 (비어 있을 수도 있는) 내용으로 설정합니다.

    2. failed fontsfont face set[[FailedFonts]] 슬롯의 (비어 있을 수도 있는) 내용으로 설정합니다.

    3. [[LoadedFonts]][[FailedFonts]] 슬롯을 빈 리스트로 리셋합니다.

    4. loadingdone 이벤트를 font face setloaded fonts와 함께 발생시킵니다.

    5. font face setfailed fonts가 비어 있지 않으면, loadingerror 이벤트를 font face setfailed fonts와 함께 발생시킵니다.

FontFaceSet환경에서 pending 상태에서 벗어날 때마다, 사용자 에이전트는 아래 단계를 실행해야 합니다:

  1. FontFaceSet환경에서 멈춤 상태이고 [[LoadingFonts]] 리스트가 비어 있으면, FontFaceSet을 loaded 상태로 전환합니다.

  2. FontFaceSet환경에서 멈춤 상태라면, 해당 상태 표시를 해제합니다.

매칭되는 글꼴 페이스를 찾다는 것은 FontFaceSet source에서 주어진 글꼴 문자열 font, 선택적으로 샘플 텍스트 text, 그리고 선택적으로 allow system fonts 플래그와 함께 다음 단계를 실행하는 것을 의미합니다:

  1. fontfont 속성의 CSS 값 문법으로 파싱합니다. 문법 오류가 발생하면, 문법 오류를 반환합니다.

    파싱된 값이 CSS-wide 키워드라면, 문법 오류를 반환합니다.

    모든 상대 길이를 해당 속성의 초기값 기준으로 절대값으로 변환합니다. (예를 들어, boldernormal 기준으로 평가됩니다.)

  2. text가 명시적으로 제공되지 않았다면, 한 개의 공백(U+0020 SPACE)만 담긴 문자열로 설정합니다.
  3. font family listfont에서 파싱된 글꼴 패밀리 목록으로, font stylefont에서 파싱된 기타 스타일 속성으로 설정합니다.
  4. available font facessource사용가능한 글꼴 페이스 목록으로 설정합니다. allow system fonts 플래그가 지정되면, 모든 시스템 글꼴을 available font faces에 추가합니다.
  5. matched font faces를 빈 리스트로 초기화합니다.
  6. font family list의 각 패밀리에 대해, 글꼴 매칭 규칙을 사용해 available font facesfont style에 맞는 글꼴 페이스를 선택하여 matched font faces에 추가합니다. unicodeRange 속성 때문에 한 개 이상의 글꼴 페이스가 선택될 수 있습니다.
  7. matched font faces가 비어 있으면, found faces 플래그를 false로 설정합니다. 아니면 true로 설정합니다.
  8. matched font faces의 각 글꼴 페이스에 대해, 해당 unicode-rangetext의 적어도 한 글자 코드포인트가 포함되지 않으면 리스트에서 제거합니다.

    참고: 따라서 text가 빈 문자열이면, 모든 글꼴이 제거됩니다.

  9. matched font facesfound faces 플래그를 반환합니다.

3.2. load() 메서드

load() 메서드는 FontFaceSet 내 주어진 글꼴 목록의 모든 글꼴이 로드 및 사용 가능 상태인지 판단합니다. 다운로드 가능한 글꼴 중 아직 로드되지 않은 것이 있으면, 사용자 에이전트가 각각의 글꼴 로드를 시작합니다. 이 메서드는 Promise를 반환하며, 모든 글꼴이 정상적으로 로드되어 사용 가능해지면 fulfill되고, 하나라도 정상적으로 로드되지 않으면 reject됩니다.

load( font, text ) 메서드가 호출되면, 다음 단계를 실행합니다:

  1. font face set을 이 메서드가 호출된 FontFaceSet 객체로 설정한다. promise를 새로 생성한 promise 객체로 설정한다.
  2. promise를 반환한다. 나머지 단계는 비동기로 진행한다.
  3. 일치하는 폰트 페이스 찾기font face set에서, 함수에 전달된 fonttext 인자를 사용해 수행하고, font face list에 그 반환값을 할당한다 (found faces 플래그는 무시). 만약 구문 오류가 반환되면, promise를 SyntaxError 예외로 거부하고 이 단계를 종료한다.
  4. 다음 단계를 동기적으로 실행하기 위해 태스크를 큐에 넣는다:
    1. font face list의 모든 폰트 페이스에 대해 load() 메서드를 호출한다.
    2. font face list의 각 폰트 페이스의 [[FontStatusPromise]] 를 모두 기다린 결과로 promise를 resolve한다. (순서대로)

3.3. check() 메서드

check() 메서드는 FontFaceSet에서 주어진 텍스트를 특정 글꼴 목록으로 "안전하게" 렌더링할 수 있는지, 즉 나중에 "글꼴 교체"가 발생하지 않는지 판단합니다. 주어진 텍스트/글꼴 조합이 아직 로드되지 않았거나 로딩 중인 글꼴을 사용하지 않고 렌더링된다면, 이 메서드는 true를 반환하며; 그렇지 않으면 false를 반환합니다.

이 메서드의 동작에는 두 가지 특수 사례가 있으니 주의해야 합니다:

check( font, text) 메서드가 호출되면, 다음 단계를 실행합니다:

  1. font face set을 이 메서드가 호출된 FontFaceSet 객체로 설정합니다.
  2. 매칭되는 글꼴 페이스를 찾는다font face set에서 fonttext 인자와 시스템 글꼴 포함으로 실행하여, 반환된 글꼴 페이스 리스트를 font face list로, 반환된 found faces 플래그를 found faces로 설정합니다. 문법 오류가 반환되면, SyntaxError 예외를 throw하고 단계를 종료합니다.
  3. font face list가 비어 있거나, 모든 글꼴이 status 속성이 "loaded"이거나 시스템 글꼴이라면, true를 반환합니다. 아니면 false를 반환합니다.

3.4. ready 속성

얼마나 많은 글꼴이 로드될지 여부는 주어진 텍스트에 사용되는 글꼴 수에 따라 달라지므로, 어떤 경우에는 글꼴이 로드되어야 하는지 알 수 없습니다. ready 속성은 문서의 글꼴 로딩이 완료될 때 resolve되는 Promise를 포함하며, 작성자가 어떤 글꼴이 로드되었는지 일일이 추적하지 않고도 글꼴 로딩에 영향을 받을 수 있는 콘텐츠를 확인할 수 있게 해줍니다.

참고: ready promise는 한 번만 fulfill되며, 그 이후에도 추가 글꼴이 로드될 수 있습니다. 이는 loadingdone 이벤트를 듣는 것과 유사하지만, ready promise에 전달된 콜백은 해당 글꼴들이 이미 로드된 경우에도 항상 호출됩니다. 어떤 글꼴이 언제 로드되는지 직접 추적할 필요 없이 글꼴 로드에 맞춰 코드를 동기화하는 쉬운 방법입니다.

참고: UA는 ready promise가 fulfill되기 전에 여러 번의 글꼴 로딩을 반복할 수 있습니다. 글꼴 폴백 상황에서는, 글꼴 목록의 한 글꼴이 로드되었으나 특정 글리프가 없어 다른 글꼴을 추가로 로딩해야 하는 경우가 있습니다. ready promise는 레이아웃 작업이 모두 완료되고 추가 글꼴 로드가 필요 없을 때만 fulfill됩니다.

참고:ready 속성이 반환하는 Promise는 항상 fulfill되며, FontFaceload() 메서드가 반환하는 Promise처럼 reject되지 않습니다.

3.5. CSS 글꼴 로딩 및 매칭과의 상호작용

[CSS-FONTS-3]의 글꼴 매칭 알고리즘이 UA에 의해 자동 실행될 때, 매칭에 사용되는 글꼴 페이스 집합은 반드시 문서의 font source에 있는 글꼴들과 모든 로컬 글꼴 페이스 집합이어야 합니다.

UA가 글꼴 페이스를 로드할 필요가 있을 때, 해당 load() 메서드를 해당 FontFace 객체에서 호출해 로드를 시작해야 합니다.

(즉, 객체의 load 속성에 저장된 값을 직접 호출하는 것이 아니라, 동일한 알고리즘을 실행해야 합니다.)

글꼴은 FontFaceSet에 추가될 때 사용 가능합니다. 스타일시트에 새로운 @font-face 규칙을 추가하면, FontFaceFontFaceSet에 추가됩니다. Document 객체의.

@font-face 규칙 추가 예시:

document.styleSheets[0].insertRule(
  "@font-face { font-family: newfont; src: url(newfont.woff); }", 0);
document.body.style.fontFamily = "newfont, serif";

새로운 FontFace 객체를 생성해서 document.fonts에 추가하는 예시:

var f = new FontFace("newfont", "url(newfont.woff)");
document.fonts.add(f);
document.body.style.fontFamily = "newfont, serif";

두 경우 모두 "newfont.woff" 글꼴 리소스의 로딩은 레이아웃 엔진에 의해 시작되며, 다른 @font-face 규칙 글꼴들과 동일하게 로드됩니다.

document.fonts에 추가하지 않으면, 해당 글꼴은 절대 로드되지 않으며, 텍스트는 기본 serif 글꼴로 표시됩니다:

var f = new FontFace("newfont", "url(newtest.woff)", {});

/* new {{FontFace}} not added to {{FontFaceSet}},
   so the 'font-family' property can’t see it,
   and serif will be used instead */
document.body.style.fontFamily = "newfont, serif";

글꼴을 사용하기 전에 미리 로드하고 싶다면, 새 FontFaceFontFaceSet에 추가하는 시점을 로드 완료 후로 미룰 수 있습니다:

var f = new FontFace("newfont", "url(newfont.woff)", {});
f.load().then(function(loadedFace) {
  document.fonts.add(loadedFace);
  document.body.style.fontFamily = "newfont, serif";
});

이 경우, 먼저 "newfont.woff" 리소스를 다운로드합니다. 다운로드가 완료되면, 글꼴을 문서의 FontFaceSet에 추가하고, body 폰트를 변경하며, 레이아웃 엔진이 새 글꼴 리소스를 사용하게 됩니다.

4. FontFaceSource 믹스인

interface mixin FontFaceSource {
  readonly attribute FontFaceSet fonts;
};

Document includes FontFaceSource;
WorkerGlobalScope includes FontFaceSource;

문서, 워커, 기타 글꼴을 사용할 수 있는 모든 컨텍스트는 FontFaceSource 믹스인을 포함해야 합니다. 해당 컨텍스트의 fonts 속성의 값이 해당 컨텍스트의 font source이며, 별도 정의가 없는 한, 글꼴 관련 연산에서 사용되는 모든 글꼴을 제공합니다. "font source"를 참조하는 연산은 해당 연산이 일어나는 컨텍스트의 font source를 참조하는 것으로 해석해야 합니다.

이런 컨텍스트 내에서 발생하는 글꼴 관련 연산의 경우, font sourceFontFace 객체들이 해당 컨텍스트의 사용가능한 글꼴 페이스가 됩니다.

4.1. 워커 FontFaceSources

Worker 문서 내에서 font source는 처음에 비어 있습니다.

참고: FontFace 객체는 평소처럼 생성해 추가할 수 있으며, 이는 워커 내의 CSS 글꼴 매칭(예: OffscreenCanvas에 텍스트를 그릴 때 등)에 영향을 줍니다.

4.2. CSS의 @font-face 규칙과의 상호작용

문서의 set entries는 문서의 font source에 대해, 문서 또는 섀도우 루트의 CSS 스타일시트에 있는 모든 CSS 연결된 FontFace 객체로 처음 채워져야 합니다. 이때 CSS @font-face 규칙의 문서 순서를 따릅니다. @font-face 규칙이 스타일시트에 추가되거나 삭제되거나, @font-face 규칙을 포함하는 스타일시트가 추가되거나 삭제되는 경우, 해당 CSS 연결된 FontFace 객체도 문서의 font source에 추가 또는 삭제되어야 하며, 이 순서를 유지해야 합니다.

수동으로 추가된 FontFace 객체는 CSS-연결됨 객체 뒤에 순서대로 정렬되어야 합니다.

FontFaceSet 객체의 add() 메서드가 CSS-연결됨 FontFace 객체로 호출되면, 이미 집합에 있으면 아무 동작도 하지 않으며; 그렇지 않으면 아무 동작도 하지 않고, InvalidModificationError를 throw해야 합니다.

FontFaceSet 객체의 delete() 메서드가 CSS-연결됨 FontFace 객체로 호출되면, 아무 동작도 하지 않으며, false를 반환해야 합니다.

참고: 작성자는 자동으로 font source에서 제거된 FontFace에 대한 참조를 계속 유지할 수 있습니다. 하지만 § 2.3 CSS의 @font-face 규칙과의 상호작용에서 명시한 대로, 해당 FontFace는 더 이상 CSS-연결됨이 아닙니다.

참고: 향후 명세 버전에서는 로컬 글꼴과의 상호작용 및 질의 방법도 정의될 것으로 예상됩니다.

5. API 예시

모든 글꼴 로드가 완료된 후에만 콘텐츠를 표시하기:
document.fonts.ready.then(function(){
  var content = document.getElementById("content");
  content.style.visibility = "visible";
});
다운로드 가능한 글꼴로 캔버스에 텍스트를 그리기, 글꼴 다운로드를 명시적으로 시작하고 완료 후 텍스트 그리기를 수행:
function drawStuff() {
  var ctx = document.getElementById("c").getContext("2d");

  ctx.fillStyle = "red";
  ctx.font = "50px MyDownloadableFont";
  ctx.fillText("Hello!", 100, 100);
}

document.fonts.load("50px MyDownloadableFont")
              .then(drawStuff, handleError);
리치 텍스트 편집 앱에서 편집 작업 이후 텍스트 요소의 측정이 필요할 수 있습니다. 스타일 변경이 추가 글꼴 다운로드를 요구할 수도, 이미 글꼴이 다운로드되어 있을 수도 있으므로, 측정은 글꼴 로드가 완료된 후에 이루어져야 합니다:
function measureTextElements() {
  // 다운로드 가능한 글꼴의 메트릭을 활용해 콘텐츠 측정 가능
}

function doEditing() {
  // 추가 글꼴 로드를 유발할 수 있는 콘텐츠/레이아웃 작업
  document.fonts.ready.then(measureTextElements);
}
loadingdone 이벤트는 모든 글꼴 관련 로드가 완료되고 텍스트가 추가 글꼴 로드 없이 레이아웃된 후에만 발생합니다:
<style>
@font-face {
  font-family: latin-serif;
  src: url(latinserif.woff) format("woff"); /* 일본어 글리프 없음 */
}
@font-face {
  font-family: jpn-mincho;
  src: url(mincho.woff) format("woff");
}
@font-face {
  font-family: unused;
  src: url(unused.woff);
}

body { font-family: latin-serif, jpn-mincho; }
</style>
<p>納豆はいかがでしょうか

이 경우 UA는 먼저 "latinserif.woff"를 다운로드하고, 일본어 텍스트를 그릴 때 이 글꼴을 사용하려 시도합니다. 해당 글꼴에 일본어 글리프가 없으므로 폴백이 발생하고 "mincho.woff" 글꼴이 다운로드됩니다. 두 번째 글꼴이 다운로드되고 일본어 텍스트가 레이아웃된 후에 loadingdone 이벤트가 발생합니다.

"unused" 글꼴은 로드되지 않으며, 해당 글꼴을 사용하는 텍스트가 없으므로 UA가 로드를 시도하지도 않습니다. loadingdone 이벤트에 영향을 주지 않습니다.

변경 사항

2014년 5월 CSS 글꼴 로딩 마지막 호출 작업 초안 이후의 변경 사항:

감사의 글

Google Fonts 팀의 여러 멤버들이 글꼴 로드 이벤트에 대해 유익한 피드백을 주었으며, Boris Zbarsky, Jonas Sicking, ms2ger 역시 많은 도움을 주었습니다.

개인정보 보호 고려사항

FontFaceSet 객체는 사용자의 설치된 글꼴에 대한 정보를 누설할 수 있지만, 이는 기존 @font-face 규칙과 동일한 방식입니다. 새로운 정보가 누설되거나 더 쉽게 접근할 수 있게 되는 것은 아닙니다.

보안 고려사항

이 명세에 대해 제기된 보안 고려사항은 없습니다.

적합성

문서 규칙

적합성 요구사항은 설명적 명제와 RFC 2119 용어의 조합으로 표현됩니다. “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL” 등의 단어는 이 명세의 규범적 부분에서 RFC 2119에 명시된 대로 해석되어야 합니다. 다만, 가독성을 위해 이 명세에서는 이러한 단어들이 모두 대문자로 표기되지 않습니다.

이 명세의 모든 텍스트는 명시적으로 비규범적임을 표시한 부분, 예시, 노트를 제외하고 규범적입니다. [RFC2119]

이 명세의 예시는 “for example”이라는 단어로 시작하거나 class="example"로 구분되어, 아래와 같이 규범적 텍스트와 구분됩니다:

이것은 정보 제공용 예시입니다.

정보용 노트는 “Note”라는 단어로 시작하며 class="note"로 구분되어, 아래와 같이 규범적 텍스트와 구분됩니다:

Note, 이것은 정보 제공용 노트입니다.

권고문은 규범적 섹션 중 특별한 주의를 환기하도록 스타일링되며 <strong class="advisement">으로 구분되어 아래와 같이 표시됩니다: UA는 반드시 접근 가능한 대안을 제공해야 합니다.

적합성 클래스

이 명세에 대한 적합성은 세 가지 적합성 클래스로 정의됩니다:

스타일시트
CSS 스타일시트.
렌더러
UA는 스타일시트의 의미를 해석하고 이를 사용하는 문서를 렌더링합니다.
저작 도구
UA는 스타일시트를 작성합니다.

스타일시트가 이 명세에 적합하다고 인정받으려면, 이 모듈에서 정의된 문법을 사용하는 모든 명령문이 CSS 일반 문법과 각 기능별 개별 문법에 따라 유효해야 합니다.

렌더러가 이 명세에 적합하려면, 스타일시트를 적절한 명세에 따라 해석하는 것 외에도, 이 명세에서 정의된 모든 기능을 올바르게 파싱하고 문서를 그에 맞게 렌더링해야 합니다. 단, 디바이스의 한계로 인해 UA가 문서를 올바르게 렌더링하지 못하는 경우 UA가 비적합하다고 볼 수 없습니다. (예를 들어, UA가 흑백 모니터에서 색상을 렌더링할 필요는 없습니다.)

저작 도구가 이 명세에 적합하려면, CSS 일반 문법과 각 기능별 개별 문법에 맞게 스타일시트를 올바르게 작성하고, 이 모듈에서 설명된 스타일시트의 모든 적합성 요구사항을 충족해야 합니다.

부분 구현

작성자가 forward-compatible 파싱 규칙을 활용해 폴백 값을 지정할 수 있도록, CSS 렌더러는 지원하지 않는 at-rule, 속성, 속성값, 키워드 등 사용 불가능한 구문 구조를 반드시 무효로 처리하고 적절하게 무시해야 합니다. 특히, UA는 지원하지 않는 구성 값만 선택적으로 무시하고 지원되는 값만 적용해서는 안 됩니다. 어떤 값이 무효(지원되지 않는 값)로 간주되면 CSS는 전체 선언을 무시하도록 요구합니다.

불안정 및 독점 기능의 구현

향후 안정적인 CSS 기능과 충돌하지 않도록, CSSWG는 최적 구현 방법을 따라 불안정 기능과 독점 확장을 구현할 것을 권장합니다.

비실험적 구현

명세가 후보 권고(Candidate Recommendation) 단계에 도달하면 비실험적 구현이 가능하며, 구현자는 명세에 맞게 올바르게 구현됐음을 입증할 수 있는 모든 CR 레벨 기능에 대해 prefix 없는 구현을 제공해야 합니다.

CSS의 구현 간 상호운용성을 확보·유지하기 위해, CSS 작업 그룹은 비실험적 CSS 렌더러가 어떤 CSS 기능의 prefix 없는 구현을 릴리즈하기 전에 해당 구현 보고서(필요시 테스트케이스 포함)를 W3C에 제출할 것을 요청합니다. W3C에 제출된 테스트케이스는 CSS 작업 그룹의 검토와 수정 대상이 됩니다.

테스트케이스 및 구현 보고서 제출에 대한 추가 정보는 CSS 작업 그룹 웹사이트 https://www.w3.org/Style/CSS/Test/에서 확인할 수 있습니다. 문의는 public-css-testsuite@w3.org 메일링 리스트로 하시기 바랍니다.

색인

이 명세에서 정의된 용어

참조로 정의된 용어

참고 문헌

규범적 참고 문헌

[CSS-FONT-LOADING-3]
Tab Atkins Jr.. CSS Font Loading Module Level 3. 2014년 5월 22일. WD. URL: https://www.w3.org/TR/css-font-loading-3/
[CSS-FONTS-3]
John Daggett; Myles Maxfield; Chris Lilley. CSS Fonts Module Level 3. 2018년 9월 20일. REC. URL: https://www.w3.org/TR/css-fonts-3/
[CSS-FONTS-4]
John Daggett; Myles Maxfield; Chris Lilley. CSS Fonts Module Level 4. 2021년 12월 21일. WD. URL: https://www.w3.org/TR/css-fonts-4/
[CSS-FONTS-5]
Myles Maxfield; Chris Lilley. CSS Fonts Module Level 5. 2021년 12월 21일. WD. URL: https://www.w3.org/TR/css-fonts-5/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 2021년 12월 24일. CR. URL: https://www.w3.org/TR/css-syntax-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 2022년 10월 19일. WD. URL: https://www.w3.org/TR/css-values-4/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 2021년 8월 26일. WD. URL: https://www.w3.org/TR/cssom-1/
[DOM]
Anne van Kesteren. DOM Standard. 현행 표준. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; 외. HTML Standard. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. 현행 표준. URL: https://webidl.spec.whatwg.org/

IDL 색인

typedef (ArrayBuffer or ArrayBufferView) BinaryData;

dictionary FontFaceDescriptors {
  CSSOMString style = "normal";
  CSSOMString weight = "normal";
  CSSOMString stretch = "normal";
  CSSOMString unicodeRange = "U+0-10FFFF";
  CSSOMString variant = "normal";
  CSSOMString featureSettings = "normal";
  CSSOMString variationSettings = "normal";
  CSSOMString display = "auto";
  CSSOMString ascentOverride = "normal";
  CSSOMString descentOverride = "normal";
  CSSOMString lineGapOverride = "normal";
};

enum FontFaceLoadStatus { "unloaded", "loading", "loaded", "error" };

[Exposed=(Window,Worker)]
interface FontFace {
  constructor(CSSOMString family, (CSSOMString or BinaryData) source,
                optional FontFaceDescriptors descriptors = {});
  attribute CSSOMString family;
  attribute CSSOMString style;
  attribute CSSOMString weight;
  attribute CSSOMString stretch;
  attribute CSSOMString unicodeRange;
  attribute CSSOMString variant;
  attribute CSSOMString featureSettings;
  attribute CSSOMString variationSettings;
  attribute CSSOMString display;
  attribute CSSOMString ascentOverride;
  attribute CSSOMString descentOverride;
  attribute CSSOMString lineGapOverride;

  readonly attribute FontFaceLoadStatus status;

  Promise<FontFace> load();
  readonly attribute Promise<FontFace> loaded;
};

[Exposed=(Window,Worker)]
interface FontFaceFeatures {
  /* The CSSWG is still discussing what goes in here */
};

[Exposed=(Window,Worker)]
interface FontFaceVariationAxis {
  readonly attribute DOMString name;
  readonly attribute DOMString axisTag;
  readonly attribute double minimumValue;
  readonly attribute double maximumValue;
  readonly attribute double defaultValue;
};

[Exposed=(Window,Worker)]
interface FontFaceVariations {
  readonly setlike<FontFaceVariationAxis>;
};

[Exposed=(Window,Worker)]
interface FontFacePalette {
  iterable<DOMString>;
  readonly attribute unsigned long length;
  getter DOMString (unsigned long index);
  readonly attribute boolean usableWithLightBackground;
  readonly attribute boolean usableWithDarkBackground;
};

[Exposed=(Window,Worker)]
interface FontFacePalettes {
  iterable<FontFacePalette>;
  readonly attribute unsigned long length;
  getter FontFacePalette (unsigned long index);
};

partial interface FontFace {
  readonly attribute FontFaceFeatures features;
  readonly attribute FontFaceVariations variations;
  readonly attribute FontFacePalettes palettes;
};

dictionary FontFaceSetLoadEventInit : EventInit {
  sequence<FontFace> fontfaces = [];
};

[Exposed=(Window,Worker)]
interface FontFaceSetLoadEvent : Event {
  constructor(CSSOMString type, optional FontFaceSetLoadEventInit eventInitDict = {});
  [SameObject] readonly attribute FrozenArray<FontFace> fontfaces;
};

enum FontFaceSetLoadStatus { "loading", "loaded" };

[Exposed=(Window,Worker)]
interface FontFaceSet : EventTarget {
  constructor(sequence<FontFace> initialFaces);

  setlike<FontFace>;
  FontFaceSet add(FontFace font);
  boolean delete(FontFace font);
  undefined clear();

  // events for when loading state changes
  attribute EventHandler onloading;
  attribute EventHandler onloadingdone;
  attribute EventHandler onloadingerror;

  // check and start loads if appropriate
  // and fulfill promise when all loads complete
  Promise<sequence<FontFace>> load(CSSOMString font, optional CSSOMString text = " ");

  // return whether all fonts in the fontlist are loaded
  // (does not initiate load if not available)
  boolean check(CSSOMString font, optional CSSOMString text = " ");

  // async notification that font loading and layout operations are done
  readonly attribute Promise<FontFaceSet> ready;

  // loading state, "loading" while one or more fonts loading, "loaded" otherwise
  readonly attribute FontFaceSetLoadStatus status;
};

interface mixin FontFaceSource {
  readonly attribute FontFaceSet fonts;
};

Document includes FontFaceSource;
WorkerGlobalScope includes FontFaceSource;

이슈 색인

이 명세의 여러 항목은 일반 ES 객체를 사용하여 동작을 정의하며, 다양한 내부 Promise 사용이나 FontFaceSet의 내부 Set 사용 등이 있습니다. 여기서의 의도는 이러한 객체(및 프로토타입 체인)가 순수하게, 작성자가 한 어떠한 작업에도 영향을 받지 않도록 하는 것입니다. 이것이 좋은 의도일까요? 그렇다면 명세에서 어떻게 표시해야 할까요?
"문서"에 대한 모든 언급을 명확히 하여, 객체가 문서 간 이동할 수 있으므로 어떤 문서를 참조하는지 분명하게 해야 합니다.
base url 정의 필요. 상대 URL을 해석할 때 문서의 URL을 사용할지, 워커에서는 워커의 url을 사용할지, 항상 정의되는지 검토 필요.
FontFace가 문서 간 이동되면 더 이상 CSS-연결됨이 아닙니다.