From 4755b0b52592cb506b3e002775ac66177f383495 Mon Sep 17 00:00:00 2001 From: Kevin Lubick Date: Thu, 22 Apr 2021 13:53:35 -0400 Subject: [PATCH] [canvaskit] Add TextHeightBehavior Bug: skia:11881 Change-Id: I220f5ad43de95324172ee5b6d3d5a975a3f8a166 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/399836 Reviewed-by: Julia Lavrova --- modules/canvaskit/CHANGELOG.md | 1 + modules/canvaskit/externs.js | 7 ++++ .../npm_build/types/canvaskit-wasm-tests.ts | 4 +++ modules/canvaskit/npm_build/types/index.d.ts | 18 +++++++--- modules/canvaskit/paragraph.js | 3 +- modules/canvaskit/paragraph_bindings.cpp | 21 ++++++----- modules/canvaskit/paragraph_bindings_gen.cpp | 6 ++++ modules/canvaskit/tests/paragraph.spec.js | 35 +++++++++++++++++++ 8 files changed, 81 insertions(+), 14 deletions(-) diff --git a/modules/canvaskit/CHANGELOG.md b/modules/canvaskit/CHANGELOG.md index 9305265ffe..99d6195e6b 100644 --- a/modules/canvaskit/CHANGELOG.md +++ b/modules/canvaskit/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 to `RuntimeEffect.makeShader` as floats (like all other uniforms), and will be converted to integers internally, to match the expectations of the shader. - Add 'halfLeading' to `TextStyle` and `StrutStyle`. + - `ParagraphStyle` now accepts textHeightBehavior. ### Removed - `Picture.saveAsFile()`, in favor of `Picture.serialize()` where clients can control how to diff --git a/modules/canvaskit/externs.js b/modules/canvaskit/externs.js index bbec785a20..800844b85b 100644 --- a/modules/canvaskit/externs.js +++ b/modules/canvaskit/externs.js @@ -939,6 +939,13 @@ var CanvasKit = { RTL: {}, }, + TextHeightBehavior: { + All: {}, + DisableFirstAscent: {}, + DisableLastDescent: {}, + DisableAll: {}, + }, + DecorationStyle: { Solid: {}, Double: {}, diff --git a/modules/canvaskit/npm_build/types/canvaskit-wasm-tests.ts b/modules/canvaskit/npm_build/types/canvaskit-wasm-tests.ts index c2ceb96398..33332122e8 100644 --- a/modules/canvaskit/npm_build/types/canvaskit-wasm-tests.ts +++ b/modules/canvaskit/npm_build/types/canvaskit-wasm-tests.ts @@ -532,6 +532,10 @@ function paragraphBuilderTests(CK: CanvasKit, fontMgr?: FontMgr, paint?: Paint) heightMultiplier: 1.5, forceStrutHeight: true, }, + disableHinting: true, + heightMultiplier: 2.5, + textDirection: CK.TextDirection.LTR, + textHeightBehavior: CK.TextHeightBehavior.DisableFirstAscent }); const blueText = new CK.TextStyle({ // $ExpectType TextStyle backgroundColor: CK.Color(234, 208, 232), // light pink diff --git a/modules/canvaskit/npm_build/types/index.d.ts b/modules/canvaskit/npm_build/types/index.d.ts index ddbe562818..78a38190b1 100644 --- a/modules/canvaskit/npm_build/types/index.d.ts +++ b/modules/canvaskit/npm_build/types/index.d.ts @@ -503,6 +503,7 @@ export interface CanvasKit { readonly TextAlign: TextAlignEnumValues; readonly TextBaseline: TextBaselineEnumValues; readonly TextDirection: TextDirectionEnumValues; + readonly TextHeightBehavior: TextHeightBehaviorEnumValues; // Paragraph Constants readonly NoDecoration: number; @@ -877,6 +878,7 @@ export interface ParagraphStyle { strutStyle?: StrutStyle; textAlign?: TextAlign; textDirection?: TextDirection; + textHeightBehavior?: TextHeightBehavior; textStyle?: TextStyle; } @@ -1563,10 +1565,10 @@ export interface ContourMeasure extends EmbindObject { } export interface FontMetrics { - ascent: number, // suggested space above the baseline. < 0 - descent: number, // suggested space below the baseline. > 0 - leading: number, // suggested spacing between descent of previous line and ascent of next line. - bounds?: Rect, // smallest rect containing all glyphs (relative to 0,0) + ascent: number; // suggested space above the baseline. < 0 + descent: number; // suggested space below the baseline. > 0 + leading: number; // suggested spacing between descent of previous line and ascent of next line. + bounds?: Rect; // smallest rect containing all glyphs (relative to 0,0) } /** @@ -3694,6 +3696,7 @@ export type RectWidthStyle = EmbindEnumEntity; export type TextAlign = EmbindEnumEntity; export type TextBaseline = EmbindEnumEntity; export type TextDirection = EmbindEnumEntity; +export type TextHeightBehavior = EmbindEnumEntity; export interface AffinityEnumValues extends EmbindEnum { Upstream: Affinity; @@ -3936,6 +3939,13 @@ export interface TextDirectionEnumValues extends EmbindEnum { RTL: TextDirection; } +export interface TextHeightBehaviorEnumValues extends EmbindEnum { + All: TextHeightBehavior; + DisableFirstAscent: TextHeightBehavior; + DisableLastDescent: TextHeightBehavior; + DisableAll: TextHeightBehavior; +} + export interface TileModeEnumValues extends EmbindEnum { Clamp: TileMode; Decal: TileMode; diff --git a/modules/canvaskit/paragraph.js b/modules/canvaskit/paragraph.js index 0e3c183327..0b95a75cf7 100644 --- a/modules/canvaskit/paragraph.js +++ b/modules/canvaskit/paragraph.js @@ -69,10 +69,11 @@ s['heightMultiplier'] = s['heightMultiplier'] || 0; s['maxLines'] = s['maxLines'] || 0; + s['strutStyle'] = strutStyle(s['strutStyle']); s['textAlign'] = s['textAlign'] || CanvasKit.TextAlign.Start; s['textDirection'] = s['textDirection'] || CanvasKit.TextDirection.LTR; + s['textHeightBehavior'] = s['textHeightBehavior'] || CanvasKit.TextHeightBehavior.All; s['textStyle'] = CanvasKit.TextStyle(s['textStyle']); - s['strutStyle'] = strutStyle(s['strutStyle']); return s; }; diff --git a/modules/canvaskit/paragraph_bindings.cpp b/modules/canvaskit/paragraph_bindings.cpp index 3b19cb733e..8ce6f89e5f 100644 --- a/modules/canvaskit/paragraph_bindings.cpp +++ b/modules/canvaskit/paragraph_bindings.cpp @@ -214,6 +214,7 @@ struct SimpleParagraphStyle { size_t maxLines; para::TextAlign textAlign; para::TextDirection textDirection; + para::TextHeightBehavior textHeightBehavior; SimpleTextStyle textStyle; SimpleStrutStyle strutStyle; }; @@ -241,6 +242,7 @@ para::ParagraphStyle toParagraphStyle(const SimpleParagraphStyle& s) { if (s.maxLines != 0) { ps.setMaxLines(s.maxLines); } + ps.setTextHeightBehavior(s.textHeightBehavior); return ps; } @@ -464,15 +466,16 @@ EMSCRIPTEN_BINDINGS(Paragraph) { .field("width", &SimpleFontStyle::width); value_object("ParagraphStyle") - .field("disableHinting", &SimpleParagraphStyle::disableHinting) - .field("_ellipsisPtr", &SimpleParagraphStyle::ellipsisPtr) - .field("_ellipsisLen", &SimpleParagraphStyle::ellipsisLen) - .field("heightMultiplier", &SimpleParagraphStyle::heightMultiplier) - .field("maxLines", &SimpleParagraphStyle::maxLines) - .field("textAlign", &SimpleParagraphStyle::textAlign) - .field("textDirection", &SimpleParagraphStyle::textDirection) - .field("textStyle", &SimpleParagraphStyle::textStyle) - .field("strutStyle", &SimpleParagraphStyle::strutStyle); + .field("disableHinting", &SimpleParagraphStyle::disableHinting) + .field("_ellipsisPtr", &SimpleParagraphStyle::ellipsisPtr) + .field("_ellipsisLen", &SimpleParagraphStyle::ellipsisLen) + .field("heightMultiplier", &SimpleParagraphStyle::heightMultiplier) + .field("maxLines", &SimpleParagraphStyle::maxLines) + .field("textAlign", &SimpleParagraphStyle::textAlign) + .field("textDirection", &SimpleParagraphStyle::textDirection) + .field("textHeightBehavior", &SimpleParagraphStyle::textHeightBehavior) + .field("textStyle", &SimpleParagraphStyle::textStyle) + .field("strutStyle", &SimpleParagraphStyle::strutStyle); value_object("StrutStyle") .field("_fontFamiliesPtr", &SimpleStrutStyle::fontFamiliesPtr) diff --git a/modules/canvaskit/paragraph_bindings_gen.cpp b/modules/canvaskit/paragraph_bindings_gen.cpp index 1f69e33057..e4f943ace8 100644 --- a/modules/canvaskit/paragraph_bindings_gen.cpp +++ b/modules/canvaskit/paragraph_bindings_gen.cpp @@ -92,4 +92,10 @@ EMSCRIPTEN_BINDINGS(ParagraphGen) { enum_("TextDirection") .value("LTR", para::TextDirection::kLtr) .value("RTL", para::TextDirection::kRtl); + + enum_("TextHeightBehavior") + .value("All", para::TextHeightBehavior::kAll) + .value("DisableFirstAscent", para::TextHeightBehavior::kDisableFirstAscent) + .value("DisableLastDescent", para::TextHeightBehavior::kDisableLastDescent) + .value("DisableAll", para::TextHeightBehavior::kDisableAll); } diff --git a/modules/canvaskit/tests/paragraph.spec.js b/modules/canvaskit/tests/paragraph.spec.js index 66a53191c9..18d198829b 100644 --- a/modules/canvaskit/tests/paragraph.spec.js +++ b/modules/canvaskit/tests/paragraph.spec.js @@ -846,6 +846,41 @@ describe('Paragraph Behavior', function() { builder.delete(); }); + gm('paragraph_mixed_text_height_behavior', (canvas) => { + const fontMgr = CanvasKit.FontMgr.FromData(notoSerifFontBuffer); + expect(fontMgr.countFamilies()).toEqual(1); + expect(fontMgr.getFamilyName(0)).toEqual('Noto Serif'); + canvas.clear(CanvasKit.WHITE); + const paint = new CanvasKit.Paint(); + paint.setColor(CanvasKit.RED); + paint.setStyle(CanvasKit.PaintStyle.Stroke); + + const wrapTo = 220; + const behaviors = ["All", "DisableFirstAscent", "DisableLastDescent", "DisableAll"]; + + for (let i = 0; i < behaviors.length; i++) { + const style = new CanvasKit.ParagraphStyle({ + textStyle: { + color: CanvasKit.BLACK, + fontFamilies: ['Noto Serif'], + fontSize: 20, + heightMultiplier: 3, // make the difference more obvious + }, + textHeightBehavior: CanvasKit.TextHeightBehavior[behaviors[i]], + }); + const builder = CanvasKit.ParagraphBuilder.Make(style, fontMgr); + builder.addText('Text height behavior\nof '+behaviors[i]); + const paragraph = builder.build(); + paragraph.layout(wrapTo); + canvas.drawParagraph(paragraph, 0, 150 * i); + canvas.drawRect(CanvasKit.LTRBRect(0, 150 * i, wrapTo, 150 * i + 120), paint); + paragraph.delete(); + builder.delete(); + } + paint.delete(); + fontMgr.delete(); + }); + it('should not crash if we omit font family on pushed textStyle', () => { const surface = CanvasKit.MakeCanvasSurface('test'); expect(surface).toBeTruthy('Could not make surface');