[canvaskit] JS API in place for shaped text
Depends on https://skia-review.googlesource.com/c/skia/+/186870 It's optional at build time, which is good given that it adds about 2MB of uncompressed size (from 4.3 MB to 6.4 MB) Bug: skia: Change-Id: I5f54ad628b735c3bc880e917394fb27d16849ebe Reviewed-on: https://skia-review.googlesource.com/c/187924 Commit-Queue: Kevin Lubick <kjlubick@google.com> Reviewed-by: Ben Wagner <bungeman@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
18e5841c0d
commit
1ba9c4df77
17
BUILD.gn
17
BUILD.gn
@ -12,11 +12,6 @@ if (is_fuchsia) {
|
||||
import("//build/vulkan/config.gni")
|
||||
}
|
||||
|
||||
if (!defined(is_skia_standalone)) {
|
||||
is_skia_standalone = false
|
||||
}
|
||||
is_skia_dev_build = is_skia_standalone && !is_official_build
|
||||
|
||||
declare_args() {
|
||||
skia_enable_flutter_defines = false
|
||||
}
|
||||
@ -45,12 +40,10 @@ declare_args() {
|
||||
skia_enable_ccpr = true
|
||||
skia_enable_nvpr = !skia_enable_flutter_defines
|
||||
skia_enable_discrete_gpu = true
|
||||
skia_enable_gpu = true
|
||||
skia_enable_nima = false
|
||||
skia_enable_pdf = true
|
||||
skia_enable_spirv_validation = is_skia_dev_build && is_debug
|
||||
skia_enable_skpicture = true
|
||||
skia_enable_tools = is_skia_dev_build
|
||||
skia_enable_vulkan_debug_layers = is_skia_dev_build && is_debug
|
||||
skia_qt_path = getenv("QT_PATH")
|
||||
skia_compile_processors = false
|
||||
@ -93,9 +86,6 @@ if (defined(skia_settings)) {
|
||||
import(skia_settings)
|
||||
}
|
||||
|
||||
# Our tools require static linking (they use non-exported symbols), and the GPU backend.
|
||||
skia_enable_tools = skia_enable_tools && !is_component_build && skia_enable_gpu
|
||||
|
||||
skia_public_includes = [
|
||||
"include/android",
|
||||
"include/c",
|
||||
@ -1125,6 +1115,13 @@ static_library("pathkit") {
|
||||
]
|
||||
}
|
||||
|
||||
group("modules") {
|
||||
deps = [
|
||||
"modules/skottie",
|
||||
"modules/skshaper",
|
||||
]
|
||||
}
|
||||
|
||||
# Targets guarded by skia_enable_tools may use //third_party freely.
|
||||
if (skia_enable_tools) {
|
||||
# Used by gn_to_bp.py to list our public include dirs.
|
||||
|
@ -13,9 +13,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
`SkPath.toCmds`.
|
||||
- `SkCanvas.drawTextBlob()` and `SkCanvas.SkTextBlob.MakeFromText()` to draw text to a canvas.
|
||||
- `CanvasKit.TextEncoding` enum. For use with `SkTextBlob`.
|
||||
- Text shaping with `ShapedText` object and `SkCanvas.drawText`. At compile time, one can choose
|
||||
between using Harfbuzz/ICU (default) or a primitive one ("primitive_shaper") which just does
|
||||
line breaking. Using Harfbuzz/ICU substantially increases code size (4.3 MB to 6.4 MB).
|
||||
|
||||
### Changed
|
||||
- `SkCanvas.drawText()` now requires an `SkFont` object.
|
||||
- `SkCanvas.drawText()` now requires an `SkFont` object for raw strings.
|
||||
|
||||
|
||||
### Removed
|
||||
- `SkPaint.setTextSize()`, `SkPaint.getTextSize()`, `SkPaint.setTypeface()`
|
||||
|
@ -61,3 +61,10 @@ test-continuous:
|
||||
|
||||
node-example:
|
||||
node ./canvaskit/node.example.js --expose-wasm
|
||||
|
||||
docker-compile:
|
||||
mkdir -p ${SKIA_ROOT}/out/canvaskit_wasm_docker
|
||||
docker run --rm --volume ${SKIA_ROOT}:/SRC \
|
||||
--volume ${SKIA_ROOT}/out/canvaskit_wasm_docker:/OUT \
|
||||
gcr.io/skia-public/canvaskit-emsdk:1.38.27_v1 \
|
||||
/SRC/infra/canvaskit/build_canvaskit.sh
|
||||
|
BIN
experimental/canvaskit/canvaskit/NotoSerif-Regular.ttf
Normal file
BIN
experimental/canvaskit/canvaskit/NotoSerif-Regular.ttf
Normal file
Binary file not shown.
@ -43,6 +43,9 @@
|
||||
<canvas id=paths width=200 height=200></canvas>
|
||||
<canvas id=ink width=300 height=300></canvas>
|
||||
|
||||
<h2> CanvasKit can allow for text shaping (e.g. breaking, kerning)</h2>
|
||||
<canvas id=shape1 width=600 height=600></canvas>
|
||||
|
||||
<h2> Skottie </h2>
|
||||
<canvas id=sk_legos width=300 height=300></canvas>
|
||||
<canvas id=sk_drinks width=500 height=500></canvas>
|
||||
@ -61,6 +64,7 @@
|
||||
var fullBounds = {fLeft: 0, fTop: 0, fRight: 500, fBottom: 500};
|
||||
|
||||
var robotoData = null;
|
||||
var notoserifData = null;
|
||||
|
||||
var bonesImageData = null;
|
||||
CanvasKitInit({
|
||||
@ -85,12 +89,14 @@
|
||||
CanvasAPI5(CanvasKit);
|
||||
CanvasAPI6(CanvasKit);
|
||||
CanvasAPI7(CanvasKit);
|
||||
CanvasAPI8(CanvasKit)
|
||||
CanvasAPI8(CanvasKit);
|
||||
|
||||
VertexAPI1(CanvasKit);
|
||||
VertexAPI2(CanvasKit, bonesImageData);
|
||||
|
||||
GradiantAPI1(CanvasKit);
|
||||
|
||||
TextShapingAPI1(CanvasKit, notoserifData);
|
||||
});
|
||||
|
||||
fetch('https://storage.googleapis.com/skia-cdn/misc/lego_loader.json').then((resp) => {
|
||||
@ -132,7 +138,14 @@
|
||||
fetch('./Roboto-Regular.woff').then((resp) => {
|
||||
resp.arrayBuffer().then((buffer) => {
|
||||
robotoData = buffer;
|
||||
DrawingExample(CanvasKit, robotoData)
|
||||
DrawingExample(CanvasKit, robotoData);
|
||||
});
|
||||
});
|
||||
|
||||
fetch('./NotoSerif-Regular.ttf').then((resp) => {
|
||||
resp.arrayBuffer().then((buffer) => {
|
||||
notoserifData = buffer;
|
||||
TextShapingAPI1(CanvasKit, notoserifData);
|
||||
});
|
||||
});
|
||||
|
||||
@ -152,7 +165,7 @@
|
||||
const paint = new CanvasKit.SkPaint();
|
||||
|
||||
const fontMgr = CanvasKit.SkFontMgr.RefDefault();
|
||||
let roboto = fontMgr.MakeTypefaceFromData(robotoData);
|
||||
const roboto = fontMgr.MakeTypefaceFromData(robotoData);
|
||||
|
||||
const textPaint = new CanvasKit.SkPaint();
|
||||
textPaint.setColor(CanvasKit.RED);
|
||||
@ -183,7 +196,7 @@
|
||||
canvas.clear(CanvasKit.TRANSPARENT);
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
canvas.drawText('Try Clicking!', 10, 280, textFont, textPaint);
|
||||
canvas.drawText('Try Clicking!', 10, 280, textPaint, textFont);
|
||||
|
||||
surface.flush();
|
||||
|
||||
@ -1078,4 +1091,73 @@
|
||||
textBlob.delete();
|
||||
surface.flush();
|
||||
}
|
||||
|
||||
function TextShapingAPI1(CanvasKit, notoserifData) {
|
||||
if (!notoserifData || !CanvasKit) {
|
||||
return;
|
||||
}
|
||||
const surface = CanvasKit.MakeCanvasSurface('shape1');
|
||||
if (!surface) {
|
||||
console.error('Could not make surface');
|
||||
return;
|
||||
}
|
||||
const context = CanvasKit.currentContext();
|
||||
const canvas = surface.getCanvas();
|
||||
const paint = new CanvasKit.SkPaint();
|
||||
paint.setColor(CanvasKit.BLUE);
|
||||
paint.setStyle(CanvasKit.PaintStyle.Stroke);
|
||||
|
||||
const fontMgr = CanvasKit.SkFontMgr.RefDefault();
|
||||
const notoSerif = fontMgr.MakeTypefaceFromData(notoserifData);
|
||||
|
||||
const textPaint = new CanvasKit.SkPaint();
|
||||
const textFont = new CanvasKit.SkFont(notoSerif, 20);
|
||||
|
||||
canvas.drawRect(CanvasKit.LTRBRect(30, 30, 200, 200), paint);
|
||||
canvas.drawText('This text is not shaped, and overflows the boundry',
|
||||
35, 50, textPaint, textFont);
|
||||
|
||||
const shapedText = new CanvasKit.ShapedText({
|
||||
font: textFont,
|
||||
leftToRight: true,
|
||||
text: 'This text *is* shaped, and wraps to the right width.',
|
||||
width: 160,
|
||||
});
|
||||
const textBoxX = 35;
|
||||
const textBoxY = 55;
|
||||
canvas.drawText(shapedText, textBoxX, textBoxY, textPaint);
|
||||
const bounds = shapedText.getBounds();
|
||||
|
||||
bounds.fLeft += textBoxX;
|
||||
bounds.fRight += textBoxX;
|
||||
bounds.fTop += textBoxY;
|
||||
bounds.fBottom += textBoxY
|
||||
|
||||
canvas.drawRect(bounds, paint);
|
||||
const SHAPE_TEST_TEXT = 'VAVAVAVAVAFIfi';
|
||||
const textFont2 = new CanvasKit.SkFont(notoSerif, 60);
|
||||
const shapedText2 = new CanvasKit.ShapedText({
|
||||
font: textFont2,
|
||||
leftToRight: true,
|
||||
text: SHAPE_TEST_TEXT,
|
||||
width: 600,
|
||||
});
|
||||
|
||||
canvas.drawText('no kerning ↓', 10, 240, textPaint, textFont);
|
||||
canvas.drawText(SHAPE_TEST_TEXT, 10, 300, textPaint, textFont2);
|
||||
canvas.drawText(shapedText2, 10, 300, textPaint);
|
||||
canvas.drawText('kerning ↑', 10, 390, textPaint, textFont);
|
||||
|
||||
surface.flush();
|
||||
|
||||
paint.delete();
|
||||
notoSerif.delete();
|
||||
textPaint.delete();
|
||||
textFont.delete();
|
||||
shapedText.delete();
|
||||
textFont2.delete();
|
||||
shapedText2.delete();
|
||||
|
||||
surface.delete();
|
||||
}
|
||||
</script>
|
||||
|
@ -73,7 +73,7 @@ function fancyAPI(CanvasKit) {
|
||||
canvas.clear(CanvasKit.Color(255, 255, 255, 1.0));
|
||||
|
||||
canvas.drawPath(skpath, paint);
|
||||
canvas.drawText('Try Clicking!', 10, 280, textFont, textPaint);
|
||||
canvas.drawText('Try Clicking!', 10, 280, textPaint, textFont);
|
||||
|
||||
surface.flush();
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "SkScalar.h"
|
||||
#include "SkShader.h"
|
||||
#include "SkShadowUtils.h"
|
||||
#include "SkShaper.h"
|
||||
#include "SkString.h"
|
||||
#include "SkStrokeRec.h"
|
||||
#include "SkSurface.h"
|
||||
@ -462,6 +463,58 @@ Uint8Array getSkDataBytes(const SkData *data) {
|
||||
return Uint8Array(typed_memory_view(data->size(), data->bytes()));
|
||||
}
|
||||
|
||||
// Text Shaping abstraction
|
||||
|
||||
struct ShapedTextOpts {
|
||||
SkFont font;
|
||||
bool leftToRight;
|
||||
std::string text;
|
||||
SkScalar width;
|
||||
};
|
||||
|
||||
std::unique_ptr<SkShaper> shaper;
|
||||
|
||||
static sk_sp<SkTextBlob> do_shaping(const ShapedTextOpts& opts, SkPoint* pt) {
|
||||
SkTextBlobBuilderRunHandler builder(opts.text.c_str());
|
||||
if (!shaper) {
|
||||
shaper = SkShaper::Make();
|
||||
}
|
||||
*pt = shaper->shape(&builder, opts.font, opts.text.c_str(),
|
||||
opts.text.length(), opts.leftToRight,
|
||||
{0, 0}, opts.width);
|
||||
return builder.makeBlob();
|
||||
}
|
||||
|
||||
class ShapedText {
|
||||
public:
|
||||
ShapedText(ShapedTextOpts opts) : fOpts(opts) {}
|
||||
|
||||
SkRect getBounds() {
|
||||
this->init();
|
||||
return SkRect::MakeLTRB(0, 0, fOpts.width, fPoint.y());
|
||||
}
|
||||
|
||||
SkTextBlob* blob() {
|
||||
this->init();
|
||||
return fBlob.get();
|
||||
}
|
||||
private:
|
||||
const ShapedTextOpts fOpts;
|
||||
SkPoint fPoint;
|
||||
sk_sp<SkTextBlob> fBlob;
|
||||
|
||||
void init() {
|
||||
if (!fBlob) {
|
||||
fBlob = do_shaping(fOpts, &fPoint);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void drawShapedText(SkCanvas& canvas, ShapedText st, SkScalar x,
|
||||
SkScalar y, SkPaint paint) {
|
||||
canvas.drawTextBlob(st.blob(), x, y, paint);
|
||||
}
|
||||
|
||||
// These objects have private destructors / delete mthods - I don't think
|
||||
// we need to do anything other than tell emscripten to do nothing.
|
||||
namespace emscripten {
|
||||
@ -690,6 +743,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
SkShadowUtils::DrawShadow(&self, path, zPlaneParams, lightPos, lightRadius,
|
||||
SkColor(ambientColor), SkColor(spotColor), flags);
|
||||
}))
|
||||
.function("_drawShapedText", &drawShapedText)
|
||||
.function("_drawSimpleText", optional_override([](SkCanvas& self, uintptr_t /* char* */ sptr,
|
||||
size_t len, SkScalar x, SkScalar y, const SkFont& font,
|
||||
const SkPaint& paint) {
|
||||
@ -753,6 +807,10 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
.function("setSkewX", &SkFont::setSkewX)
|
||||
.function("setTypeface", &SkFont::setTypeface, allow_raw_pointers());
|
||||
|
||||
class_<ShapedText>("ShapedText")
|
||||
.constructor<ShapedTextOpts>()
|
||||
.function("getBounds", &ShapedText::getBounds);
|
||||
|
||||
class_<SkFontMgr>("SkFontMgr")
|
||||
.smart_ptr<sk_sp<SkFontMgr>>("sk_sp<SkFontMgr>")
|
||||
.class_function("RefDefault", &SkFontMgr::RefDefault)
|
||||
@ -1043,6 +1101,12 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
// A value object is much simpler than a class - it is returned as a JS
|
||||
// object and does not require delete().
|
||||
// https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
|
||||
value_object<ShapedTextOpts>("ShapedTextOpts")
|
||||
.field("font", &ShapedTextOpts::font)
|
||||
.field("leftToRight", &ShapedTextOpts::leftToRight)
|
||||
.field("text", &ShapedTextOpts::text)
|
||||
.field("width", &ShapedTextOpts::width);
|
||||
|
||||
value_object<SkRect>("SkRect")
|
||||
.field("fLeft", &SkRect::fLeft)
|
||||
.field("fTop", &SkRect::fTop)
|
||||
|
@ -51,38 +51,32 @@ if [[ $@ == *cpu* ]]; then
|
||||
WASM_GPU="-DSK_SUPPORT_GPU=0 --pre-js $BASE_DIR/cpu.js"
|
||||
fi
|
||||
|
||||
WASM_SKOTTIE=" \
|
||||
$BASE_DIR/skottie_bindings.cpp \
|
||||
modules/skottie/src/Skottie.cpp \
|
||||
modules/skottie/src/SkottieAdapter.cpp \
|
||||
modules/skottie/src/SkottieAnimator.cpp \
|
||||
modules/skottie/src/SkottieJson.cpp \
|
||||
modules/skottie/src/SkottieLayer.cpp \
|
||||
modules/skottie/src/SkottieLayerEffect.cpp \
|
||||
modules/skottie/src/SkottiePrecompLayer.cpp \
|
||||
modules/skottie/src/SkottieProperty.cpp \
|
||||
modules/skottie/src/SkottieShapeLayer.cpp \
|
||||
modules/skottie/src/SkottieTextLayer.cpp \
|
||||
modules/skottie/src/SkottieValue.cpp \
|
||||
modules/sksg/src/*.cpp \
|
||||
modules/skshaper/src/SkShaper.cpp \
|
||||
modules/skshaper/src/SkShaper_primitive.cpp \
|
||||
# TODO(fmalita,kjlubick): reduce this list to one item by fixing
|
||||
# the libskottie.a and libsksg.a builds
|
||||
SKOTTIE_BINDINGS="$BASE_DIR/skottie_bindings.cpp\
|
||||
src/core/SkColorMatrixFilterRowMajor255.cpp \
|
||||
src/core/SkCubicMap.cpp \
|
||||
src/core/SkTime.cpp \
|
||||
src/effects/imagefilters/SkDropShadowImageFilter.cpp \
|
||||
src/pathops/SkOpBuilder.cpp \
|
||||
src/utils/SkJSON.cpp \
|
||||
src/utils/SkParse.cpp "
|
||||
|
||||
SKOTTIE_LIB="$BUILD_DIR/libskottie.a \
|
||||
$BUILD_DIR/libsksg.a"
|
||||
|
||||
if [[ $@ == *no_skottie* ]]; then
|
||||
echo "Omitting Skottie"
|
||||
WASM_SKOTTIE=""
|
||||
SKOTTIE_LIB=""
|
||||
SKOTTIE_BINDINGS=""
|
||||
fi
|
||||
|
||||
WASM_MANAGED_SKOTTIE="\
|
||||
MANAGED_SKOTTIE_BINDINGS="\
|
||||
-DSK_INCLUDE_MANAGED_SKOTTIE=1 \
|
||||
modules/skottie/utils/SkottieUtils.cpp"
|
||||
if [[ $@ == *no_managed_skottie* ]]; then
|
||||
echo "Omitting managed Skottie"
|
||||
WASM_MANAGED_SKOTTIE="-DSK_INCLUDE_MANAGED_SKOTTIE=0"
|
||||
MANAGED_SKOTTIE_BINDINGS="-DSK_INCLUDE_MANAGED_SKOTTIE=0"
|
||||
fi
|
||||
|
||||
HTML_CANVAS_API="--pre-js $BASE_DIR/htmlcanvas/preamble.js \
|
||||
@ -115,6 +109,17 @@ else
|
||||
--align 4
|
||||
fi
|
||||
|
||||
GN_SHAPER="skia_use_icu=true skia_use_system_icu=false"
|
||||
SHAPER_LIB="$BUILD_DIR/libharfbuzz.a \
|
||||
$BUILD_DIR/libicu.a"
|
||||
SHAPER_TARGETS="libharfbuzz.a libicu.a"
|
||||
if [[ $@ == *primitive_shaper* ]]; then
|
||||
echo "Using the primitive shaper instead of the harfbuzz/icu one"
|
||||
GN_SHAPER="skia_use_icu=false"
|
||||
SHAPER_LIB=""
|
||||
SHAPER_TARGETS=""
|
||||
fi
|
||||
|
||||
# Turn off exiting while we check for ninja (which may not be on PATH)
|
||||
set +e
|
||||
NINJA=`which ninja`
|
||||
@ -149,33 +154,36 @@ echo "Compiling bitcode"
|
||||
skia_use_expat=false \
|
||||
skia_use_fontconfig=false \
|
||||
skia_use_freetype=true \
|
||||
skia_use_icu=false \
|
||||
skia_use_libheif=false \
|
||||
skia_use_system_libjpeg_turbo = false \
|
||||
skia_use_libjpeg_turbo=true \
|
||||
skia_use_libpng=true \
|
||||
skia_use_libwebp=false \
|
||||
skia_use_lua=false \
|
||||
skia_use_piex=false \
|
||||
skia_use_system_libpng=true \
|
||||
skia_use_system_freetype2=true \
|
||||
skia_use_system_libjpeg_turbo = false \
|
||||
skia_use_vulkan=false \
|
||||
skia_use_zlib=true \
|
||||
\
|
||||
${GN_SHAPER} \
|
||||
${GN_GPU} \
|
||||
\
|
||||
skia_enable_skshaper=true \
|
||||
skia_enable_ccpr=false \
|
||||
skia_enable_nvpr=false \
|
||||
skia_enable_skpicture=false \
|
||||
${GN_GPU} \
|
||||
skia_enable_fontmgr_empty=false \
|
||||
skia_enable_pdf=false"
|
||||
|
||||
${NINJA} -C ${BUILD_DIR} libskia.a
|
||||
# Build all the libs, we'll link the appropriate ones down below
|
||||
${NINJA} -C ${BUILD_DIR} libskia.a libskottie.a libsksg.a libskshaper.a $SHAPER_TARGETS
|
||||
|
||||
export EMCC_CLOSURE_ARGS="--externs $BASE_DIR/externs.js "
|
||||
|
||||
echo "Generating final wasm"
|
||||
|
||||
# Skottie doesn't end up in libskia and is currently not its own library
|
||||
# so we just hack in the .cpp files we need for now.
|
||||
# Emscripten prefers that libskia.a goes last in order, otherwise, it
|
||||
# Emscripten prefers that the .a files go last in order, otherwise, it
|
||||
# may drop symbols that it incorrectly thinks aren't used. One day,
|
||||
# Emscripten will use LLD, which may relax this requirement.
|
||||
${EMCXX} \
|
||||
@ -200,8 +208,8 @@ ${EMCXX} \
|
||||
-Isrc/sfnt/ \
|
||||
-Isrc/shaders/ \
|
||||
-Isrc/utils/ \
|
||||
-Ithird_party/icu \
|
||||
-Itools \
|
||||
-Itools/fonts \
|
||||
-DSK_DISABLE_READBUFFER \
|
||||
-DSK_DISABLE_AAA \
|
||||
-DSK_DISABLE_DAA \
|
||||
@ -214,16 +222,19 @@ ${EMCXX} \
|
||||
$HTML_CANVAS_API \
|
||||
$BUILTIN_FONT \
|
||||
$BASE_DIR/canvaskit_bindings.cpp \
|
||||
$WASM_SKOTTIE \
|
||||
$WASM_MANAGED_SKOTTIE \
|
||||
$SKOTTIE_BINDINGS \
|
||||
$MANAGED_SKOTTIE_BINDINGS \
|
||||
$BUILD_DIR/libskia.a \
|
||||
$SKOTTIE_LIB \
|
||||
$BUILD_DIR/libskshaper.a \
|
||||
$SHAPER_LIB \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
-s EXPORT_NAME="CanvasKitInit" \
|
||||
-s FORCE_FILESYSTEM=0 \
|
||||
-s MODULARIZE=1 \
|
||||
-s NO_EXIT_RUNTIME=1 \
|
||||
-s STRICT=1 \
|
||||
-s TOTAL_MEMORY=32MB \
|
||||
-s TOTAL_MEMORY=128MB \
|
||||
-s USE_FREETYPE=1 \
|
||||
-s USE_LIBPNG=1 \
|
||||
-s WARN_UNALIGNED=1 \
|
||||
|
@ -67,6 +67,7 @@ var CanvasKit = {
|
||||
_MakeSkVertices: function() {},
|
||||
_MakeTwoPointConicalGradientShader: function() {},
|
||||
_decodeImage: function() {},
|
||||
_drawShapedText: function() {},
|
||||
_getRasterDirectSurface: function() {},
|
||||
_getRasterN32PremulSurface: function() {},
|
||||
_getWebGLSurface: function() {},
|
||||
@ -77,6 +78,11 @@ var CanvasKit = {
|
||||
|
||||
// Objects and properties on CanvasKit
|
||||
|
||||
ShapedText: {
|
||||
// public API (from C++ bindings)
|
||||
getBounds: function() {},
|
||||
},
|
||||
|
||||
SkCanvas: {
|
||||
// public API (from C++ bindings)
|
||||
clear: function() {},
|
||||
|
@ -382,15 +382,20 @@
|
||||
throw 'encodeToData expected to take 0 or 2 arguments. Got ' + arguments.length;
|
||||
}
|
||||
|
||||
CanvasKit.SkCanvas.prototype.drawText = function(str, x, y, font, paint) {
|
||||
// lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
|
||||
// JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
|
||||
// Add 1 for null terminator
|
||||
var strLen = lengthBytesUTF8(str) + 1;
|
||||
var strPtr = CanvasKit._malloc(strLen);
|
||||
// Add 1 for the null terminator.
|
||||
stringToUTF8(str, strPtr, strLen);
|
||||
this._drawSimpleText(strPtr, strLen, x, y, font, paint);
|
||||
// str can be either a text string or a ShapedText object
|
||||
CanvasKit.SkCanvas.prototype.drawText = function(str, x, y, paint, font) {
|
||||
if (typeof str === 'string') {
|
||||
// lengthBytesUTF8 and stringToUTF8Array are defined in the emscripten
|
||||
// JS. See https://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html#stringToUTF8
|
||||
// Add 1 for null terminator
|
||||
var strLen = lengthBytesUTF8(str) + 1;
|
||||
var strPtr = CanvasKit._malloc(strLen);
|
||||
|
||||
stringToUTF8(str, strPtr, strLen);
|
||||
this._drawSimpleText(strPtr, strLen, x, y, font, paint);
|
||||
} else {
|
||||
this._drawShapedText(str, x, y, paint);
|
||||
}
|
||||
}
|
||||
|
||||
// returns Uint8Array
|
||||
|
@ -14,6 +14,7 @@ module.exports = function(config) {
|
||||
{ pattern: 'tests/assets/*', included:false, served:true},
|
||||
'../../modules/pathkit/tests/testReporter.js',
|
||||
'canvaskit/bin/canvaskit.js',
|
||||
'tests/util.js',
|
||||
'tests/*.spec.js'
|
||||
],
|
||||
|
||||
|
BIN
experimental/canvaskit/tests/assets/NotoSerif-Regular.ttf
Normal file
BIN
experimental/canvaskit/tests/assets/NotoSerif-Regular.ttf
Normal file
Binary file not shown.
@ -517,9 +517,9 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
|
||||
it('supports gradients, which respect clip/save/restore', function(done) {
|
||||
LoadCanvasKit.then(catchException(done, () => {
|
||||
multipleCanvasTest('gradients_clip', done, (canvas) => {
|
||||
let ctx = canvas.getContext('2d');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
var rgradient = ctx.createRadialGradient(200, 300, 10, 100, 100, 300);
|
||||
const rgradient = ctx.createRadialGradient(200, 300, 10, 100, 100, 300);
|
||||
|
||||
rgradient.addColorStop(0, 'red');
|
||||
rgradient.addColorStop(.7, 'white');
|
||||
@ -539,7 +539,7 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
|
||||
ctx.save();
|
||||
ctx.clip();
|
||||
|
||||
var lgradient = ctx.createLinearGradient(200, 20, 420, 40);
|
||||
const lgradient = ctx.createLinearGradient(200, 20, 420, 40);
|
||||
|
||||
lgradient.addColorStop(0, 'green');
|
||||
lgradient.addColorStop(.5, 'cyan');
|
||||
@ -844,8 +844,8 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
|
||||
LoadCanvasKit.then(catchException(done, () => {
|
||||
multipleCanvasTest('path2d_line_drawing_operations', done, (canvas) => {
|
||||
let ctx = canvas.getContext('2d');
|
||||
var clock;
|
||||
var path;
|
||||
let clock;
|
||||
let path;
|
||||
if (canvas.makePath2D) {
|
||||
clock = canvas.makePath2D('M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z');
|
||||
path = canvas.makePath2D();
|
||||
|
118
experimental/canvaskit/tests/font.spec.js
Normal file
118
experimental/canvaskit/tests/font.spec.js
Normal file
@ -0,0 +1,118 @@
|
||||
// The increased timeout is especially needed with larger binaries
|
||||
// like in the debug/gpu build
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
|
||||
|
||||
describe('CanvasKit\'s Path Behavior', function() {
|
||||
// Note, don't try to print the CanvasKit object - it can cause Karma/Jasmine to lock up.
|
||||
var CanvasKit = null;
|
||||
const LoadCanvasKit = new Promise(function(resolve, reject) {
|
||||
if (CanvasKit) {
|
||||
resolve();
|
||||
} else {
|
||||
CanvasKitInit({
|
||||
locateFile: (file) => '/canvaskit/'+file,
|
||||
}).ready().then((_CanvasKit) => {
|
||||
CanvasKit = _CanvasKit;
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
const CANVAS_WIDTH = 600;
|
||||
const CANVAS_HEIGHT = 600;
|
||||
|
||||
beforeEach(function() {
|
||||
container.innerHTML = `
|
||||
<canvas width=600 height=600 id=test></canvas>
|
||||
<canvas width=600 height=600 id=report></canvas>`;
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container.innerHTML = '';
|
||||
});
|
||||
|
||||
it('can draw shaped and unshaped text', function(done) {
|
||||
let fontBuffer = null;
|
||||
|
||||
// This font is known to support kerning
|
||||
const skFontLoaded = fetch('/assets/NotoSerif-Regular.ttf').then(
|
||||
(response) => response.arrayBuffer()).then(
|
||||
(buffer) => {
|
||||
fontBuffer = buffer;
|
||||
});
|
||||
|
||||
LoadCanvasKit.then(catchException(done, () => {
|
||||
skFontLoaded.then(() => {
|
||||
// This is taken from example.html
|
||||
const surface = CanvasKit.MakeCanvasSurface('test');
|
||||
expect(surface).toBeTruthy('Could not make surface')
|
||||
if (!surface) {
|
||||
done();
|
||||
return;
|
||||
}
|
||||
const canvas = surface.getCanvas();
|
||||
const paint = new CanvasKit.SkPaint();
|
||||
|
||||
paint.setColor(CanvasKit.BLUE);
|
||||
paint.setStyle(CanvasKit.PaintStyle.Stroke);
|
||||
|
||||
const fontMgr = CanvasKit.SkFontMgr.RefDefault();
|
||||
const notoSerif = fontMgr.MakeTypefaceFromData(fontBuffer);
|
||||
|
||||
const textPaint = new CanvasKit.SkPaint();
|
||||
// use the built-in monospace typeface.
|
||||
const textFont = new CanvasKit.SkFont(notoSerif, 20);
|
||||
|
||||
canvas.drawRect(CanvasKit.LTRBRect(30, 30, 200, 200), paint);
|
||||
canvas.drawText('This text is not shaped, and overflows the boundry',
|
||||
35, 50, textPaint, textFont);
|
||||
|
||||
const shapedText = new CanvasKit.ShapedText({
|
||||
font: textFont,
|
||||
leftToRight: true,
|
||||
text: 'This text *is* shaped, and wraps to the right width.',
|
||||
width: 160,
|
||||
});
|
||||
const textBoxX = 35;
|
||||
const textBoxY = 55;
|
||||
canvas.drawText(shapedText, textBoxX, textBoxY, textPaint);
|
||||
const bounds = shapedText.getBounds();
|
||||
|
||||
bounds.fLeft += textBoxX;
|
||||
bounds.fRight += textBoxX;
|
||||
bounds.fTop += textBoxY;
|
||||
bounds.fBottom += textBoxY
|
||||
|
||||
canvas.drawRect(bounds, paint);
|
||||
const SHAPE_TEST_TEXT = 'VAVAVAVAVAFIfi';
|
||||
const textFont2 = new CanvasKit.SkFont(notoSerif, 60);
|
||||
const shapedText2 = new CanvasKit.ShapedText({
|
||||
font: textFont2,
|
||||
leftToRight: true,
|
||||
text: SHAPE_TEST_TEXT,
|
||||
width: 600,
|
||||
});
|
||||
|
||||
canvas.drawText('no kerning ↓', 10, 240, textPaint, textFont);
|
||||
canvas.drawText(SHAPE_TEST_TEXT, 10, 300, textPaint, textFont2);
|
||||
canvas.drawText(shapedText2, 10, 300, textPaint);
|
||||
canvas.drawText('kerning ↑', 10, 390, textPaint, textFont);
|
||||
|
||||
surface.flush();
|
||||
|
||||
paint.delete();
|
||||
notoSerif.delete();
|
||||
textPaint.delete();
|
||||
textFont.delete();
|
||||
shapedText.delete();
|
||||
textFont2.delete();
|
||||
shapedText2.delete();
|
||||
reportSurface(surface, 'text_shaping', done);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
// TODO more tests
|
||||
});
|
@ -33,22 +33,6 @@ describe('CanvasKit\'s Path Behavior', function() {
|
||||
container.innerHTML = '';
|
||||
});
|
||||
|
||||
function reportSurface(surface, testname, done) {
|
||||
// In docker, the webgl canvas is blank, but the surface has the pixel
|
||||
// data. So, we copy it out and draw it to a normal canvas to take a picture.
|
||||
// To be consistent across CPU and GPU, we just do it for all configurations
|
||||
// (even though the CPU canvas shows up after flush just fine).
|
||||
let pixels = surface.getCanvas().readPixels(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||
pixels = new Uint8ClampedArray(pixels.buffer);
|
||||
var imageData = new ImageData(pixels, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||
|
||||
let reportingCanvas = document.getElementById('report');
|
||||
reportingCanvas.getContext('2d').putImageData(imageData, 0, 0);
|
||||
reportCanvas(reportingCanvas, testname).then(() => {
|
||||
done();
|
||||
}).catch(reportError(done));
|
||||
}
|
||||
|
||||
it('can draw a path', function(done) {
|
||||
LoadCanvasKit.then(catchException(done, () => {
|
||||
// This is taken from example.html
|
||||
@ -134,7 +118,7 @@ describe('CanvasKit\'s Path Behavior', function() {
|
||||
canvas.drawArc(CanvasKit.LTRBRect(55, 35, 95, 80), 15, 270, true, paint);
|
||||
|
||||
const font = new CanvasKit.SkFont(null, 20);
|
||||
canvas.drawText('this is ascii text', 5, 100, font, paint);
|
||||
canvas.drawText('this is ascii text', 5, 100, paint, font);
|
||||
|
||||
const blob = CanvasKit.SkTextBlob.MakeFromText('Unicode chars 💩 é É ص', font);
|
||||
canvas.drawTextBlob(blob, 5, 130, paint);
|
||||
@ -189,7 +173,7 @@ describe('CanvasKit\'s Path Behavior', function() {
|
||||
canvas.clear(CanvasKit.Color(255, 255, 255, 1.0));
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
canvas.drawText('This is text', 10, 280, textFont, textPaint);
|
||||
canvas.drawText('This is text', 10, 280, textPaint, textFont);
|
||||
surface.flush();
|
||||
dpe.delete();
|
||||
path.delete();
|
||||
|
19
experimental/canvaskit/tests/util.js
Normal file
19
experimental/canvaskit/tests/util.js
Normal file
@ -0,0 +1,19 @@
|
||||
// The size of the golden images (DMs)
|
||||
const CANVAS_WIDTH = 600;
|
||||
const CANVAS_HEIGHT = 600;
|
||||
|
||||
function reportSurface(surface, testname, done) {
|
||||
// In docker, the webgl canvas is blank, but the surface has the pixel
|
||||
// data. So, we copy it out and draw it to a normal canvas to take a picture.
|
||||
// To be consistent across CPU and GPU, we just do it for all configurations
|
||||
// (even though the CPU canvas shows up after flush just fine).
|
||||
let pixels = surface.getCanvas().readPixels(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||
pixels = new Uint8ClampedArray(pixels.buffer);
|
||||
const imageData = new ImageData(pixels, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||
|
||||
let reportingCanvas = document.getElementById('report');
|
||||
reportingCanvas.getContext('2d').putImageData(imageData, 0, 0);
|
||||
reportCanvas(reportingCanvas, testname).then(() => {
|
||||
done();
|
||||
}).catch(reportError(done));
|
||||
}
|
16
gn/skia.gni
16
gn/skia.gni
@ -2,7 +2,17 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
declare_args() {
|
||||
skia_use_icu = !is_fuchsia && !is_ios
|
||||
skia_enable_skshaper = true
|
||||
if (!defined(is_skia_standalone)) {
|
||||
is_skia_standalone = false
|
||||
}
|
||||
is_skia_dev_build = is_skia_standalone && !is_official_build
|
||||
|
||||
declare_args() {
|
||||
skia_enable_gpu = true
|
||||
skia_enable_skshaper = true
|
||||
skia_enable_tools = is_skia_dev_build
|
||||
skia_use_icu = !is_fuchsia && !is_ios
|
||||
}
|
||||
|
||||
# Our tools require static linking (they use non-exported symbols), and the GPU backend.
|
||||
skia_enable_tools = skia_enable_tools && !is_component_build && skia_enable_gpu
|
||||
|
@ -2,7 +2,7 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
DOCKER_IMAGE = 'gcr.io/skia-public/emsdk-release:1.38.16_v1'
|
||||
DOCKER_IMAGE = 'gcr.io/skia-public/canvaskit-emsdk:1.38.27_v1'
|
||||
INNER_BUILD_SCRIPT = '/SRC/skia/infra/canvaskit/build_canvaskit.sh'
|
||||
|
||||
BUILD_PRODUCTS_ISOLATE_WHITELIST_WASM = [
|
||||
|
@ -23,7 +23,7 @@
|
||||
"[START_DIR]/cache/work:/SRC",
|
||||
"--volume",
|
||||
"[START_DIR]/cache/docker/canvaskit:/OUT",
|
||||
"gcr.io/skia-public/emsdk-release:1.38.16_v1",
|
||||
"gcr.io/skia-public/canvaskit-emsdk:1.38.27_v1",
|
||||
"/SRC/skia/infra/canvaskit/build_canvaskit.sh",
|
||||
"debug"
|
||||
],
|
||||
|
@ -23,7 +23,7 @@
|
||||
"[START_DIR]/cache/work:/SRC",
|
||||
"--volume",
|
||||
"[START_DIR]/cache/docker/canvaskit:/OUT",
|
||||
"gcr.io/skia-public/emsdk-release:1.38.16_v1",
|
||||
"gcr.io/skia-public/canvaskit-emsdk:1.38.27_v1",
|
||||
"/SRC/skia/infra/canvaskit/build_canvaskit.sh",
|
||||
"cpu"
|
||||
],
|
||||
|
6
infra/canvaskit/docker/Makefile
Normal file
6
infra/canvaskit/docker/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
EMSDK_VERSION=1.38.27_v1
|
||||
|
||||
publish_canvaskit_emsdk:
|
||||
docker build -t canvaskit-emsdk ./canvaskit-emsdk/
|
||||
docker tag emsdk-base gcr.io/skia-public/canvaskit-emsdk:${EMSDK_VERSION}
|
||||
docker push gcr.io/skia-public/canvaskit-emsdk:${EMSDK_VERSION}
|
7
infra/canvaskit/docker/canvaskit-emsdk/Dockerfile
Normal file
7
infra/canvaskit/docker/canvaskit-emsdk/Dockerfile
Normal file
@ -0,0 +1,7 @@
|
||||
# A Docker image that augments the Emscripten SDK Docker image
|
||||
# with anything needed to build Canvaskit
|
||||
|
||||
FROM gcr.io/skia-public/emsdk-release:1.38.27_v1
|
||||
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
|
||||
libfreetype6-dev
|
@ -3,6 +3,8 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("../../gn/skia.gni")
|
||||
|
||||
declare_args() {
|
||||
skia_enable_skottie = true
|
||||
}
|
||||
@ -14,7 +16,7 @@ config("public_config") {
|
||||
}
|
||||
}
|
||||
|
||||
source_set("skottie") {
|
||||
component("skottie") {
|
||||
if (skia_enable_skottie) {
|
||||
import("skottie.gni")
|
||||
public_configs = [ ":public_config" ]
|
||||
@ -49,93 +51,95 @@ if (defined(is_skia_standalone)) {
|
||||
}
|
||||
}
|
||||
|
||||
source_set("tests") {
|
||||
if (skia_enable_skottie) {
|
||||
testonly = true
|
||||
if (skia_enable_tools) {
|
||||
source_set("tests") {
|
||||
if (skia_enable_skottie) {
|
||||
testonly = true
|
||||
|
||||
configs += [
|
||||
"../..:skia_private",
|
||||
"../..:tests_config",
|
||||
]
|
||||
sources = [
|
||||
"src/SkottieTest.cpp",
|
||||
]
|
||||
configs += [
|
||||
"../..:skia_private",
|
||||
"../..:tests_config",
|
||||
]
|
||||
sources = [
|
||||
"src/SkottieTest.cpp",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":skottie",
|
||||
"../..:gpu_tool_utils",
|
||||
"../..:skia",
|
||||
]
|
||||
deps = [
|
||||
":skottie",
|
||||
"../..:gpu_tool_utils",
|
||||
"../..:skia",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
source_set("fuzz") {
|
||||
if (skia_enable_skottie) {
|
||||
source_set("fuzz") {
|
||||
if (skia_enable_skottie) {
|
||||
testonly = true
|
||||
|
||||
configs += [ "../..:skia_private" ]
|
||||
include_dirs = [
|
||||
"../../tools",
|
||||
"../../tools/flags",
|
||||
"../../tools/fonts",
|
||||
]
|
||||
sources = [
|
||||
"../../tools/Resources.cpp",
|
||||
"../../tools/fonts/SkTestFontMgr.cpp",
|
||||
"../../tools/fonts/SkTestSVGTypeface.cpp",
|
||||
"../../tools/fonts/SkTestTypeface.cpp",
|
||||
"fuzz/FuzzSkottieJSON.cpp",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../..:experimental_svg_model",
|
||||
"../..:skia",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":skottie",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("tool") {
|
||||
testonly = true
|
||||
|
||||
configs += [ "../..:skia_private" ]
|
||||
include_dirs = [
|
||||
"../../tools",
|
||||
"../../tools/flags",
|
||||
"../../tools/fonts",
|
||||
]
|
||||
sources = [
|
||||
"../../tools/Resources.cpp",
|
||||
"../../tools/fonts/SkTestFontMgr.cpp",
|
||||
"../../tools/fonts/SkTestSVGTypeface.cpp",
|
||||
"../../tools/fonts/SkTestTypeface.cpp",
|
||||
"fuzz/FuzzSkottieJSON.cpp",
|
||||
"src/SkottieTool.cpp",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../..:experimental_svg_model",
|
||||
"../..:flags",
|
||||
"../..:skia",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":skottie",
|
||||
":utils",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("tool") {
|
||||
testonly = true
|
||||
source_set("gm") {
|
||||
if (skia_enable_skottie) {
|
||||
testonly = true
|
||||
|
||||
configs += [ "../..:skia_private" ]
|
||||
sources = [
|
||||
"src/SkottieTool.cpp",
|
||||
]
|
||||
# would be nice to have a gm_config
|
||||
include_dirs = [ "../../gm" ]
|
||||
|
||||
deps = [
|
||||
"../..:flags",
|
||||
"../..:skia",
|
||||
]
|
||||
configs += [ "../..:skia_private" ]
|
||||
sources = [
|
||||
"gm/SkottieGM.cpp",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":skottie",
|
||||
":utils",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("gm") {
|
||||
if (skia_enable_skottie) {
|
||||
testonly = true
|
||||
|
||||
# would be nice to have a gm_config
|
||||
include_dirs = [ "../../gm" ]
|
||||
|
||||
configs += [ "../..:skia_private" ]
|
||||
sources = [
|
||||
"gm/SkottieGM.cpp",
|
||||
]
|
||||
|
||||
deps = [
|
||||
":skottie",
|
||||
":utils",
|
||||
"../..:gpu_tool_utils",
|
||||
"../..:skia",
|
||||
"../..:tool_utils",
|
||||
]
|
||||
deps = [
|
||||
":skottie",
|
||||
":utils",
|
||||
"../..:gpu_tool_utils",
|
||||
"../..:skia",
|
||||
"../..:tool_utils",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("../../gn/skia.gni")
|
||||
|
||||
config("public_config") {
|
||||
include_dirs = [ "include" ]
|
||||
}
|
||||
@ -17,7 +19,7 @@ component("sksg") {
|
||||
]
|
||||
}
|
||||
|
||||
if (defined(is_skia_standalone)) {
|
||||
if (defined(is_skia_standalone) && skia_enable_tools) {
|
||||
source_set("tests") {
|
||||
testonly = true
|
||||
|
||||
|
@ -15,7 +15,7 @@ config("public_config") {
|
||||
}
|
||||
}
|
||||
|
||||
source_set("skshaper") {
|
||||
component("skshaper") {
|
||||
if (skia_enable_skshaper) {
|
||||
import("skshaper.gni")
|
||||
public_configs = [ ":public_config" ]
|
||||
|
15
third_party/icu/BUILD.gn
vendored
15
third_party/icu/BUILD.gn
vendored
@ -25,6 +25,8 @@ if (skia_use_icu) {
|
||||
}
|
||||
data_dir = "../externals/icu/"
|
||||
if (target_cpu == "wasm") {
|
||||
# Use a super super super stripped down version for wasm,
|
||||
# which is the same thing flutter is using.
|
||||
data_dir += "flutter"
|
||||
} else if (is_android) {
|
||||
data_dir += "android"
|
||||
@ -37,8 +39,12 @@ if (skia_use_icu) {
|
||||
if (target_cpu == "wasm") {
|
||||
_u_icu_version_major_num = "63" # defined in source/common/unicode/uvernum.h
|
||||
script = "make_data_cpp.py"
|
||||
inputs = [ "$data_dir/icudtl.dat" ]
|
||||
outputs = [ data_assembly ]
|
||||
inputs = [
|
||||
"$data_dir/icudtl.dat",
|
||||
]
|
||||
outputs = [
|
||||
data_assembly,
|
||||
]
|
||||
args = [
|
||||
"icudt${_u_icu_version_major_num}_dat",
|
||||
rebase_path(inputs[0], root_build_dir),
|
||||
@ -80,6 +86,11 @@ if (skia_use_icu) {
|
||||
"U_ENABLE_DYLOAD=0",
|
||||
"U_I18N_IMPLEMENTATION",
|
||||
]
|
||||
if (target_cpu == "wasm") {
|
||||
# Tell ICU that we are a 32 bit platform, otherwise,
|
||||
# double-conversion-utils.h doesn't know how to operate.
|
||||
defines += [ "__i386__" ]
|
||||
}
|
||||
sources = icu_sources
|
||||
if (is_win) {
|
||||
deps = [
|
||||
|
Loading…
Reference in New Issue
Block a user