[canvaskit] Add docs/types for Font and related.

Paragraph will be its own CL.

Bug: skia:10717
Change-Id: I5c0d0ff40b500ec8f8eb74e7a44402a9e9548f8e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/321519
Reviewed-by: Kevin Lubick <kjlubick@google.com>
This commit is contained in:
Kevin Lubick 2020-10-02 09:08:07 -04:00
parent a2535afd56
commit 166d633c89
4 changed files with 410 additions and 18 deletions

View File

@ -10,6 +10,7 @@ import {
SkCanvas,
SkColorFilter,
SkFont,
SkFontMgr,
SkImage,
SkImageFilter,
SkImageInfo,
@ -22,6 +23,7 @@ import {
SkShader,
SkSurface,
SkTextBlob,
SkTypeface,
SkVertices,
TypedArray,
} from "canvaskit-wasm";
@ -32,6 +34,8 @@ CanvasKitInit({locateFile: (file: string) => '/node_modules/canvaskit/bin/' + fi
colorTests(CK);
imageFilterTests(CK);
imageTests(CK);
fontTests(CK);
fontMgrTests(CK);
mallocTests(CK);
maskFilterTests(CK);
matrixTests(CK);
@ -39,7 +43,9 @@ CanvasKitInit({locateFile: (file: string) => '/node_modules/canvaskit/bin/' + fi
pathEffectTests(CK);
pathTests(CK);
rectangleTests(CK);
shapedTextTests(CK);
surfaceTests(CK);
textBlobTests(CK);
});
// In an effort to keep these type-checking tests easy to read and understand, we can "inject"
@ -190,6 +196,59 @@ function imageFilterTests(CK: CanvasKit, colorFilter?: SkColorFilter) {
CK.FilterQuality.None, filter6);
}
function fontTests(CK: CanvasKit, face?: SkTypeface, paint?: SkPaint) {
if (!face || !paint) return;
const font = new CK.SkFont(); // $ExpectType SkFont
const f2 = new CK.SkFont(face); // $ExpectType SkFont
const f3 = new CK.SkFont(null); // $ExpectType SkFont
const f4 = new CK.SkFont(face, 20); // $ExpectType SkFont
const f5 = new CK.SkFont(null, 20); // $ExpectType SkFont
const f6 = new CK.SkFont(null, 20, 2, 3); // $ExpectType SkFont
const f7 = new CK.SkFont(face, 20, 4, 5); // $ExpectType SkFont
const glyphMalloc = CK.MallocGlyphIDs(20);
const someGlyphs = [1, 2, 3, 4, 5];
const glyphBounds = font.getGlyphBounds(glyphMalloc, paint); // $ExpectType Float32Array
font.getGlyphBounds(someGlyphs, null, glyphBounds);
const ids = font.getGlyphIDs('abcd');
font.getGlyphIDs('efgh', 4, ids);
const widths = font.getGlyphWidths(glyphMalloc, paint);
font.getGlyphWidths(someGlyphs, null, widths);
font.getScaleX();
font.getSize();
font.getSkewX();
font.getTypeface();
const w2 = font.getWidths('abcdefg'); // $ExpectType number[]
const w = font.measureText('abc'); // $ExpectType number
font.setEdging(CK.FontEdging.Alias);
font.setEmbeddedBitmaps(true);
font.setHinting(CK.FontHinting.Slight);
font.setLinearMetrics(true);
font.setScaleX(5);
font.setSize(15);
font.setSkewX(2);
font.setSubpixel(true);
font.setTypeface(null);
font.setTypeface(face);
}
function fontMgrTests(CK: CanvasKit) {
const fm = CK.SkFontMgr.RefDefault(); // $ExpectType SkFontMgr
const buff1 = new ArrayBuffer(10);
const buff2 = new ArrayBuffer(20);
const fm2 = CK.SkFontMgr.FromData(buff1, buff2);
fm.countFamilies();
fm.getFamilyName(0);
const tf = fm.makeTypefaceFromData(buff1); // $ExpectType SkTypeface
}
function paintTests(CK: CanvasKit, colorFilter?: SkColorFilter, imageFilter?: SkImageFilter,
maskFilter?: SkMaskFilter, pathEffect?: SkPathEffect, shader?: SkShader) {
if (!colorFilter || !colorFilter || !imageFilter || !maskFilter || !pathEffect || !shader) {
@ -364,6 +423,27 @@ function matrixTests(CK: CanvasKit) {
const matr13 = m44.transpose([4, 5, 8]); // $ExpectType number[]
}
function rectangleTests(CK: CanvasKit) {
const rectOne = CK.LTRBRect(5, 10, 20, 30); // $ExpectType Float32Array
const rectTwo = CK.XYWHRect(5, 10, 15, 20); // $ExpectType Float32Array
const iRectOne = CK.LTRBiRect(105, 110, 120, 130); // $ExpectType Int32Array
const iRectTwo = CK.XYWHiRect(105, 110, 15, 20); // $ExpectType Int32Array
const rrectOne = CK.RRectXY(rectOne, 3, 7); // $ExpectType Float32Array
}
function shapedTextTests(CK: CanvasKit, textFont?: SkFont) {
if (!textFont) return;
const shaped = new CK.ShapedText({ // $ExpectType ShapedText
font: textFont,
leftToRight: true,
text: 'this is shaped',
width: 20,
});
const bounds = shaped.getBounds();
shaped.getBounds(bounds);
}
function surfaceTests(CK: CanvasKit) {
const canvasEl = document.querySelector('canvas') as HTMLCanvasElement;
const surfaceOne = CK.MakeCanvasSurface(canvasEl)!; // $ExpectType SkSurface
@ -401,10 +481,19 @@ function surfaceTests(CK: CanvasKit) {
CK.SkColorSpace.ADOBE_RGB)!;
}
function rectangleTests(CK: CanvasKit) {
const rectOne = CK.LTRBRect(5, 10, 20, 30); // $ExpectType Float32Array
const rectTwo = CK.XYWHRect(5, 10, 15, 20); // $ExpectType Float32Array
const iRectOne = CK.LTRBiRect(105, 110, 120, 130); // $ExpectType Int32Array
const iRectTwo = CK.XYWHiRect(105, 110, 15, 20); // $ExpectType Int32Array
const rrectOne = CK.RRectXY(rectOne, 3, 7); // $ExpectType Float32Array
function textBlobTests(CK: CanvasKit, font?: SkFont, path?: SkPath) {
if (!font || !path) return;
const tb = CK.SkTextBlob; // less typing
const ids = font.getGlyphIDs('abc');
const mXforms = CK.Malloc(Float32Array, ids.length * 4);
const blob = tb.MakeFromGlyphs([5, 6, 7, 8], font); // $ExpectType SkTextBlob
const blob1 = tb.MakeFromGlyphs(ids, font); // $ExpectType SkTextBlob
const blob2 = tb.MakeFromRSXform('cdf', mXforms, font); // $ExpectType SkTextBlob
const blob3 = tb.MakeFromRSXform('c', [-1, 0, 2, 3], font); // $ExpectType SkTextBlob
const blob4 = tb.MakeFromRSXformGlyphs([3, 6], mXforms, font); // $ExpectType SkTextBlob
const blob5 = tb.MakeFromRSXformGlyphs(ids, [-1, 0, 2, 3], font); // $ExpectType SkTextBlob
const blob6 = tb.MakeFromText('xyz', font); // $ExpectType SkTextBlob
const blob7 = tb.MakeOnPath('tuv', path, font); // $ExpectType SkTextBlob
const blob8 = tb.MakeOnPath('tuv', path, font, 10); // $ExpectType SkTextBlob
}

View File

@ -134,6 +134,13 @@ export interface CanvasKit {
*/
Malloc(typedArray: TypedArrayConstructor, len: number): MallocObj;
/**
* As Malloc but for GlyphIDs. This helper exists to make sure the JS side and the C++ side
* stay in agreement with how wide GlyphIDs are.
* @param len - number of GlyphIDs to make space for.
*/
MallocGlyphIDs(len: number): MallocObj;
/**
* Free frees the memory returned by Malloc.
* Any memory allocated by CanvasKit.Malloc needs to be released with CanvasKit.Free.
@ -205,14 +212,18 @@ export interface CanvasKit {
getSkDataBytes(data: SkData): Uint8Array;
// Constructors, i.e. things made with `new CanvasKit.Foo()`;
readonly ShapedText: ShapedTextConstructor;
readonly SkFont: SkFontConstructor;
readonly SkPaint: DefaultConstructor<SkPaint>;
readonly SkPath: SkPathConstructorAndFactory;
// Factories, i.e. things made with CanvasKit.Foo.MakeTurboEncapsulator()
readonly SkColorFilter: SkColorFilterFactory;
readonly SkFontMgr: SkFontMgrFactory;
readonly SkImageFilter: SkImageFilterFactory;
readonly SkMaskFilter: SkMaskFilterFactory;
readonly SkPathEffect: SkPathEffectFactory;
readonly SkTextBlob: SkTextBlobFactory;
// Misc
readonly SkColorMatrix: ColorMatrixHelpers;
@ -225,15 +236,17 @@ export interface CanvasKit {
readonly BlurStyle: BlurStyleEnumValues;
readonly ClipOp: ClipOpEnumValues;
readonly ColorType: ColorTypeEnumValues;
readonly ImageFormat: ImageFormatEnumValues;
readonly FillType: FillTypeEnumValues;
readonly FilterQuality: FilterQualityEnumValues;
readonly FontEdging: FontEdgingEnumValues;
readonly FontHinting: FontHintingEnumValues;
readonly ImageFormat: ImageFormatEnumValues;
readonly PaintStyle: PaintStyleEnumValues;
readonly PathOp: PathOpEnumValues;
readonly PointMode: PointModeEnumValues;
readonly SkColorSpace: ColorSpaceEnumValues;
readonly StrokeCap: StrokeCapEnumValues;
readonly StrokeJoin: StrokeJoinEnumValues;
readonly SkColorSpace: ColorSpaceEnumValues;
readonly TileMode: TileModeEnumValues;
// Constants
@ -363,6 +376,13 @@ export interface ShapedText extends EmbindObject<ShapedText> {
getBounds(outputArray?: SkRect): SkRect;
}
export interface ShapedTextOpts {
text: string;
font: SkFont;
leftToRight: boolean;
width: number;
}
/**
* See SkAnimatedImage.h for more information on this class.
*/
@ -793,7 +813,7 @@ export interface SkCanvas extends EmbindObject<SkCanvas> {
}
/**
* See SkColorFilter.h for more on this class. The objects returned are opaque.
* See SkColorFilter.h for more on this class. The objects are opaque.
*/
export type SkColorFilter = EmbindObject<SkColorFilter>;
@ -811,7 +831,153 @@ export interface SkData extends EmbindObject<SkData> {
* See SkFont.h for more on this class.
*/
export interface SkFont extends EmbindObject<SkFont> {
todo: number; // TODO(kjlubick)
/**
* Retrieves the bounds for each glyph in glyphs.
* If paint is not null, its stroking, SkPathEffect, and SkMaskFilter fields are respected.
* These are returned as flattened rectangles. For each glyph, there will be 4 floats for
* left, top, right, bottom (relative to 0, 0) for that glyph.
* @param glyphs
* @param paint
* @param output - if provided, the results will be copied into this array.
*/
getGlyphBounds(glyphs: InputGlyphIDArray, paint?: SkPaint | null,
output?: Float32Array): Float32Array;
/**
* Retrieves the glyph ids for each code point in the provided string. Note that glyph IDs
* are font-dependent; different fonts may have different ids for the same code point.
* @param str
* @param numCodePoints - the number of code points in the string. Defaults to str.length.
* @param output - if provided, the results will be copied into this array.
*/
getGlyphIDs(str: string, numCodePoints?: number,
output?: TypedArray): GlyphIDArray;
/**
* Retrieves the advanceX measurements for each glyph.
* If paint is not null, its stroking, SkPathEffect, and SkMaskFilter fields are respected.
* One width per glyph is returned in the returned array.
* @param glyphs
* @param paint
* @param output - if provided, the results will be copied into this array.
*/
getGlyphWidths(glyphs: InputGlyphIDArray, paint?: SkPaint | null,
output?: Float32Array): Float32Array;
/**
* Returns text scale on x-axis. Default value is 1.
*/
getScaleX(): number;
/**
* Returns text size in points.
*/
getSize(): number;
/**
* Returns text skew on x-axis. Default value is zero.
*/
getSkewX(): number;
/**
* Returns the SkTypeface set for this font.
*/
getTypeface(): SkTypeface | null;
/**
* Retrieves the advanceX measurements for each code point in str.
* [deprecated] Use getGlyphIDs and getGlyphWidths instead.
* @param str
*/
getWidths(str: string): number[];
/**
* Retrieves the total advance with the given string.
* If attempting to shape text to fit into a given width, using getGlyphIDs and getGlyphWidths
* is probably easier / more efficient.
* @param str
*/
measureText(str: string): number;
/**
* Requests, but does not require, that edge pixels draw opaque or with partial transparency.
* @param edging
*/
setEdging(edging: FontEdging): void;
/**
* Requests, but does not require, to use bitmaps in fonts instead of outlines.
* @param embeddedBitmaps
*/
setEmbeddedBitmaps(embeddedBitmaps: boolean): void;
/**
* Sets level of glyph outline adjustment.
* @param hinting
*/
setHinting(hinting: FontHinting): void;
/**
* Requests, but does not require, linearly scalable font and glyph metrics.
*
* For outline fonts 'true' means font and glyph metrics should ignore hinting and rounding.
* Note that some bitmap formats may not be able to scale linearly and will ignore this flag.
* @param linearMetrics
*/
setLinearMetrics(linearMetrics: boolean): void;
/**
* Sets the text scale on the x-axis.
* @param sx
*/
setScaleX(sx: number): void;
/**
* Sets the text size in points on this font.
* @param points
*/
setSize(points: number): void;
/**
* Sets the text-skew on the x axis for this font.
* @param sx
*/
setSkewX(sx: number): void;
/**
* Requests, but does not require, that glyphs respect sub-pixel positioning.
* @param subpixel
*/
setSubpixel(subpixel: boolean): void;
/**
* Sets the typeface to use with this font. null means to clear the typeface and use the
* default one.
* @param face
*/
setTypeface(face: SkTypeface | null): void;
}
/**
* See SkFontMgr.h for more details
*/
export interface SkFontMgr extends EmbindObject<SkFontMgr> {
/**
* Return the number of font families loaded in this manager. Useful for debugging.
*/
countFamilies(): number;
/**
* Return the nth family name. Useful for debugging.
* @param index
*/
getFamilyName(index: number): string;
/**
* Create a typeface for the specified bytes and return it.
* @param fontData
*/
makeTypefaceFromData(fontData: ArrayBuffer): SkTypeface;
}
/**
@ -862,7 +1028,7 @@ export interface SkImage extends EmbindObject<SkImage> {
}
/**
* See SkImageFilter.h for more on this class. The objects returned are opaque.
* See SkImageFilter.h for more on this class. The objects are opaque.
*/
export type SkImageFilter = EmbindObject<SkImageFilter>;
@ -875,7 +1041,7 @@ export interface SkImageInfo {
}
/**
* See SkMaskFilter.h for more on this class. The objects returned are opaque.
* See SkMaskFilter.h for more on this class. The objects are opaque.
*/
export type SkMaskFilter = EmbindObject<SkMaskFilter>;
@ -1479,7 +1645,7 @@ export interface SkPath extends EmbindObject<SkPath> {
}
/**
* See SkPathEffect.h for more on this class. The objects returned are opaque.
* See SkPathEffect.h for more on this class. The objects are opaque.
*/
export type SkPathEffect = EmbindObject<SkPathEffect>;
@ -1568,11 +1734,14 @@ export interface SkSurface extends EmbindObject<SkSurface> {
}
/**
* See SkTextBlob.h for more on this class.
* See SkTextBlob.h for more on this class. The objects are opaque.
*/
export interface SkTextBlob extends EmbindObject<SkTextBlob> {
todo: number; // TODO(kjlubick)
}
export type SkTextBlob = EmbindObject<SkTextBlob>;
/**
* See SkTypeface.h for more on this class. The objects are opaque.
*/
export type SkTypeface = EmbindObject<SkTypeface>;
/**
* See SkVertices.h for more on this class.
@ -1824,6 +1993,17 @@ export interface Matrix4x4Helpers {
transpose(matrix: Matrix4x4 | number[]): number[];
}
/**
* This class is an abstraction around SkShaper.h
*/
export interface ShapedTextConstructor {
/**
* Return a ShapedText from the given options. See SkShaper.h for more.
* @param opts
*/
new (opts: ShapedTextOpts): ShapedText;
}
/**
* See SkColorFilter.h for more.
*/
@ -1867,6 +2047,43 @@ export interface SkColorFilterFactory {
MakeSRGBToLinearGamma(): SkColorFilter;
}
/**
* See SkFont.h for more.
*/
export interface SkFontConstructor extends DefaultConstructor<SkFont> {
/**
* Constructs SkFont with default values with SkTypeface.
* @param face
* @param size - font size in points. If not specified, uses a default value.
*/
new (face: SkTypeface | null, size?: number): SkFont;
/**
* Constructs SkFont with default values with SkTypeface and size in points,
* horizontal scale, and horizontal skew. Horizontal scale emulates condensed
* and expanded fonts. Horizontal skew emulates oblique fonts.
* @param face
* @param size
* @param scaleX
* @param skewX
*/
new (face: SkTypeface | null, size: number, scaleX: number, skewX: number): SkFont;
}
export interface SkFontMgrFactory {
/**
* Create an SkFontMgr with the created font data. Returns null if buffers was empty.
* @param buffers
*/
FromData(...buffers: ArrayBuffer[]): SkFontMgr | null;
/**
* Return the default SkFontMgr. This will generally have 0 or 1 fonts in it, depending on if
* the demo monospace font was compiled in.
*/
RefDefault(): SkFontMgr;
}
/**
* See effects/SkImageFilters.h for more.
*/
@ -1979,6 +2196,65 @@ export interface SkPathEffectFactory {
MakeDiscrete(segLength: number, dev: number, seedAssist: number): SkPathEffect;
}
/**
* See SkTextBlob.h for more details.
*/
export interface SkTextBlobFactory {
/**
* Return a TextBlob with a single run of text.
*
* It does not perform typeface fallback for characters not found in the SkTypeface.
* It does not perform kerning or other complex shaping; glyphs are positioned based on their
* default advances.
* @param glyphs - if using Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs().
* @param font
*/
MakeFromGlyphs(glyphs: InputGlyphIDArray, font: SkFont): SkTextBlob;
/**
* Returns a TextBlob built from a single run of text with rotation, scale, and translations.
*
* It uses the default character-to-glyph mapping from the typeface in the font.
* @param str
* @param rsxforms
* @param font
*/
MakeFromRSXform(str: string, rsxforms: FlattenedRSXFormArray, font: SkFont): SkTextBlob;
/**
* Returns a TextBlob built from a single run of text with rotation, scale, and translations.
*
* @param glyphs - if using Malloc'd array, be sure to use CanvasKit.MallocGlyphIDs().
* @param rsxforms
* @param font
*/
MakeFromRSXformGlyphs(glyphs: InputGlyphIDArray, rsxforms: FlattenedRSXFormArray,
font: SkFont): SkTextBlob;
/**
* Return a TextBlob with a single run of text.
*
* It uses the default character-to-glyph mapping from the typeface in the font.
* It does not perform typeface fallback for characters not found in the SkTypeface.
* It does not perform kerning or other complex shaping; glyphs are positioned based on their
* default advances.
* @param str
* @param font
*/
MakeFromText(str: string, font: SkFont): SkTextBlob;
/**
* Returns a TextBlob that has the glyphs following the contours of the given path.
*
* It is a convenience wrapper around MakeFromRSXform and SkPathMeasure.
* @param str
* @param path
* @param font
* @param initialOffset - the length in pixels to start along the path.
*/
MakeOnPath(str: string, path: SkPath, font: SkFont, initialOffset?: number): SkTextBlob;
}
/**
* An SkColor is represented by 4 floats, typically with values between 0 and 1.0. In order,
* the floats correspond to red, green, blue, alpha.
@ -2043,6 +2319,11 @@ export type FlattenedRectangleArray = MallocObj | Float32Array | number[];
* be scos, ssin, tx, ty for each RSXForm. See RSXForm.h for more details.
*/
export type FlattenedRSXFormArray = MallocObj | Float32Array | number[];
/**
* Regardless of the format we use internally for GlyphID (16 bit unsigned atm), we expose them
* as 32 bit unsigned.
*/
export type GlyphIDArray = Uint32Array;
/**
* PathCommand contains a verb and then any arguments needed to fulfill that path verb.
* Examples:
@ -2078,6 +2359,11 @@ export type InputColor = MallocObj | SkColor | number[];
* Length 20.
*/
export type InputColorMatrix = MallocObj | SkColorMatrix | number[];
/**
* CanvasKit APIs accept normal arrays, typed arrays, or Malloc'd memory as glyph IDs.
* Length n for n glyph IDs.
*/
export type InputGlyphIDArray = MallocObj | GlyphIDArray | number[];
/**
* CanvasKit APIs accept all of these matrix types. Under the hood, we generally use 4x4 matrices.
*/
@ -2107,6 +2393,8 @@ export type ColorType = EmbindEnumEntity;
export type EncodedImageFormat = EmbindEnumEntity;
export type FillType = EmbindEnumEntity;
export type FilterQuality = EmbindEnumEntity;
export type FontEdging = EmbindEnumEntity;
export type FontHinting = EmbindEnumEntity;
export type PathOp = EmbindEnumEntity;
export type PaintStyle = EmbindEnumEntity;
export type PointMode = EmbindEnumEntity;
@ -2205,6 +2493,19 @@ export interface FilterQualityEnumValues extends EmbindEnum {
High: FilterQuality;
}
export interface FontEdgingEnumValues extends EmbindEnum {
Alias: FontEdging;
AntiAlias: FontEdging;
SubpixelAntiAlias: FontEdging;
}
export interface FontHintingEnumValues extends EmbindEnum {
None: FontHinting;
Slight: FontHinting;
Normal: FontHinting;
Full: FontHinting;
}
export interface PaintStyleEnumValues extends EmbindEnum {
Fill: PaintStyle;
Stroke: PaintStyle;

View File

@ -629,6 +629,7 @@ static sk_sp<SkTextBlob> do_shaping(const ShapedTextOpts& opts, SkPoint* pt) {
return builder.makeBlob();
}
// TODO(kjlubick) ShapedText is a very thin veneer around SkTextBlob - can probably remove it.
class ShapedText {
public:
ShapedText(ShapedTextOpts opts) : fOpts(opts) {}

View File

@ -93,7 +93,8 @@ CanvasKit._extraInitializations.push(function() {
return rv;
};
// Returns an array of the widths of the glyphs in this string.
// Returns an array of the widths of the glyphs in this string.
// TODO(kjlubick) Remove this API - getGlyphWidths is the better API.
CanvasKit.SkFont.prototype.getWidths = function(str) {
// add 1 for null terminator
var codePoints = str.length + 1;