blob: d52e2417fa776c480a07d2e262880fb9ac290197 [file]
// Copyright 2026 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Based on https://github.com/googlefonts/fontations/pull/1820
#include "core/fxge/skrifa/src/outlines.h"
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <iterator>
#include <string>
#include <string_view>
#include <vector>
#include "core/fxge/skrifa/src/main.rs.h"
void dump_outline(skrifa::Outline& outline);
void skrifa::run(rust::Str font_path) {
// Load the font data
std::string path_str(font_path.data(), font_path.size());
std::ifstream input(path_str, std::ios::binary);
std::vector<uint8_t> bytes((std::istreambuf_iterator<char>(input)),
(std::istreambuf_iterator<char>()));
input.close();
rust::Slice<const uint8_t> slice(bytes);
// Load the font. Note that the bytes vector must live as long as the font
auto font = skrifa::new_font(slice, 0);
if (!font->is_ok()) {
printf("Failed to load font!\n");
return;
}
// Get the PostScript name
std::string name(font->postscript_name());
// And the family name
auto family_name = std::string(font->family_name());
printf("ps name = %s, family name = %s\n", name.c_str(), family_name.c_str());
// How many glyphs?
printf("Font has %d glyphs\n", font->num_glyphs());
// The font's encoding is Adobe standard
assert(font->encoding() == PsEncodingKind::Standard);
// The Adobe standard code for 'x' is 120
auto gid_from_code = font->code_to_gid(120);
// But we also generate a Unicode mapping for glyphs present in the AGL
auto gid = font->unicode_to_gid('x');
assert(gid_from_code == gid);
// Storage for our outline
skrifa::Outline outline;
// Load an unscaled outline
font->unscaled_outline(gid, outline);
dump_outline(outline);
// Load the same outline at 16px
font->scaled_outline(gid, 16.0, outline);
dump_outline(outline);
// Convert glyph name to unicode
uint32_t period_unicode;
assert(skrifa::agl_name_to_unicode("period", period_unicode));
assert(period_unicode == '.');
// Convert unicode to glyph name
uint8_t period_name[64] = {};
assert(
skrifa::agl_unicode_to_name('.', rust::Slice<uint8_t>(period_name, 40)));
assert(std::string_view(reinterpret_cast<const char*>(&period_name[0])) ==
"period");
}
void dump_outline(skrifa::Outline& outline) {
auto point_idx = 0;
for (auto verb : outline.verbs) {
switch (verb) {
case skrifa::PathVerb::MoveTo: {
auto p = outline.points[point_idx];
point_idx += 1;
printf("M%f,%f ", p.x, p.y);
break;
}
case skrifa::PathVerb::LineTo: {
auto p = outline.points[point_idx];
point_idx += 1;
printf("L%f,%f ", p.x, p.y);
break;
}
case skrifa::PathVerb::QuadTo: {
auto c0 = outline.points[point_idx];
auto p = outline.points[point_idx + 1];
point_idx += 2;
printf("Q%f,%f %f,%f ", c0.x, c0.y, p.x, p.y);
break;
}
case skrifa::PathVerb::CurveTo: {
auto c0 = outline.points[point_idx];
auto c1 = outline.points[point_idx + 1];
auto p = outline.points[point_idx + 2];
point_idx += 3;
printf("C%f,%f %f,%f %f,%f ", c0.x, c0.y, c1.x, c1.y, p.x, p.y);
break;
}
case skrifa::PathVerb::Close:
printf("Z");
break;
default:
break;
}
}
printf("\nadvance = %f\n", outline.advance_width);
}