Skip to content

Commit

Permalink
fix(🐛): Fix parameter handling in SkTypefaceFontProvider.matchFamilyS…
Browse files Browse the repository at this point in the history
…tyle() (#2518)
  • Loading branch information
wcandillon authored Jul 5, 2024
1 parent cda67f3 commit 5665baa
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 8 deletions.
7 changes: 7 additions & 0 deletions docs/docs/text/text.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ export const HelloWorld = () => {

Once the fonts are loaded, we provide a `matchFont` function that given a font style will return a font object that you can use directly.

:::info

For font matching we recommend using the [Paragraph API](/docs/text/paragraph/) instead.
The APIs belows were made available before the Paragraph API was released.

:::

```tsx twoslash
import {useFonts, Text, matchFont} from "@shopify/react-native-skia";

Expand Down
18 changes: 14 additions & 4 deletions package/cpp/api/JsiSkTypefaceFontProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,20 @@ class JsiSkTypefaceFontProvider
}

JSI_HOST_FUNCTION(matchFamilyStyle) {
auto name = arguments[0].asString(runtime).utf8(runtime);
auto fontStyle = JsiSkFontStyle::fromValue(runtime, arguments[1]);
sk_sp<SkFontStyleSet> set(getObject()->onMatchFamily(name.c_str()));
sk_sp<SkTypeface> typeface(set->matchStyle(*fontStyle));
auto name = count > 0 ? arguments[0].asString(runtime).utf8(runtime) : "";
auto fontStyle =
count > 1 ? JsiSkFontStyle::fromValue(runtime, arguments[1]) : nullptr;
if (name == "" || fontStyle == nullptr) {
throw std::runtime_error("matchFamilyStyle requires a name and a style");
}
auto set = getObject()->onMatchFamily(name.c_str());
if (!set) {
throw std::runtime_error("Could not find font family " + name);
}
auto typeface = set->matchStyle(*fontStyle);
if (!typeface) {
throw std::runtime_error("Could not find font style for " + name);
}
return jsi::Object::createFromHostObject(
runtime, std::make_shared<JsiSkTypeface>(getContext(), typeface));
}
Expand Down
49 changes: 46 additions & 3 deletions package/src/renderer/__tests__/e2e/FontMgr.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,50 @@ describe("FontMgr", () => {
expect(width).not.toEqual([0, 0]);
}
});
// Add test
// * Passing |nullptr| as the parameter for |familyName| will return the
// * default system font.
itRunsE2eOnly("Shouldn't crash the font cannot be resolved", async () => {
const result = await surface.eval(
(Skia, { fonts }) => {
const fontMgr = Skia.TypefaceFontProvider.Make();
(Object.keys(fonts) as (keyof typeof fonts)[]).flatMap((familyName) => {
const typefaces = fonts[familyName];
typefaces.forEach((typeface) => {
const data = Skia.Data.fromBytes(new Uint8Array(typeface));
fontMgr.registerFont(
Skia.Typeface.MakeFreeTypeFaceFromData(data)!,
familyName
);
});
});
let exists1 = true;
let exists2 = true;
let exists3 = true;
try {
fontMgr.matchFamilyStyle("Robot", {
weight: 400,
});
} catch {
exists1 = false;
}
try {
fontMgr.matchFamilyStyle("Roboto", {
weight: 100,
});
} catch {
exists2 = false;
}
try {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
fontMgr.matchFamilyStyle();
} catch {
exists3 = false;
}
return { exists1, exists2, exists3 };
},
{ fonts: testingFonts }
);
expect(result.exists1).toBe(false);
expect(result.exists2).toBe(true);
expect(result.exists3).toBe(false);
});
});
2 changes: 1 addition & 1 deletion package/src/skia/types/Font/FontMgr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import type { FontStyle } from "./Font";
export interface SkFontMgr extends SkJSIInstance<"FontMgr"> {
countFamilies(): number;
getFamilyName(index: number): string;
matchFamilyStyle(name?: string, style?: FontStyle): SkTypeface;
matchFamilyStyle(name: string, style: FontStyle): SkTypeface;
}

0 comments on commit 5665baa

Please sign in to comment.