### Install npm Dependencies and Build Example Source: https://github.com/google/skia/blob/main/modules/canvaskit/README.md Installs all npm dependencies and builds the release version of CanvasKit for local example testing. This command only needs to be run when setting up or if npm dependencies change. ```bash npm ci make release # make debug is much faster and has better error messages make local-example ``` -------------------------------- ### Build Skia Example on Mac Source: https://github.com/google/skia/blob/main/site/docs/dev/contrib/bazel.md Use this command to build the bazel_test_exe example application on a Mac host. Ensure Xcode is installed and xcode-select is in your PATH. ```bash bazel build //example:bazel_test_exe ``` -------------------------------- ### Run Skia Example on Linux Source: https://github.com/google/skia/blob/main/site/docs/dev/contrib/bazel.md Execute the built hello_world_gl example application using Bazel on a Linux host. ```bash bazel run //example:hello_world_gl ``` -------------------------------- ### Install and Run SkQP Tests via ADB Source: https://github.com/google/skia/blob/main/tools/skqp/README.md Install the built SkQP APK on an Android device using ADB and then run the instrumented tests. This command clears existing logs and starts the test runner. ```bash adb install -r out/skqp/skqp-universal-debug.apk adb logcat -c adb shell am instrument -w org.skia.skqp ``` -------------------------------- ### Basic CMake Project Setup Source: https://github.com/google/skia/blob/main/experimental/lowp-basic/CMakeLists.txt Sets the minimum CMake version, project name, and C++ standard. Use this as a starting point for Skia-related CMake projects. ```cmake cmake_minimum_required(VERSION 3.20) project(lowp_basic) set(CMAKE_CXX_STANDARD 17) ``` -------------------------------- ### Install depot_tools Source: https://github.com/google/skia/blob/main/site/docs/user/download.md Clone the depot_tools repository and add it to your PATH. This installs gclient, git-cl, and Ninja. ```shell git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' export PATH="${PWD}/depot_tools:${PATH}" ``` -------------------------------- ### Install Dependencies Source: https://github.com/google/skia/blob/main/tools/lottiecap/README.md Run this command to install the necessary Node.js dependencies for the lottiecap tool. ```bash npm install ``` -------------------------------- ### Start Skia Viewer on Android with Arguments Source: https://github.com/google/skia/blob/main/site/docs/user/sample/viewer.md Launches the Skia Viewer on an Android device and passes command-line arguments. This example starts the viewer with the '--androidndkfonts' argument. ```bash adb shell am start -a android.intent.action.MAIN -n org.skia.viewer/org.skia.viewer.ViewerActivity --es args '"--androidndkfonts"' ``` -------------------------------- ### Generate PDF with Skia Source: https://github.com/google/skia/blob/main/site/docs/user/sample/pdf.md Example demonstrating the basic usage of Skia's PDF backend to create a PDF document. No specific setup is required beyond including Skia. ```cpp void PDF(SkCanvas* canvas) { // Example content drawn to the canvas. // This content will be rendered into the PDF. SkPaint paint; paint.setColor(SK_ColorRED); canvas->drawRect(SkRect::MakeXYWH(10, 10, 100, 100), paint); paint.setColor(SK_ColorBLUE); canvas->drawCircle(150, 150, 50, paint); } ``` -------------------------------- ### Shaping Example Initialization Source: https://github.com/google/skia/blob/main/site/docs/user/modules/canvaskit.md Initializes the ShapingExample by making a canvas surface and fetching font data. This is a setup for text shaping demonstrations. ```javascript function ShapingExample(CanvasKit) { const surface = CanvasKit.MakeCanvasSurface('shaping'); if (!surface) { console.log('Could not make surface'); return; } let robotoData = null; fetch('https://cdn.skia.org/google-web-fonts/Roboto-Regular.ttf').then((resp) => { ``` -------------------------------- ### Install and Run SkQP Tests Source: https://github.com/google/skia/blob/main/site/docs/dev/testing/skqp.md Install the SkQP APK, clear logs, run tests, and monitor output. Ensure you use the correct APK SHA. ```bash adb install -r skqp-universal-{APK_SHA_HERE}.apk adb logcat -c adb shell am instrument -w org.skia.skqp ``` ```bash adb logcat TestRunner org.skia.skqp skia DEBUG "*:S" ``` -------------------------------- ### Build Skia Example on Linux Source: https://github.com/google/skia/blob/main/site/docs/dev/contrib/bazel.md Use this command to build the hello_world_gl example application on a Linux host. It utilizes a hermetic C++ toolchain and the sk_app framework. ```bash bazel build //example:hello_world_gl ``` -------------------------------- ### Initialize Skottie-WASM and Load Assets Source: https://github.com/google/skia/blob/main/tools/perf-canvaskit-puppeteer/skottie-frames.html Initializes CanvasKit, loads Lottie JSON, and fetches necessary fonts and assets. This setup is required before starting the animation benchmark. ```javascript const WIDTH = 1000; const HEIGHT = 1000; const WARM_UP_FRAMES = 0; // No warmup, so that the jank of initial frames gets measured. // We sample MAX_FRAMES or until MAX_SAMPLE_SECONDS has elapsed. const MAX_FRAMES = 600; // ~10s at 60fps const MAX_SAMPLE_MS = 90 * 1000; // in case something takes a while, stop after 90 seconds. const LOTTIE_JSON_PATH = '/static/lottie.json'; const ASSETS_PATH = '/static/assets/'; (function() { const loadKit = CanvasKitInit({ locateFile: (file) => '/static/' + file, }); const loadLottie = fetch(LOTTIE_JSON_PATH).then((resp) => { return resp.text(); }); const loadFontsAndAssets = loadLottie.then((jsonStr) => { const lottie = JSON.parse(jsonStr); const promises = []; promises.push(...loadFonts(lottie.fonts)); promises.push(...loadAssets(lottie.assets)); return Promise.all(promises); }); Promise.all([ loadKit, loadLottie, loadFontsAndAssets ]).then((values) => { const [CanvasKit, json, externalAssets] = values; console.log(externalAssets); const assets = {}; for (const asset of externalAssets) { if (asset) { assets[asset.name] = asset.bytes; } } const loadStart = performance.now(); const animation = CanvasKit.MakeManagedAnimation(json, assets); const loadTime = performance.now() - loadStart; window._perfData = { json_load_ms: loadTime, }; const duration = animation.duration() * 1000; const bounds = CanvasKit.LTRBRect(0, 0, WIDTH, HEIGHT); const urlSearchParams = new URLSearchParams(window.location.search); let glversion = 2; if (urlSearchParams.has('webgl1')) { glversion = 1; } const surface = getSurface(CanvasKit, glversion); if (!surface) { console.error('Could not make surface', window._error); return; } const canvas = surface.getCanvas(); document.getElementById('start_bench').addEventListener('click', async () => { const startTime = Date.now(); const damageRect = Float32Array.of(0, 0, 0, 0); function draw() { const seek = ((Date.now() - startTime) / duration) % 1.0; const damage = animation.seek(seek, damageRect); if (damage[2] > damage[0] && damage[3] > damage[1]) { animation.render(canvas, bounds); } } startTimingFrames(draw, surface, WARM_UP_FRAMES, MAX_FRAMES, MAX_SAMPLE_MS).then((results) => { Object.assign(window._perfData, results); window._perfDone = true; }).catch((error) => { window._error = error; }); }); console.log('Perf is ready'); window._perfReady = true; }); })(); ``` -------------------------------- ### Install and Run iOS Test Binaries Source: https://github.com/google/skia/blob/main/site/docs/user/build.md Use `ios-deploy` to install and run signed iOS test binaries on a device. The `--args` flag can be used to pass arguments to the application. ```bash ios-deploy -b out/Debug/dm.app -d --args "--match foo" ``` -------------------------------- ### Run Skia Example with Flags on Linux Source: https://github.com/google/skia/blob/main/site/docs/dev/contrib/bazel.md Pass custom flags to the hello_world_gl example application when running it with Bazel on a Linux host. Use '--' to separate Bazel flags from application flags. ```bash bazel run //example:hello_world_gl -- --flag_one=apple --flag_two=cherry ``` -------------------------------- ### Install google-pprof on Debian/Ubuntu Source: https://github.com/google/skia/blob/main/site/docs/dev/testing/profiling.md Installs the google-pprof analysis tool for external users. It is recommended to create an alias for 'pprof'. ```bash # On Debian/Ubuntu: $ sudo apt-get install google-perftools ``` -------------------------------- ### Helper Function for Full Example Source: https://github.com/google/skia/blob/main/infra/bots/README.recipes.md A helper function 'myfunc' used within the full example recipe, taking the API and an index 'i' as parameters. ```python def myfunc(api, i): pass ``` -------------------------------- ### Install Skia build dependencies Source: https://github.com/google/skia/blob/main/site/docs/user/build.md If header files are missing during the build process, run this script to install the necessary system dependencies. ```bash tools/install_dependencies.sh ``` -------------------------------- ### Install Node.js and ios-deploy Source: https://github.com/google/skia/blob/main/site/docs/dev/testing/ios.md Install Node.js and the ios-deploy package using Homebrew and npm. This is necessary for deploying applications to iOS devices from the command line. ```bash $ brew update $ brew install node $ npm install ios-deploy ``` -------------------------------- ### Example: Trigger a specific job with SK CLI Source: https://github.com/google/skia/blob/main/infra/bots/README.md An example demonstrating how to trigger a specific job, 'Test-Mac14-Clang-MacMini9.1-GPU-AppleM1-arm64-Debug-All', using the 'sk try' command. ```bash $ ./bin/sk try Test-Mac14-Clang-MacMini9.1-GPU-AppleM1-arm64-Debug-All ``` -------------------------------- ### Compile Skottie iOS Example for CPU Backend Source: https://github.com/google/skia/blob/main/tools/skottie_ios_app/README.md Use this to compile the Skottie iOS example app for the CPU rendering backend. This configuration disables Ganesh and PDF support. ```bash cd $SKIA_ROOT_DIRECTORY mkdir -p out/ios_arm64_cpu cat > out/ios_arm64_cpu/args.gn < { CanvasKitInit({ locateFile: (file) => '/static/' + file, }).then(run); }); function run(CanvasKit) { const surface = getSurface(CanvasKit); if (!surface) { console.error('Could not make surface', window._error); return; } const skcanvas = surface.getCanvas(); const grContext = surface.grContext; document.getElementById('start_bench').addEventListener('click', () => { // Initialize drawing related objects const svgElement = svgObjectElement.contentDocument; const svgPathAndFillColorPairs = svgToPathAndFillColorPairs(svgElement, CanvasKit); const paint = new CanvasKit.Paint(); paint.setAntiAlias(true); paint.setStyle(CanvasKit.PaintStyle.Fill); let paintColor = CanvasKit.BLACK; // Path is large, scale canvas so entire path is visible skcanvas.scale(0.5, 0.5); // Initialize perf data let currentFrameNumber = 0; const frameTimesMs = new Float32Array(MAX_FRAMES); let startTimeMs = performance.now(); let previousFrameTimeMs = performance.now(); const resourceCacheUsageBytes = new Float32Array(MAX_FRAMES); const usedJSHeapSizesBytes = new Float32Array(MAX_FRAMES); function drawFrame() { // Draw complex path with random translations and rotations. let randomHorizontalTranslation = 0; let randomVerticalTranslation = 0; let randomRotation = 0; if (urlSearchParams.has('translate')) { randomHorizontalTranslation = Math.random() * 50 - 25; randomVerticalTranslation = Math.random() * 50 - 25; } if (urlSearchParams.has('snap')) { randomHorizontalTranslation = Math.round(randomHorizontalTranslation); randomVerticalTranslation = Math.round(randomVerticalTranslation); } if (urlSearchParams.has('opacity')) { paintColor = TRANSPARENT_PINK; } if (urlSearchParams.has('rotate')) { randomRotation = (Math.random() - 0.5) / 20; } skcanvas.clear(CanvasKit.WHITE); for (const [path, color] of svgPathAndFillColorPairs) { path.transform([ Math.cos(randomRotation), -Math.sin(randomRotation), randomHorizontalTranslation, Math.sin(randomRotation), Math.cos(randomRotation), randomVerticalTranslation, 0, 0, 1 ]); paint.setColor(paintColor); skcanvas.drawPath(path, paint); } surface.flush(); // Record perf data: measure frame times, memory usage const currentFrameTimeMs = performance.now(); frameTimesMs[currentFrameNumber] = currentFrameTimeMs - previousFrameTimeMs; previousFrameTimeMs = currentFrameTimeMs; resourceCacheUsageBytes[currentFrameNumber] = grContext.getResourceCacheUsageBytes(); usedJSHeapSizesBytes[currentFrameNumber] = window.performance.memory.totalJSHeapSize; currentFrameNumber++; const timeSinceStart = performance.now() - startTimeMs; if (currentFrameNumber >= MAX_FRAMES || timeSinceStart >= MAX_SAMPLE_MS) { window._perfData = { frames_ms: Array.from(frameTimesMs).slice(0, currentFrameNumber), resourceCacheUsage_bytes: Array.from(resourceCacheUsageBytes).slice(0, currentFrameNumber), usedJSHeapSizes_bytes: Array.from(usedJSHeapSizesBytes).slice(0, currentFrameNumber), }; window._perfDone = true; return; } window.requestAnimationFrame(drawFrame); } window.requestAnimationFrame(drawFrame); }); console.log('Perf is ready'); window._perfReady = true; } ``` -------------------------------- ### Full Example: Drawing Text on Canvas Source: https://github.com/google/skia/blob/main/site/docs/user/modules/quickstart.md An end-to-end example demonstrating loading a font, setting up styles, building a paragraph, and drawing it on a CanvasKit surface. Ensure CanvasKit is loaded and the font URL is accessible. ```javascript const loadFont = fetch('https://cdn.skia.org/misc/Roboto-Regular.ttf') .then((response) => response.arrayBuffer()); Promise.all([ckLoaded, loadFont]).then(([CanvasKit, robotoData]) => { const surface = CanvasKit.MakeCanvasSurface('foo3'); const canvas = surface.getCanvas(); canvas.clear(CanvasKit.Color4f(0.9, 0.9, 0.9, 1.0)); const fontMgr = CanvasKit.FontMgr.FromData([robotoData]); const paraStyle = new CanvasKit.ParagraphStyle({ textStyle: { color: CanvasKit.BLACK, fontFamilies: ['Roboto'], fontSize: 28, }, textAlign: CanvasKit.TextAlign.Left, }); const text = 'Any sufficiently entrenched technology is indistinguishable from Javascript'; const builder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr); builder.addText(text); const paragraph = builder.build(); paragraph.layout(290); // width in pixels to use when wrapping text canvas.drawParagraph(paragraph, 10, 10); surface.flush(); }); ``` -------------------------------- ### Vulkan Info with Installed Drivers Source: https://github.com/google/skia/blob/main/infra/bots/assets/mesa_intel_driver_linux_22/README.md Example output of vulkaninfo showing the system's installed Mesa drivers (22.0.5) without specific environment variables set. ```console chrome-bot@skia-e-linux-600:~/mesa/foo$ vulkaninfo | grep Mesa WARNING: lavapipe is not a conformant vulkan implementation, testing use only. VK_LAYER_MESA_overlay (Mesa Overlay layer) Vulkan version 1.3.211, layer version 1: WARNING: lavapipe is not a conformant vulkan implementation, testing use only. driverName = Intel open-source Mesa driver driverInfo = Mesa 22.0.5 driverName = Intel open-source Mesa driver driverInfo = Mesa 22.0.5 driverInfo = Mesa 22.0.5 (LLVM 14.0.4) driverInfo = Mesa 22.0.5 (LLVM 14.0.4) ``` -------------------------------- ### Start Local Web Server Source: https://github.com/google/skia/blob/main/demos.skia.org/README.md Execute this command from the project root to launch a local web server for testing. ```bash make local ``` -------------------------------- ### Initialize WebGPU and Skia Demo Source: https://github.com/google/skia/blob/main/experimental/webgpu-bazel/example/index.html Checks for WebGPU support, requests an adapter and device, initializes the WebGPUKit, and sets up the Skia demo. Requires the browser to support WebGPU. ```javascript if (navigator.gpu) { log("WebGPU detected") WebGPUDemo(); } else { log("No WebGPU support.") } function log(s) { document.getElementById("log").innerText = s; } async function WebGPUDemo() { const adapter = await navigator.gpu.requestAdapter(); if (!adapter) { log("Could not load an adapter. For Chrome, try running with --enable-features=Vulkan --enable-unsafe-webgpu"); return; } const device = await adapter.requestDevice(); console.log(adapter, device); const wk = await WebGPUKitInit({locateFile: (file) => "/build/"+file}); // https://github.com/emscripten-core/emscripten/issues/12750#issuecomment-725001907 wk.preinitializedWebGPUDevice = device; const demo = new wk.Demo(); if (!demo.init("#webgpu-demo-canvas", 600, 600)) { log("Failed to initialize Skia context"); return; } let demoKind = wk.DemoKind.RUNTIME_EFFECT; document.getElementById("runtime-effect").style["text-decoration"] = "underline"; document.getElementById("solid-color").onclick = function() { demoKind = wk.DemoKind.SOLID_COLOR; document.getElementById("solid-color").style["text-decoration"] = "underline"; document.getElementById("gradient").style["text-decoration"] = "none"; document.getElementById("runtime-effect").style["text-decoration"] = "none"; }; document.getElementById("gradient").onclick = function() { demoKind = wk.DemoKind.GRADIENT; document.getElementById("solid-color").style["text-decoration"] = "none"; document.getElementById("gradient").style["text-decoration"] = "underline"; document.getElementById("runtime-effect").style["text-decoration"] = "none"; }; document.getElementById("runtime-effect").onclick = function() { demoKind = wk.DemoKind.RUNTIME_EFFECT; document.getElementById("solid-color").style["text-decoration"] = "none"; document.getElementById("gradient").style["text-decoration"] = "none"; document.getElementById("runtime-effect").style["text-decoration"] = "underline"; }; let timestamp = 0; async function frame(now) { if (demoKind == wk.DemoKind.RUNTIME_EFFECT || timestamp == 0 || now - timestamp >= 1000) { timestamp = now; demo.setKind(demoKind); await demo.draw(timestamp); } requestAnimationFrame(frame); } requestAnimationFrame(frame); } ``` -------------------------------- ### Get Grapheme Boundaries in JavaScript Source: https://github.com/google/skia/blob/main/modules/canvaskit/npm_build/paragraphs.html Calculates the start indices of graphemes in a given text using Intl.Segmenter. Ensure the Intl.Segmenter API is available in your environment. ```javascript function getGraphemeBoundaries(text) { const segmenter = new Intl.Segmenter(['en'], {type: 'grapheme'}); const segments = segmenter.segment(text); const graphemeBoundaries = []; for (const segment of segments) { graphemeBoundaries.push(segment.index); } graphemeBoundaries.push(text.length); return graphemeBoundaries; } ``` -------------------------------- ### Build and Run Skia Benchmarking Tools Source: https://github.com/google/skia/blob/main/infra/bots/assets/text_blob_traces/README.md Sets up the Skia build environment, compiles necessary tools like nanobench and blob_cache_sim, and runs a text trace benchmark. ```bash tools/git-sync-deps bin/gn gen out/release --args='is_debug=false' ninja -C out/release nanobench blob_cache_sim out/release/nanobench -m SkDiffBench --texttraces text_blob_traces -q ``` -------------------------------- ### Interactive Bash in Binary Size Image Source: https://github.com/google/skia/blob/main/infra/docker/README.md Starts an interactive shell within the binary size analysis Docker image. Useful for inspecting the environment and installed tools. ```bash docker run -it binary-size /bin/sh ``` -------------------------------- ### Initialize WebGPU and Render Triangle Source: https://github.com/google/skia/blob/main/demos.skia.org/demos/webgpu/index.html Initializes WebGPU, requests an adapter and device, configures the canvas context, creates a render pipeline with vertex and fragment shaders, and sets up a render loop to draw a triangle. ```javascript async function WebGPUDemo() { // Adapted from https://github.com/austinEng/webgpu-samples/blob/main/src/sample/helloTriangle/main.ts const adapter = await navigator.gpu.requestAdapter(); if (!adapter) { log("Could not load an adapter. For Chrome, try running with --enable-features=Vulkan --enable-unsafe-webgpu"); return; } const device = await adapter.requestDevice(); console.log(adapter, device); const canvas = document.getElementById("draw"); const context = canvas.getContext('webgpu'); if (!context) { log("Could not load webgpu context"); return; } console.log(context); const devicePixelRatio = window.devicePixelRatio || 1; const presentationSize = [ canvas.clientWidth * devicePixelRatio, canvas.clientHeight * devicePixelRatio, ]; const presentationFormat = context.getPreferredFormat(adapter); context.configure({ device, format: presentationFormat, size: presentationSize, }); const triangleVertWGSL = `[[stage(vertex)]] fn main([[builtin(vertex_index)]] VertexIndex : u32) -> [[builtin(position)]] vec4 { var pos = array, 3>( vec2(0.0, 0.5), vec2(-0.5, -0.5), vec2(0.5, -0.5) ); return vec4(pos[VertexIndex], 0.0, 1.0); } `; const redFragWGSL = `[[stage(fragment)]] fn main() -> [[location(0)]] vec4 { return vec4(1.0, 0.0, 0.0, 1.0); } `; const pipeline = device.createRenderPipeline({ vertex: { module: device.createShaderModule({ code: triangleVertWGSL, }), entryPoint: 'main', }, fragment: { module: device.createShaderModule({ code: redFragWGSL, }), entryPoint: 'main', targets: [ { format: presentationFormat, }, ], }, primitive: { topology: 'triangle-list', }, }); console.log(pipeline); const startTime = Date.now(); function frame() { const now = Date.now(); const commandEncoder = device.createCommandEncoder(); const textureView = context.getCurrentTexture().createView(); const renderPassDescriptor = { colorAttachments: [ { view: textureView, loadValue: { r: Math.abs(Math.sin((startTime - now) / 500)), g: Math.abs(Math.sin((startTime - now) / 600)), b: Math.abs(Math.sin((startTime - now) / 700)), a: 1.0 }, storeOp: 'store', }, ], }; const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); passEncoder.setPipeline(pipeline); passEncoder.draw(3, 1, 0, 0); passEncoder.endPass(); device.queue.submit([commandEncoder.finish()]); requestAnimationFrame(frame); } requestAnimationFrame(frame); } ``` -------------------------------- ### Initialize CanvasKit and Load Resources Source: https://github.com/google/skia/blob/main/modules/canvaskit/npm_build/extra.html Initializes CanvasKit and fetches necessary external resources like JSON data, fonts, and images. This setup is required for examples that depend on these assets. ```javascript var CanvasKit = null; var cdn = 'https://cdn.skia.org/misc/'; const ckLoaded = CanvasKitInit({locateFile: (file) => '/build/'+file}); const loadLegoJSON = fetch(cdn + 'lego_loader.json').then((response) => response.text()); const loadDrinksJSON = fetch(cdn + 'drinks.json').then((response) => response.text()); const loadConfettiJSON = fetch(cdn + 'confetti.json').then((response) => response.text()); const loadOnboardingJSON = fetch(cdn + 'onboarding.json').then((response) => response.text()); const loadMultiframeJSON = fetch(cdn + 'skottie_sample_multiframe.json').then((response) => response.text()); const loadFlightGif = fetch(cdn + 'flightAnim.gif').then((response) => response.arrayBuffer()); const loadFont = fetch(cdn + 'Roboto-Regular.ttf').then((response) => response.arrayBuffer()); const loadDog = fetch(cdn + 'dog.jpg').then((response) => response.arrayBuffer()); const loadMandrill = fetch(cdn + 'mandrill_256.png').then((response) => response.arrayBuffer()); const loadBrickTex = fetch(cdn + 'brickwork-texture.jpg').then((response) => response.arrayBuffer()); const loadBrickBump = fetch(cdn + 'brickwork_normal-map.jpg').then((response) => response.arrayBuffer()); ``` -------------------------------- ### Interactive Bash in CMake Release Image Source: https://github.com/google/skia/blob/main/infra/docker/README.md Starts an interactive bash shell within the CMake release Docker image. Useful for exploring the environment and checking installed tools. ```bash docker run -it cmake-release /bin/bash ``` -------------------------------- ### Initialize RenderEngine Capture Source: https://github.com/google/skia/blob/main/site/docs/dev/tools/android-capture.md Run this command once before capturing to set up RenderEngine for debugging. ```bash frameworks/native/libs/renderengine/skia/debug/record.sh rootandsetup ``` -------------------------------- ### Precompilation Context API Update Source: https://github.com/google/skia/blob/main/RELEASE_NOTES.md Demonstrates a threading model for Skia's precompilation process using the new PrecompileContext API. This example outlines a setup with dedicated threads for recording creation, precompilation, and main thread operations. ```cpp bool Precompile(PrecompileContext*, ...) ``` -------------------------------- ### Set up Android SDK Command Line Tools Source: https://github.com/google/skia/blob/main/site/docs/user/sample/viewer.md Installs and configures the Android SDK command line tools, including setting the ANDROID_HOME environment variable. This is a prerequisite for building the Skia Viewer on Android. ```bash mkdir ~/android-sdk cd ~/android-sdk unzip ~/Downloads/commandlinetools-*.zip yes | cmdline-tools/bin/sdkmanager --licenses --sdk_root=. export ANDROID_HOME=~/android-sdk # Or wherever you installed the Android SDK. ``` -------------------------------- ### Install libimobiledevice Tools with Brew Source: https://github.com/google/skia/blob/main/site/docs/dev/testing/ios.md Use Homebrew to install libimobiledevice and related tools required for iOS development and testing. Ensure you have caskroom/cask and osxfuse installed. ```bash brew install libimobiledevice brew install ideviceinstaller brew install caskroom/cask/brew-cask brew install Caskroom/cask/osxfuse brew install ifuse ``` -------------------------------- ### Build Skia with Ninja Source: https://github.com/google/skia/blob/main/site/docs/dev/chrome/repo.md After setting up Skia and its dependencies, use Ninja to build Skia, for example, to build the 'dm' tool. ```bash ninja -C out/Debug dm ``` -------------------------------- ### Install Python Package for Mesa Build Source: https://github.com/google/skia/blob/main/infra/bots/assets/mesa_intel_driver_linux/README.md Installs the 'mako' Python package, which is a dependency for building the Mesa driver. ```bash sudo pip install mako ``` -------------------------------- ### Build Skia Viewer on Desktop Source: https://github.com/google/skia/blob/main/site/docs/user/sample/viewer.md Build the Skia Viewer using the GN build process. Ensure you have a ninja out directory configured. ```bash bin/gn gen out/Release --args='is_debug=false' ninja -C out/Release viewer ``` -------------------------------- ### Initialize and Use TSKit Source: https://github.com/google/skia/blob/main/experimental/tskit/npm_build/example.html Demonstrates initializing TSKit, calling basic functions, creating and manipulating objects, and checking for extensions. Ensure TSKit is correctly initialized before use. ```typescript async function run() { const tsKit = InitTSKit({locateFile: (file) => '/npm_build/bin/' + file}); const TSK = await tsKit; TSK.sayHello(8, 4); TSK.publicFunction("vanilla"); const sm = new TSK.Something("sentinel"); sm.setName("double_vision"); console.log(sm.getName()); sm.delete(); if (TSK.publicExtension) { console.log("extension", TSK.publicExtension([0, 0, 10, 10, 10, 10, 20, 20])); TSK.withObject({alpha: 7, beta: "foo"}); } else { console.log("no extension") } } run(); ``` -------------------------------- ### Install Doxygen on Linux Source: https://github.com/google/skia/blob/main/tools/doxygen/README.md Use the system's package manager to install the Doxygen tool on a Linux desktop environment. ```bash sudo apt install doxygen ``` -------------------------------- ### Prerequisites for SKP Capture Source: https://github.com/google/skia/blob/main/site/docs/dev/tools/android-capture.md Run these commands to enable file system write access for the recording process on a rooted device. ```bash adb root adb remount ``` -------------------------------- ### Run CanvasKit Examples Source: https://github.com/google/skia/blob/main/modules/canvaskit/npm_build/extra.html Executes CanvasKit examples that only require CanvasKit itself, such as RTShader, ColorSupport, and SkpExample. These are run after CanvasKit is loaded. ```javascript // Examples which only require canvaskit ckLoaded.then((CK) => { CanvasKit = CK; RTShaderAPI1(CanvasKit); ColorSupport(CanvasKit); SkpExample(CanvasKit); }); ``` -------------------------------- ### Run Skia Viewer with Resource Path Source: https://github.com/google/skia/blob/main/site/docs/user/sample/viewer.md Launch the Skia Viewer on desktop and specify the path to load resources. This is useful for displaying custom content. ```bash /out/Release/viewer --resourcePath /resources ``` -------------------------------- ### test_exceptions for flavor example Source: https://github.com/google/skia/blob/main/infra/bots/README.recipes.md A test function within the 'flavor' recipe module example, likely demonstrating exception handling. ```python def test_exceptions(api): pass ``` -------------------------------- ### DM Tool Help and Basic Usage Source: https://github.com/google/skia/blob/main/site/docs/dev/testing/testing.md Prints all available flags for the DM tool, including their defaults and a brief explanation. Also shows how to run only unit tests. ```bash out/Debug/dm --help # Print all flags, their defaults, and a brief explanation of each. out/Debug/dm --src tests # Run only unit tests. ``` -------------------------------- ### Install gperftools on Debian/Ubuntu Source: https://github.com/google/skia/blob/main/site/docs/dev/testing/profiling.md Installs the gperftool headers for compiling and the shared libraries for linking, including libprofiler.so (for CPU) and libtcmalloc.so (for Heap). ```bash # On Debian/Ubuntu: $ sudo apt-get install libgoogle-perftools-dev ``` -------------------------------- ### Create and Upload GPU Assets Source: https://github.com/google/skia/blob/main/infra/bots/assets/chromebook_x86_64_gles/README.md Use this script to bundle GL packages and unzipped libraries for x86_64 Chromebooks. Ensure the lib_path points to the extracted /usr/lib64 folder. ```bash ./infra/bots/assets/chromebook_x86_64_gles/create_and_upload.py --lib_path [dir] ``` -------------------------------- ### Skottie Android App Example Source: https://github.com/google/skia/blob/main/site/docs/user/modules/skottie.md This path points to the directory containing the source code for an example Android application that utilizes Skottie. ```directory https://github.com/google/skia/tree/main/platform_tools/android/apps/skottie ``` -------------------------------- ### Create and Upload GPU Assets Source: https://github.com/google/skia/blob/main/infra/bots/assets/chromebook_arm64_gles/README.md Use this script to bundle GL packages with unzipped libraries from an ARM64 Chromebook. Ensure the necessary GL packages are installed on the target device. ```bash ./infra/bots/assets/chromebook_arm64_gles/create_and_upload.py --lib_path [dir] ``` -------------------------------- ### Page Frontmatter Example Source: https://github.com/google/skia/blob/main/site/docs/dev/tools/markdown.md Frontmatter is required for every page to provide metadata. This example shows basic title and linkTitle configuration. ```yaml --- title: 'Markdown' linkTitle: 'Markdown' --- ``` -------------------------------- ### Install Mesa Driver Dependencies on Ubuntu Source: https://github.com/google/skia/blob/main/infra/bots/assets/mesa_intel_driver_linux/README.md Installs all necessary development dependencies for building the Mesa driver on Ubuntu. Ensure you have `sudo` privileges. ```bash sudo apt-get install autoconf libtool scons flex bison llvm-dev libpthread-stubs0-dev x11proto-gl-dev libdrm-dev libdrm2 x11proto-dri2-dev x11proto-dri3-dev x11proto-present-dev libxcb1-dev libxcb-dri3-dev libxcb-present-dev libxshmfence-dev xserver-xorg-core xserver-xorg-dev x11proto-xext-dev libxext-dev libxdamage-dev libx11-xcb-dev libxcb-glx0-dev libxcb-dri2-0-dev libva-dev libomxil-bellagio-dev ``` -------------------------------- ### Mermaid Diagram Example Source: https://github.com/google/skia/blob/main/site/docs/dev/tools/markdown.md Shows how to embed Mermaid diagrams within Markdown files for visual representation. This example creates a simple flowchart. ```mermaid graph TD; A-->B; A-->C; B-->D; C-->D; ``` -------------------------------- ### Initialize and Render Skia Canvas Source: https://github.com/google/skia/blob/main/demos.skia.org/demos/mesh2d/index.html Sets up the Skia canvas, hides the loader, and starts the animation loop. Use this to begin rendering Skia content. ```javascript document.getElementById('loader').style.display = 'none'; switchRenderer(nativeRenderer ? nativeRenderer : ckRenderer); requestAnimationFrame(drawFrame); ``` -------------------------------- ### Download Windows Toolchain Source: https://github.com/google/skia/blob/main/site/docs/user/build.md Use the `sk.exe` script to download the Windows toolchain for Skia builds. This is particularly useful for 32-bit builds. ```bash ./bin/sk.exe asset download win_toolchain C:/toolchain ``` -------------------------------- ### DM Output Example Source: https://github.com/google/skia/blob/main/site/docs/dev/testing/testing.md Example of the detailed output generated by DM during a correctness test run. This includes task progress and resource usage. ```text Skipping nonrendering: Don't understand 'nonrendering'. Skipping angle: Don't understand 'angle'. Skipping nvprmsaa4: Could not create a surface. 492 srcs * 3 sinks + 382 tests == 1858 tasks ( 25MB 1857) 1.36ms 8888 image mandrill_132x132_12x12.astc-5-subsets ( 25MB 1856) 1.41ms 8888 image mandrill_132x132_6x6.astc-5-subsets ( 25MB 1855) 1.35ms 8888 image mandrill_132x130_6x5.astc-5-subsets ( 25MB 1854) 1.41ms 8888 image mandrill_132x130_12x10.astc-5-subsets ( 25MB 1853) 151µs 8888 image mandrill_130x132_10x6.astc-5-subsets ( 25MB 1852) 154µs 8888 image mandrill_130x130_5x5.astc-5-subsets ... ( 748MB 5) 9.43ms unit test GLInterfaceValidation ( 748MB 4) 30.3ms unit test HalfFloatTextureTest ( 748MB 3) 31.2ms unit test FloatingPointTextureTest ( 748MB 2) 32.9ms unit test DeferredCanvas_GPU ( 748MB 1) 49.4ms unit test ClipCache ( 748MB 0) 37.2ms unit test Blur ``` -------------------------------- ### Example PDF Document Structure Source: https://github.com/google/skia/blob/main/site/docs/dev/design/pdftheory.md A complete example of a PDF document structure, including catalog, pages, content streams, and cross-reference table. ```pdf %PDF-1.4 2 0 obj << /Type /Catalog /Pages 1 0 R >> endobj 3 0 obj << /Type /Page /Parent 1 0 R /Resources <> /MediaBox [0 0 612 792] /Contents 4 0 R >> endobj 4 0 obj <> stream endstream endobj 1 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj xref 0 5 0000000000 65535 f 0000000236 00000 n 0000000009 00000 n 0000000062 00000 n 0000000190 00000 n trailer <> startxref 299 %%EOF ``` -------------------------------- ### Build and Run Skia Editor Source: https://github.com/google/skia/blob/main/modules/skplaintexteditor/README.md Instructions to build the Skia editor and run it with a text file. Ensure dependencies are synced and the build system is configured. ```bash tools/git-sync-deps bin/gn gen out/default ninja -C out/default editor ``` ```bash out/default/editor resources/text/english.txt ``` ```bash cat resources/text/*.txt > example.txt out/default/editor example.txt ``` -------------------------------- ### Build SkQP Executable Source: https://github.com/google/skia/blob/main/tools/skqp/README.md Build the SkQP program as a native executable for a specific architecture (e.g., arm) using Ninja. This is an alternative to building the APK. ```bash ninja -C out/skqp/arm skqp ``` -------------------------------- ### Initialize CanvasKit and Load SKP Source: https://github.com/google/skia/blob/main/tools/perf-canvaskit-puppeteer/render-skp.html This code initializes CanvasKit and fetches an SKP file. It uses Promise.all to ensure both are loaded before proceeding. Ensure CanvasKit is available at the specified path. ```javascript const WIDTH = 1000; const HEIGHT = 1000; const WARM_UP_FRAMES = 10; const MAX_FRAMES = 201; // This should be sufficient to have low noise. const SKP_PATH = '/static/test.skp'; (function() { const loadKit = CanvasKitInit({ locateFile: (file) => '/static/' + file, }); const loadSKP = fetch(SKP_PATH).then((resp) => { return resp.arrayBuffer(); }); Promise.all([loadKit, loadSKP]).then((values) => { const [CanvasKit, skpBytes] = values; const loadStart = performance.now(); const skp = CanvasKit.MakePicture(skpBytes); const loadTime = performance.now() - loadStart; window._perfData = { skp_load_ms: loadTime, }; console.log('loaded skp', skp, loadTime); if (!skp) { window._error = 'could not read skp'; return; } const urlSearchParams = new URLSearchParams(window.location.search); let glversion = 2; if (urlSearchParams.has('webgl1')) { glversion = 1; } const surface = getSurface(CanvasKit, glversion); if (!surface) { console.error('Could not make surface', window._error); return; } const canvas = surface.getCanvas(); document.getElementById('start_bench').addEventListener('click', async () => { const clearColor = CanvasKit.WHITE; function draw() { canvas.clear(clearColor); canvas.drawPicture(skp); } const results = await startTimingFrames(draw, surface, WARM_UP_FRAMES, MAX_FRAMES); Object.assign(window._perfData, results); window._perfDone = true; }); console.log('Perf is ready'); window._perfReady = true; }); } )(); ``` -------------------------------- ### Install Skia Viewer APK Source: https://github.com/google/skia/blob/main/site/docs/user/sample/viewer.md Installs the built Skia Viewer APK onto an Android device using ADB. Ensure ADB is in your PATH. ```bash adb install /viewer.apk ``` -------------------------------- ### Initialize CanvasKit and Draw Source: https://github.com/google/skia/blob/main/demos.skia.org/demos/hello_world/index.html Use this snippet to initialize CanvasKit and draw a basic "Hello World" example. It sets up a drawing surface, defines colors and fonts, and requests animation frames to render the content. Ensure CanvasKit is loaded before attempting to draw. ```javascript // Comment the following line out and the subsequent line in to use a local build of CanvasKit // const base = 'https://unpkg.com/canvaskit-wasm@0.25.0/bin/full/'; const base = '/build/'; const ckLoaded = CanvasKitInit({ locateFile: (file) => base + file }); ckLoaded.then((CanvasKit) => { const surface = CanvasKit.MakeCanvasSurface('draw'); if (!surface) { throw 'Could not make surface'; } const paint = new CanvasKit.Paint(); paint.setColor(CanvasKit.RED); const textPaint = new CanvasKit.Paint(); const textFont = new CanvasKit.Font(CanvasKit.Typeface.GetDefault(), 20); function drawFrame(canvas) { canvas.drawRect(CanvasKit.LTRBRect(10, 10, 50, 50), paint); canvas.drawText('If you see this, CanvasKit loaded!!', 5, 100, textPaint, textFont); } surface.requestAnimationFrame(drawFrame); }); ```