벡터 이미지 편집 앱 Boxy SVG에서 사용자가 좋아하는 로컬 글꼴을 선택할 수 있도록 Local Font Access API를 사용하는 방법

Local Font Access API는 이름, 스타일, 패밀리와 같은 상위 수준 세부정보와 기본 글꼴 파일의 원시 바이트를 비롯하여 로컬에 설치된 사용자의 글꼴 데이터에 액세스하는 메커니즘을 제공합니다. SVG 편집 앱 Boxy SVG에서 이 API를 사용하는 방법을 알아보세요.

토마스 슈타이너
토마스 슈타이너
자렉 폭사
자렉 폭사

소개

(이 도움말은 동영상 형식으로도 제공됩니다.)

Boxy SVG는 벡터 그래픽 편집기입니다. 주요 사용 사례는 SVG 파일 형식으로 그림을 편집하여 삽화, 로고, 아이콘 및 기타 그래픽 디자인 요소를 만드는 것입니다. 폴란드 개발자인 야로슬라프 포크사가 개발했으며 2013년 3월 15일에 처음 출시되었습니다. 야로슬라프는 Boxy SVG 블로그를 운영하면서 앱에 추가한 새 기능을 발표합니다. 이 개발자는 Chromium의 Project Fugu를 적극적으로 지지하며 앱의 아이디어 추적기에 Fugu 태그를 가지고 있습니다.

Project Fugu 아이콘 SVG를 편집하는 Boxy SVG 앱입니다.

Boxy SVG의 로컬 글꼴 액세스 API

야로슬라프가 블로그에 게시한 한 가지 기능은 Local Font Access API였습니다. Local Font Access API를 사용하면 사용자는 로컬에 설치된 글꼴(이름, 스타일, 계열 등 상위 수준 세부정보와 기본 글꼴 파일의 원시 바이트 포함)에 액세스할 수 있습니다. 다음 스크린샷은 내 MacBook에 로컬로 설치된 글꼴에 대한 액세스 권한을 앱에 부여하고 텍스트에 대해 마커 펠트 글꼴을 선택한 방법을 보여줍니다.

Project Fugu 아이콘 SVG를 수정하는 Boxy SVG 앱이 글꼴 선택 도구에 선택된 글꼴 마커 Felt에 설정된 'Project Fugu rocks'라는 텍스트를 추가합니다.

기본 코드는 매우 간단합니다. 사용자가 글꼴 모음 선택 도구를 처음 열면 애플리케이션은 먼저 웹브라우저가 Local Font Access API를 지원하는지 확인합니다.

또한 API의 이전 시험용 버전을 확인하고 있는 경우 사용합니다. 2023년 현재, 이전 API는 실험용 Chrome 플래그를 통해 짧은 기간 동안만 제공되었기 때문에 무시해도 되지만 일부 Chromium 파생 버전에서는 계속 사용할 수 있습니다.

let isLocalFontsApiEnabled = (
  // Local Font Access API, Chrome >= 102
  window.queryLocalFonts !== undefined ||
  // Experimental Local Font Access API, Chrome < 102
  navigator.fonts?.query !== undefined
);

Local Font Access API를 사용할 수 없는 경우 글꼴 모음 선택 도구가 회색으로 바뀝니다. 사용자에게 글꼴 목록 대신 자리표시자 텍스트가 표시됩니다.

if (isLocalFontsApiEnabled === false) {
  showPlaceholder("no-local-fonts-api");
  return;
}

&#39;브라우저에서 로컬 글꼴 액세스 API를 지원하지 않습니다&#39;라는 메시지가 표시된 글꼴 선택 도구

그렇지 않으면 Local Font Access API를 사용하여 운영체제에서 모든 글꼴 목록을 검색합니다. 권한 오류를 제대로 처리하는 데 필요한 try…catch 블록을 확인하세요.

let localFonts;

if (isLocalFontsApiEnabled === true) {
  try {
    // Local Font Access API, Chrome >= 102
    if (window.queryLocalFonts) {
      localFonts = await window.queryLocalFonts();
    }
    // Experimental Local Font Access API, Chrome < 102
    else if (navigator.fonts?.query) {
      localFonts = await navigator.fonts.query({
        persistentAccess: true,
      });
    }
  } catch (error) {
    showError(error.message, error.name);
  }
}

로컬 글꼴 목록을 가져오면 이 목록에서 단순화되고 정규화된 fontsIndex가 생성됩니다.

let fontsIndex = [];

for (let localFont of localFonts) {
  let face = "400";

  // Determine the face name
  {
    let subfamily = localFont.style.toLowerCase();
    subfamily = subfamily.replaceAll(" ", "");
    subfamily = subfamily.replaceAll("-", "");
    subfamily = subfamily.replaceAll("_", "");

    if (subfamily.includes("thin")) {
      face = "100";
    } else if (subfamily.includes("extralight")) {
      face = "200";
    } else if (subfamily.includes("light")) {
      face = "300";
    } else if (subfamily.includes("medium")) {
      face = "500";
    } else if (subfamily.includes("semibold")) {
      face = "600";
    } else if (subfamily.includes("extrabold")) {
      face = "800";
    } else if (subfamily.includes("ultrabold")) {
      face = "900";
    } else if (subfamily.includes("bold")) {
      face = "700";
    }

    if (subfamily.includes("italic")) {
      face += "i";
    }
  }

  let descriptor = fontsIndex.find((descriptor) => {
    return descriptor.family === localFont.family);
  });

  if (descriptor) {
    if (descriptor.faces.includes(face) === false) {
      descriptor.faces.push(face);
    }
  } else {
    let descriptor = {
      family: localFont.family,
      faces: [face],
    };

    fontsIndex.push(descriptor);
  }
}

for (let descriptor of fontsIndex) {
  descriptor.faces.sort();
}

그러면 정규화된 글꼴 색인이 IndexedDB 데이터베이스에 저장되므로 손쉽게 쿼리하고 앱 인스턴스 간에 공유하며 세션 간에 보존할 수 있습니다. Boxy SVG는 Dexie.js를 사용하여 데이터베이스를 관리합니다.

let database = new Dexie("LocalFontsManager");
database.version(1).stores({cache: "family"}).
await database.cache.clear();
await database.cache.bulkPut(fontsIndex);

글꼴 캐시가 포함된 IndexedDB 테이블을 보여주는 Chrome DevTools 스토리지 섹션

데이터베이스가 채워지면 글꼴 선택 도구 위젯이 데이터베이스를 쿼리하고 결과를 화면에 표시할 수 있습니다.

글꼴이 채워진 글꼴 선택 도구

Boxy SVG는 <bx-fontfamilypicker>이라는 맞춤 요소로 목록을 렌더링하고 각 글꼴 목록 항목의 스타일을 지정하여 특정 글꼴 모음으로 표시되도록 합니다. 페이지의 나머지 부분과 분리하기 위해 Boxy SVG는 이 맞춤 요소와 다른 맞춤 요소에 Shadow DOM을 사용합니다.

검사 중인 글꼴 선택 도구(&#39;bx-fontfamiliypicker&#39;라는 맞춤 요소)가 표시된 Chrome DevTools의 Elements 패널

결론

로컬 글꼴 기능은 큰 인기를 누리고 있으며 사용자는 직접 만든 디자인 및 글꼴을 사용하여 즐겁게 사용하고 있습니다. API 형태가 변경되고 기능이 잠시 중단되자 사용자들은 즉시 이를 언급했습니다. 야로슬라프는 위의 스니펫에서 볼 수 있는 방어 패턴으로 코드를 신속하게 변경했습니다. 이 패턴은 최신 Chrome뿐 아니라 최신 버전으로 전환하지 않았을 수 있는 다른 Chromium 파생 버전에서도 작동합니다. Boxy SVG를 사용해 보고 로컬에 설치된 글꼴을 확인하세요. Zapf DingbatsWebdings와 같이 오랫동안 잊혀진 책도 찾아볼 수 있습니다.