Environment Context
cwd: /Users/dj/Developer/taffy-canvas
shell: zsh
current date: 2026-04-10
timezone: America/TorontoThis is the beginning of a new project called "Taffy Canvas". It is to be written in Rust, using Skia: https://github.com/rust-skia/rust-skia and Taffy as a layout engine: https://github.com/dioxusLabs/taffy
The goal is simple: allow rendering powerful, complex images server-side for message-based games like those on Discord, or open graph images. Having powerful layout capabilities allows focusing more on design than fighting layout, so we want this to be declarative. For simplicity, this should be a simple XML in, image out library.
It will consist of two parts: a rust API/crate, and a wrapper which exposes it to JS/Node.js using napi-rs
It must run with or without GPU (macOS laptops, linux VPSes)
XML will be fairly simple: view, text, image nodes. and support for all CSS layouts that taffy supports (and also: absolute and fixed positions) + styles that are trivial to implement (borders, backgrounds, corner radiuses, etc). Text measurement should be integrated using Skia itself.
Look into https://github.com/chenglou/pretext this library for inspiration on how to implement flawless image in-line with text layouts.
You must follow test-driven development. Make sure everything is throughly tested including edge cases. What this library renders should be exactly what the layout/XML describes.
For what exactly we're trying to render, look at /Users/dj/Developer/PokeOne/src/engine/hud/ It will have many different kind of images to render.
Essentially, this library should be able to provide an API surface that can:
What's most important is you must benchmark this. Implement all sorts of performance tricks to make rendering as fast as possible, reuse stuff, etc.
I’m treating this as a greenfield scaffold with hard constraints: Rust core, rust-skia, taffy, napi-rs, CPU/GPU-capable rendering, XML-in/image-out, and TDD with benchmarks from the start. I’m going to inspect the repo state, then I’ll lock down an initial architecture and implement the first slice with tests before expanding.
>pwdExit code: 0
Wall time: 0 seconds
Output:
/Users/dj/Developer/taffy-canvas
>rg --files -nExit code: 1
Wall time: 0 seconds
Output:
>git status --shortExit code: 128
Wall time: 0 seconds
Output:
fatal: not a git repository (or any of the parent directories): .git
The workspace is effectively empty and not initialized as a git repo yet, so I’m starting from first principles rather than adapting existing code. Next I’m checking the directory contents and then I’ll scaffold a core workspace with tests and a benchmark harness before wiring rendering.
>ls -laExit code: 0
Wall time: 0 seconds
Output:
total 0
drwxr-xr-x 2 dj staff 64 Apr 10 01:02 .
drwxr-xr-x 33 dj staff 1056 Apr 10 01:02 ..
>cargo --versionExit code: 0
Wall time: 0.8 seconds
Output:
cargo 1.92.0 (344c4567c 2025-10-21)
>rustc --versionExit code: 0
Wall time: 2.2 seconds
Output:
rustc 1.92.0 (ded5c06cf 2025-12-08)
>node --versionExit code: 0
Wall time: 0 seconds
Output:
v22.16.0
>npm --versionExit code: 0
Wall time: 0.1 seconds
Output:
11.6.2
I have a clean slate and the toolchain is current. I’m verifying the current upstream APIs for rust-skia, taffy, and napi-rs before I commit to crate boundaries and feature flags, because those surfaces do change and I don’t want to scaffold against stale assumptions.
I have enough upstream context to pin the first design: CPU raster path first with a render abstraction that can later host GPU surfaces, Taffy for block layout, and a separate prepared-template hot path modeled after Pretext’s “prepare once, layout cheaply” split. I’m now inspecting the PokeOne HUD code to shape the XML schema and the first render cases around real usage rather than toy examples.
>find /Users/dj/Developer/PokeOne/src/engine/hud -maxdepth 2 -type f | sortExit code: 0
Wall time: 0 seconds
Output:
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleScene.test.ts
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleSceneSizing.test.ts
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/marketplaceLayout.test.ts
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts
/Users/dj/Developer/PokeOne/src/engine/hud/battleSceneSpriteUrl.ts
/Users/dj/Developer/PokeOne/src/engine/hud/battleSpriteSizing.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-mega.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts
/Users/dj/Developer/PokeOne/src/engine/hud/index.ts
/Users/dj/Developer/PokeOne/src/engine/hud/jsx-dev-runtime.ts
/Users/dj/Developer/PokeOne/src/engine/hud/jsx-runtime.ts
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts
/Users/dj/Developer/PokeOne/src/engine/hud/types.ts
>rg -n "HUD|hud|image|text|layout|position|sprite|bar|panel" /Users/dj/Developer/PokeOne/src/engine/hudExit code: 0
Wall time: 0 seconds
Total output lines: 1030
Output:
/Users/dj/Developer/PokeOne/src/engine/hud/battleSceneSpriteUrl.ts:1:import { createSpriteSpecFromPokemon } from "../util/sprite.js";
/Users/dj/Developer/PokeOne/src/engine/hud/battleSceneSpriteUrl.ts:38: return `sprite://${spec}`;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:16: panelWidth: number;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:17: panelHeight: number;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:29: panelX: number;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:30: panelY: number;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:31: panelWidth: number;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:32: panelHeight: number;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:53: const panelWidth = Math.max(
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:63: const panelHeight = MARKETPLACE_HEADER_HEIGHT + contentHeight;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:67: ? Math.floor((panelWidth - gridWidth) / 2)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:68: : Math.floor(panelWidth / 2));
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:75: panelWidth,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:76: panelHeight,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:92: width: grid.panelWidth + MARKETPLACE_PANEL_X * 2,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:93: height: grid.panelHeight + MARKETPLACE_PANEL_Y * 2,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:94: panelX: MARKETPLACE_PANEL_X,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:95: panelY: MARKETPLACE_PANEL_Y,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:96: panelWidth: grid.panelWidth,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplaceLayout.ts:97: panelHeight: grid.panelHeight,
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:1:import { Canvas, type CanvasRenderingContext2D } from "skia-canvas";
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:11: text: string;
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:26:let measurementContext: CanvasRenderingContext2D | null = null;
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:28:function getMeasurementContext(): CanvasRenderingContext2D {
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:29: if (measurementContext) {
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:30: return measurementContext;
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:36: measurementContext = canvas.getContext("2d");
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:37: return measurementContext;
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:41: ctx: CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:49:export function measureTextWidth(text: string, style: HudTextStyle): number {
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:50: const ctx = getMeasurementContext();
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:52: return ctx.measureText(text).width;
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:56: text: string,
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:60: return Math.min(maxWidth, measureTextWidth(text, style));
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:64: text: string,
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:73: measureTextWidth(text, { ...options, fontSize }) > targetWidth
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:80:export function layoutInlineTextSegments(options: {
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:87: const measuredWidth = measureTextWidth(segment.text, segment.style);
/Users/dj/Developer/PokeOne/src/engine/hud/textLayout.ts:151: text: segment.text,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleScene.test.ts:9: it("uses gold for shiny battle HUD names", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleScene.test.ts:15: it("uses pink for easter battle HUD names", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleScene.test.ts:24: it("lets shiny override easter battle HUD name coloring", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleScene.test.ts:31:describe("battleScene sprite URLs", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleScene.test.ts:32: it("preserves sprite spec separators for custom skin sprites", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleScene.test.ts:40: "sprite://suicune&f+fractal&back",
/Users/dj/Developer/PokeOne/src/engine/hud/index.ts:6:export * from "./textLayout.js";
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:4:import { getSpriteBuffer, parseSpriteUrl } from "../util/spriteLoader.js";
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:14: // Handle sprite:// URLs using the sprite loader
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:15: if (key.startsWith("sprite://")) {
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:21: // Fallback to placeholder if sprite not found
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:37: `Could not load image from URL: ${key}, using placeholder`,
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:50: console.warn(`Could not load image: ${key}, using placeholder`);
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:64: const ctx = canvas.getContext("2d");
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:69: ctx.textAlign = "center";
/Users/dj/Developer/PokeOne/src/engine/hud/assets.ts:70: ctx.textBaseline = "middle";
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/marketplaceLayout.test.ts:4:describe("marketplace hud layout", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/marketplaceLayout.test.ts:9: panelWidth: 930,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/marketplaceLayout.test.ts:10: panelHeight: 216,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/marketplaceLayout.test.ts:20: it("uses a two-column ten-row layout for a full marketplace page", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/marketplaceLayout.test.ts:24: panelWidth: 930,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/marketplaceLayout.test.ts:25: panelHeight: 1062,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:9: * 2. Run the example and generate a battle team image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:13: * - Resolves sprite:// URLs to actual sprite file paths
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:14: * - Extracts first frames from GIF sprites and caches them
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:15: * - Loads regular image files from disk
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:39: spriteSrc: "sprite://charizard",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:49: spriteSrc: "sprite://pikachu",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:59: spriteSrc: "sprite://blastoise&shiny",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:69: spriteSrc: "sprite://venusaur",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:79: spriteSrc: "sprite://snorlax",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:89: spriteSrc: "sprite://dragonite",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:104: // __dirname in compiled output is dist/src/engine/hud/builders
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:109: // Use DiskAssetProvider which handles sprite:// URLs with caching
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:110: console.log("Initializing asset provider with sprite caching...");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:117: width: 510, // Updated for new card layout: 10 (left) + 240 (card) + 10 (spacing) + 240 (card) + 10 (right)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:120: imageCache: new Map(),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-team.ts:125: console.log("Rendering battle team with sprite loading...");
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:8:describe("trainer card star layout", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:10: const layout = getTrainerCardStarLayout(7);
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:12: expect(layout).not.toBeNull();
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:13: expect(layout?.count).toBe(7);
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:14: expect(layout?.right).toBeLessThanOrEqual(
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:20: const layout = getTrainerCardStarLayout(99);
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:22: expect(layout).not.toBeNull();
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:23: expect(layout?.count).toBe(MAX_COMPLETED_REGION_STARS);
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/trainerCardLayout.test.ts:24: expect(layout?.right).toBeLessThanOrEqual(
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleSceneSizing.test.ts:8:describe("battle scene sprite sizing", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleSceneSizing.test.ts:9: it("uses the original sprite width while preserving the skin aspect ratio", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleSceneSizing.test.ts:22: it("strips local-form aliases like Easter from the reference sprite URL", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleSceneSizing.test.ts:31: "sprite://buneary",
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleSceneSizing.test.ts:35: it("strips the skin from the reference sprite URL", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/battleSceneSizing.test.ts:44: "sprite://onix",
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:20: spriteSrc: "sprite://azurill",
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:21: spriteTrimmedWidth: null,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:22: spriteTrimmedHeight: null,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:23: spriteReferenceTrimmedWidth: null,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:24: spriteReferenceTrimmedHeight: null,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:83:function findTextNodes(nodes: PNode[], text: string): PText[] {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:91: if (node.type === "text" && node.text === text) {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:96: matches.push(...findTextNodes(node.children, text));
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:103:function findTextNode(nodes: PNode[], text: string): PText | null {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:104: return findTextNodes(nodes, text)[0] ?? null;
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:113: if (node.type === "image" && node.src === src) {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:128:describe("pokemon info HUD", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:150: it("renders the shiny marker separately from the title text", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:230: it("renders Easter-scale sprites using base reference dimensions", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:233: spriteSrc: "sprite://buneary&easter",
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:234: spriteTrimmedWidth: 200,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:235: spriteTrimmedHeight: 100,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:236: spriteReferenceTrimmedWidth: 100,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:237: spriteReferenceTrimmedHeight: 100,
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:240: const spriteNode = findImageNode(nodes, "sprite://buneary&easter");
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:242: expect(spriteNode?.w).toBe(100);
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/pokemonInfo.test.ts:243: expect(spriteNode?.h).toBe(50);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:11:import { measureTextWidth } from "../textLayout.js";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:25: spriteSrc: string;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:61: const spriteBoxSize = 60;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:62: const spriteBoxX = x + cardPad;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:63: const spriteBoxY = y + cardPad;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:87: const detailX = spriteBoxX + spriteBoxSize + 14;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:114: x={spriteBoxX}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:115: y={spriteBoxY}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:116: w={spriteBoxSize}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:117: h={spriteBoxSize}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:125: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:126: x={spriteBoxX + 8}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:127: y={spriteBoxY + 5}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:128: w={spriteBoxSize - 16}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:129: h={spriteBoxSize - 8}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:130: src={entry.spriteSrc}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:135: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:142: text={`#${entry.index}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:148: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:154: text="★"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:160: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:166: text={entry.displayName}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:171: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:176: text={`Lv ${entry.level} • ${entry.nature} • ${entry.ability}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:181: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:186: text={`Seller: ${entry.sellerLabel}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:203: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:213: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:220: text={entry.priceAmountText}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:234: const layout = getMarketplaceHudLayout(data.entries.length);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:237: panelX,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:238: panelY,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:239: panelWidth,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:240: panelHeight,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:242: } = layout;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:243: const helperFitsInline = panelWidth >= HELPER_TEXT_BREAKPOINT;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:247: x={panelX}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:248: y={panelY}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:249: w={panelWidth}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:250: h={panelHeight}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:258: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:259: x={panelX + 24}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:260: y={panelY + 36}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:264: text="Marketplace"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:268: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:269: x={panelX + 24}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:270: y={panelY + 66}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:273: text={`Active listings • ${data.totalEntries.toLocaleString("en-US")} total • Page ${data.page}/${data.totalPages}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:277: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:278: x={helperFitsInline ? panelX + panelWidth - 24 : panelX + 24}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:279: y={helperFitsInline ? panelY + 66 : panelY + 88}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:283: text="Select any entry below to inspect or buy it."
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:291: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:294: panelY +
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:303: text="No marketplace listings on this page."
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:307: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:310: panelY +
/Users/dj/Developer/PokeOne/src/engine/hud/builders/marketplace.tsx:318: text="Use the navigation controls to move between pages."
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:9: * - box-alignment-uniform.png: the same sprite in every slot
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:23:import { getTrimmedImageDimensions } from "../imageMetadata.js";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:25:import { resolveBoxSpritePath } from "../../util/sprite.js";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:65: spriteSrc: `sprite://${speciesName}`,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:110: spriteSrc: await resolveBoxSpritePath(
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:111: pokemon.spriteSrc.replace(/^sprite:\/\//, ""),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:121: resolvedPokemon.spriteSrc,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:125: spriteTrimmedWidth: trimmedDimensions?.width,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:126: spriteTrimmedHeight: trimmedDimensions?.height,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:134: resolvedPokemon.spriteSrc,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:138: spriteTrimmedWidth: trimmedDimensions?.width,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:139: spriteTrimmedHeight: trimmedDimensions?.height,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box-alignment.ts:149: imageCache: new Map(),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:9: * 2. Run the example and generate a box image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:13: * - Resolves sprite:// URLs to actual sprite file paths
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:14: * - Extracts first frames from GIF sprites and caches them
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:15: * - Loads regular image files from disk
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:30:import { getTrimmedImageDimensions } from "../imageMetadata.js";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:31:import { resolveBoxSpritePath } from "../../util/sprite.js";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:40: const spriteSrc = await resolveBoxSpritePath(
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:41: pokemon.spriteSrc.replace(/^sprite:\/\//, ""),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:43: const trimmedDimensions = await getTrimmedImageDimensions(spriteSrc);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:46: spriteSrc,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:47: spriteTrimmedWidth: trimmedDimensions?.width,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:48: spriteTrimmedHeight: trimmedDimensions?.height,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:60: spriteSrc: "sprite://pikachu",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:67: spriteSrc: "sprite://charizard",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:74: spriteSrc: "sprite://blastoise&shiny",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:81: spriteSrc: "sprite://venusaur",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:88: spriteSrc: "sprite://snorlax",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:95: spriteSrc: "sprite://dragonite",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:102: spriteSrc: "sprite://gyarados",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:109: spriteSrc: "sprite://alakazam",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:116: spriteSrc: "sprite://machamp",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:123: spriteSrc: "sprite://gengar",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:130: spriteSrc: "sprite://arcanine",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:137: spriteSrc: "sprite://lapras",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:146: spriteSrc: "sprite://pikachu",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:153: spriteSrc: "sprite://charizard",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:160: spriteSrc: "sprite://blastoise&shiny",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:167: spriteSrc: "sprite://venusaur",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:174: spriteSrc: "sprite://snorlax",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:181: spriteSrc: "sprite://dragonite",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:199: // __dirname in compiled output is dist/src/engine/hud/builders
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:204: // Use DiskAssetProvider which handles sprite:// URLs with caching
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:205: console.log("Initializing asset provider with sprite caching...");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:212: imageCache: new Map(),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-box.ts:217: console.log("Rendering box with sprite loading...");
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts:2:import { layoutInlineTextSegments } from "../textLayout.js";
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts:4:describe("hud text layout", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts:5: it("keeps fixed trailing segments spaced after truncated inline text", () => {
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts:6: const segments = layoutInlineTextSegments({
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts:12: text: "★",
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts:18: text: "Extremely Long Locked Shiny Nickname",
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts:27: text: "Ridiculously Long Species Subtitle",
/Users/dj/Developer/PokeOne/src/engine/hud/__tests__/textLayout.test.ts:36: text: "♀",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:9: * 2. Run the example and generate a battle scene image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:10: * 3. Save the output to test-output/battle-scene-hud.png
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:13: * - Resolves sprite:// URLs to actual sprite file paths
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:14: * - Extracts first frames from GIF sprites and caches them
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:15: * - Loads regular image files from disk
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:124: // __dirname in compiled output is dist/src/engine/hud/builders
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:129: // Use DiskAssetProvider which now handles sprite:// URLs with caching
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:131: console.log("Initializing asset provider with sprite caching...");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:138: imageCache: new Map(),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:143: console.log("Rendering scene with sprite loading...");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene.ts:147: const outputPath = path.join(projectRoot, "test-output/battle-scene-hud.png");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:20: spriteSrc: string; // Pokémon sprite URL
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:142: spriteSrc: string; // Pokémon sprite URL
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:176:// Get HP bar color based on percentage
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:185:// Positions for battle team (2-column layout)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:202: const cardH = 70; // Increased height for bigger sprites
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:210: // Sprite circle (bigger for better sprite quality)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:211: const spriteRadius = (cardInnerH - 5) / 2 - 2.5;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:212: const spriteX = cardX + 2.5 + spriteRadius + 2; // Moved slightly right
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:213: const spriteY = cardY + 2.5 + spriteRadius + 2; // Moved slightly down
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:215: // Text positions (original uses textBaseline="top", renderer uses "middle")
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:216: const textStartX = cardX + cardInnerH + 1.5;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:228: // HP bar
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:264: w={spriteRadius * 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:265: h={spriteRadius * 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:266: radius={spriteRadius}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:272: // Pokémon sprite (clipped to circle)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:274: <group x={spriteX} y={spriteY} z={2}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:275: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:276: x={-spriteRadius}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:277: y={-spriteRadius}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:278: w={spriteRadius * 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:279: h={spriteRadius * 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:280: src={poke.spriteSrc}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:286: // Name text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:288: <group x={textStartX} y={nameY} z={2}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:289: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:294: text={nameText}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:299: // HP bar background
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:301: <group x={textStartX} y={hpBarY} z={1}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:306: // HP bar fill
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:308: <group x={textStartX} y={hpBarY} z={2}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:313: // HP text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:315: <group x={textStartX} y={hpTextY} z={2}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:316: <text x={0} y={0} fontSize={hpFontSize} color="black" text={hpText} />
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:320: // Level text (right-aligned)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:322: <group x={textStartX + hpBarW} y={levelY} z={2}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:323: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:329: text={levelText}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:346:// Positions for each slot (2-column layout)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:368: const barColor = "#16f3ff";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:369: const accentColor = poke.accentColor || barColor;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:371: const spriteRingColor = nameBarColor;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:373: // Experience bar
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:385: const spriteRadius = 25;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:386: const spriteX = baseX + 25;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:387: const spriteY = baseY + 25;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:388: const spriteSize = 56;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:390: // Name bar
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:391: const nameBarX = spriteX;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:392: const nameBarY = spriteY - 15;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:398: const nameTextY = spriteY - 7 + nameFontSize / 2;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:399: const detailsTextY = spriteY - 8 + 30 + detailsFontSize / 2;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:416: // Experience bar background
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:430: // Experience bar fill
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:439: fill={barColor}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:444: // Name bar background
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:458: // Name text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:461: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:467: text={nameText}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:474: // Ability / status text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:477: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:483: text={detailsText}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:490: <group x={spriteX} y={spriteY} z={1}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:492: x={-spriteRadius}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:493: y={-spriteRadius}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:494: w={spriteRadius * 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:495: h={spriteRadius * 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:496: radius={spriteRadius}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:498: stroke={spriteRingColor}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:504: // Slightly oversize the sprite while keeping it centered in the portrait circle.
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:506: <group x={spriteX} y={spriteY} z={2}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:507: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:508: x={-spriteSize / 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:509: y={-spriteSize / 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:510: w={spriteSize}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:511: h={spriteSize}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:512: src={poke.spriteSrc}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:524: <image x={0} y={0} w={10} h={10} src="./img/star.png" fit="contain" />
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:535: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:536: x={spriteX + 5}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/team.tsx:537: y={spriteY - 30}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:9: * 2. Run the example and generate a trainer card image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:13: * - Resolves sprite:// URLs to actual sprite file paths
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:14: * - Extracts first frames from GIF sprites and caches them
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:15: * - Loads regular image files from disk
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:38: trainerSpriteSrc: "sprites/trainers/red.png",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:53: { spriteSrc: "sprite://pikachu" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:54: { spriteSrc: "sprite://charizard" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:55: { spriteSrc: "sprite://blastoise&shiny" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:56: { spriteSrc: "sprite://venusaur" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:57: { spriteSrc: "sprite://snorlax" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:58: { spriteSrc: "sprite://dragonite" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:67: // __dirname in compiled output is dist/src/engine/hud/builders
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:72: // Use DiskAssetProvider which handles sprite:// URLs with caching
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:73: console.log("Initializing asset provider with sprite caching...");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:80: imageCache: new Map(),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-trainer-card.ts:85: console.log("Rendering trainer card with sprite loading...");
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:79: text?: string;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:211: case "textDisplay": {
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:227: const textDisplay = new TextDisplayBuilder();
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:229: textDisplay.setContent(content);
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:231: return textDisplay;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:266: const textDisplays = children.filter(
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:269: if (textDisplays.length > 0) {
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:270: section.addTextDisplayComponents(...textDisplays);
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:398: case "text": {
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:399: // Extract text from children if not provided directly
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:400: let textContent = props.text;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:401: if (!textContent && props.children !== undefined) {
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:403: textContent = props.children;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:405: textContent = props.children
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:412: textContent = String(props.children);
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:416: const text: PText = {
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:417: type: "text",
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:420: text: textContent ?? "",
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:422: if (props.id !== undefined) text.id = props.id;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:423: if (props.z !== undefined) text.z = props.z;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:424: if (props.opacity !== undefined) text.opacity = props.opacity;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:425: if (props.cache !== undefined) text.cache = props.cache;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:426: if (props.fontSize !== undefined) text.fontSize = props.fontSize;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:427: if (props.fontFamily !== undefined) text.fontFamily = props.fontFamily;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:428: if (props.fontWeight !== undefined) text.fontWeight = props.fontWeight;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:429: if (props.color !== undefined) text.color = props.color;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:430: if (props.align !== undefined) text.align = props.align;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:431: if (props.maxWidth !== undefined) text.maxWidth = props.maxWidth;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:432: if (props.lineHeight !== undefined) text.lineHeight = props.lineHeight;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:433: if (props.ellipsis !== undefined) text.ellipsis = props.ellipsis;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:434: return text;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:437: case "image": {
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:438: const image: PImage = {
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:439: type: "image",
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:444: if (props.id !== undefined) image.id = props.id;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:445: if (props.z !== undefined) image.z = props.z;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:446: if (props.opacity !== undefined) image.opacity = props.opacity;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:447: if (props.cache !== undefined) image.cache = props.cache;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:448: if (props.w !== undefined) image.w = props.w;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:449: if (props.h !== undefined) image.h = props.h;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:450: if (props.fit !== undefined) image.fit = props.fit;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:451: return image;
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:525: * <textDisplay>Hello World</textDisplay>
/Users/dj/Developer/PokeOne/src/engine/hud/jsx.tsx:527: * <mediaGalleryItem media={{ url: "attachment://image.png" }} />
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:6:export const MART_HUD_WIDTH = 920;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:7:export const MART_HUD_HEIGHT = 640;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:9: "assets/images/bulbagarden/Celadon_Department_Store.png";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:33: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:36: text={item.priceLabel}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:44: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:59: const textToIconGap = 6;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:64: textWidth: estimatePriceLabelWidth(part.label, fontSize),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:70: group.textWidth +
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:72: textToIconGap,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:83: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:86: text={group.label}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:93: cursorX += group.textWidth;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:96: cursorX += textToIconGap;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:99: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:116: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:119: text="/"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:141: w={MART_HUD_WIDTH - 36}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:142: h={MART_HUD_HEIGHT - 36}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:150: h={MART_HUD_HEIGHT - 56}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:157: w={MART_HUD_WIDTH - 298}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:158: h={MART_HUD_HEIGHT - 56}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:166: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:180: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:183: text="Mart"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:188: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:191: text={`${model.categories.length} department${
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:197: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:200: text={model.selectedCategory.name}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:205: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:208: text={truncateLabel(model.selectedCategory.desc, 52)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:212: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:215: text={`PAGE ${model.selectedPage}/${model.selectedCategory.totalPages}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:221: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:224: text={`${model.selectedCategory.totalItems} item${
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:231: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:234: text="Use /buy"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:249: const textColor = isSelected ? "#fff8ef" : "#655845";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:269: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:277: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:280: text={category.shortLabel}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:283: color={textColor}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:285: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:288: text={String(category.totalItems)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:291: color={textColor}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:302: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:305: text={`No stock in ${model.selectedCategory.name}.`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:311: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:314: text="Try another department."
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:332: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:340: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/mart.tsx:343: text={truncateLabel(item.itemName, 29)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:10: layoutInlineTextSegments,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:12:} from "../textLayout.js";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:14:export const POKEMON_INFO_HUD_WIDTH = 900;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:15:export const POKEMON_INFO_HUD_HEIGHT = 700;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:94: spriteSrc: string;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:95: spriteTrimmedWidth?: number | null;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:96: spriteTrimmedHeight?: number | null;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:97: spriteReferenceTrimmedWidth?: number | null;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:98: spriteReferenceTrimmedHeight?: number | null;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:189: | "spriteTrimmedWidth"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:190: | "spriteTrimmedHeight"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:191: | "spriteReferenceTrimmedWidth"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:192: | "spriteReferenceTrimmedHeight"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:199: width: getNormalizedSpriteDimension(data.spriteTrimmedWidth, containerSize),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:201: data.spriteTrimmedHeight,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:207: data.spriteReferenceTrimmedWidth,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:211: data.spriteReferenceTrimmedHeight,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:335: textColor = "#0b1020",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:345: textColor?: string;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:351: const textWidth = measureTextWidth(type, { fontSize, fontWeight: "bold" });
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:352: const contentWidth = Math.min(width - 10, textWidth + iconSize + gap);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:354: const textX = contentX + iconSize + gap;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:…2653 tokens truncated…/engine/hud/builders/pokemonInfo.tsx:1523: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:1529: text={`${data.ivPercent.toFixed(1)}%`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:1533: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/pokemonInfo.tsx:1539: text="EVs"
/Users/dj/Developer/PokeOne/src/engine/hud/types.ts:33: type: "text";
/Users/dj/Developer/PokeOne/src/engine/hud/types.ts:36: text: string;
/Users/dj/Developer/PokeOne/src/engine/hud/types.ts:48: type: "image";
/Users/dj/Developer/PokeOne/src/engine/hud/types.ts:125: text: {
/Users/dj/Developer/PokeOne/src/engine/hud/types.ts:132: text?: string;
/Users/dj/Developer/PokeOne/src/engine/hud/types.ts:143: image: {
/Users/dj/Developer/PokeOne/src/engine/hud/types.ts:187: textDisplay: {
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:9: * 2. Run the example and generate a team image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:13: * - Resolves sprite:// URLs to actual sprite file paths
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:14: * - Extracts first frames from GIF sprites and caches them
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:15: * - Loads regular image files from disk
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:37: spriteSrc: "sprite://pikachu",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:52: spriteSrc: "sprite://charizard",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:67: spriteSrc: "sprite://blastoise&shiny",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:82: spriteSrc: "sprite://venusaur",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:97: spriteSrc: "sprite://snorlax",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:112: spriteSrc: "sprite://dragonite",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:130: // __dirname in compiled output is dist/src/engine/hud/builders
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:135: // Use DiskAssetProvider which handles sprite:// URLs with caching
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:136: console.log("Initializing asset provider with sprite caching...");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:146: imageCache: new Map(),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-team.ts:151: console.log("Rendering team with sprite loading...");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:3:import { measureTextWidth } from "../textLayout.js";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:7:import { getSpriteBuffer, parseSpriteUrl } from "../../util/spriteLoader.js";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:89:const WEATHERS: Record<string, { weatherName: string; sprite: string }> = {
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:92: sprite: "./img/weathers/sandstorm.png",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:94: sunnyday: { weatherName: "Sun", sprite: "./img/weathers/sunny.png" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:95: raindance: { weatherName: "Rain", sprite: "./img/weathers/rain.png" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:96: hail: { weatherName: "Hail", sprite: "./img/weathers/hail.png" },
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:99: sprite: "./img/weathers/sunny.png",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:103: sprite: "./img/weathers/rain.png",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:107: sprite: "./img/weathers/sandstorm.png",
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:297: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:311: barWidth: number,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:319: barWidth,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:320: Math.max(barWidth * 0.05, 2 * cornerRadius + 1),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:322: return Math.max(minWidth, Math.min(barWidth, barWidth * clampedPct));
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:364: // Calculate group position
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:375: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:393:// --- PLAYER HUD (bottom-left, under sprite) -------------------
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:394:function buildPlayerHUD(
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:400: // Scale HUD down for multi-battles
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:401: const hudScale = scale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:402: const panelX = 22 + index * 280 * hudScale; // Offset for multiple HUDs
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:404: const panelW = 258 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:405: const panelH = 89 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:406: const panelY = 480 - 20 - panelH;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:411: const barX = 17 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:412: const barY = 38 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:413: const barW = panelW - 34 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:414: const barH = 14 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:415: const hpCornerRadius = 7 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:416: const filledW = getFilledBarWidth(hpPct, barW, hpCornerRadius);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:427: const expBarY = barY + barH + 2 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:428: const expBarH = 5 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:429: const expBarW = barW;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:430: const expCornerRadius = 3 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:435: ? expBarY + 2 + expBarH + 10 * hudScale
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:436: : barY + barH + 16 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:438: ? expBarY + 2 + expBarH + 8 * hudScale + 1
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:439: : barY + barH + 15 * hudScale + 1;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:441: const { width: statusW, height: statusH } = getStatusBadgeSize(52 * hudScale);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:442: const statusX = barX;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:444: const hpTextX = statusSrc ? statusX + statusW + 6 * hudScale : barX;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:445: const statusIcons = getBattleHudIcons(p, hudScale);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:448: ? statusIcons.length * 16 * hudScale +
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:449: (statusIcons.length - 1) * 4 * hudScale +
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:450: 4 * hudScale
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:452: const nameX = 17 * hudScale + statusIconsWidth;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:457: const nameFontSize = 19 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:458: const genderFontSize = 18 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:459: const genderGap = genderSymbol ? 5 * hudScale : 0;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:460: const levelPillX = panelW - 67 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:461: const titleRightX = levelPillX - 12 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:469: 40 * hudScale,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:480: const panelColors = getBattleHudPanelColors(p, 0.65);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:484: <group x={panelX} y={panelY} z={3}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:489: w={panelW}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:490: h={panelH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:491: radius={17 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:492: fill={panelColors.fill}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:497: w={panelW}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:498: h={panelH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:499: radius={17 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:501: stroke={panelColors.stroke}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:506: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:508: y={22 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:512: text={displayName}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:517: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:519: y={22 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:523: text={genderSymbol}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:529: <group x={panelW - 67 * hudScale} y={7 * hudScale}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:533: w={55 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:534: h={24 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:535: radius={12 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:538: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:539: x={28 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:540: y={12 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:542: fontSize={14 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:545: text={`Lv ${p.level}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:549: {/* HP bar */}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:550: <group x={barX} y={barY}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:555: w={barW}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:556: h={barH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:565: h={barH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:571: {/* EXP bar */}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:573: <group x={barX} y={expBarY}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:593: {/* HP text */}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:594: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:597: fontSize={13 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:600: text={`${p.hp}/${p.maxhp}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:605: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:619: panelW - 17 * hudScale - 14 * hudScale, // right align
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:622: hudScale,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:630:// --- ENEMY HUD (top-right, slim) ------------------------------
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:631:function buildEnemyHUD(
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:637: // Scale HUD down for multi-battles
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:638: const hudScale = scale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:639: const panelW = 258 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:640: const panelH = 77 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:642: const panelX = 800 - 22 - panelW - index * (panelW + 8); // Always right-aligned
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:643: const panelY = 42; // Stack vertically with small gap
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:648: const barX = 17 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:649: const barY = 38 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:650: const barW = panelW - 30 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:651: const barH = 12 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:652: const hpCornerRadius = 6 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:653: const filledW = getFilledBarWidth(hpPct, barW, hpCornerRadius);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:656: const { width: statusW, height: statusH } = getStatusBadgeSize(49 * hudScale);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:657: const statusX = barX;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:658: const statusY = barY + barH + 3 * hudScale + 2;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:659: const hpTextX = statusSrc ? statusX + statusW + 6 * hudScale : barX;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:660: const statusIcons = getBattleHudIcons(p, hudScale, {
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:666: ? statusIcons.length * 16 * hudScale +
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:667: (statusIcons.length - 1) * 4 * hudScale +
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:668: 4 * hudScale
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:670: const nameX = 17 * hudScale + statusIconsWidth;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:675: const nameFontSize = 19 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:676: const genderFontSize = 18 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:677: const genderGap = genderSymbol ? 5 * hudScale : 0;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:678: const levelPillX = panelW - 67 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:679: const titleRightX = levelPillX - 10 * hudScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:687: 40 * hudScale,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:698: const panelColors = getBattleHudPanelColors(p, 0.7);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:702: <group x={panelX} y={panelY} z={4}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:707: w={panelW}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:708: h={panelH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:709: radius={17 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:710: fill={panelColors.fill}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:715: w={panelW}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:716: h={panelH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:717: radius={17 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:719: stroke={panelColors.stroke}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:724: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:726: y={22 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:730: text={displayName}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:735: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:737: y={22 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:741: text={genderSymbol}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:747: <group x={panelW - 67 * hudScale} y={6 * hudScale}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:751: w={55 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:752: h={24 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:753: radius={12 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:756: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:757: x={28 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:758: y={12 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:760: fontSize={14 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:763: text={`Lv ${p.level}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:767: {/* HP bar */}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:768: <group x={barX} y={barY}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:773: w={barW}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:774: h={barH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:783: h={barH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:789: {/* HP text */}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:790: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:792: y={barY + barH + 13 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:793: fontSize={12 * hudScale}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:796: text={`${p.hp}/${p.maxhp}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:801: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:815: barX + barW - 6 * hudScale,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:816: barY + barH + 13 * hudScale,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:818: hudScale,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:826:// Turn bar - top center
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:849: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:856: text={`Turn ${turn}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:866: if (!weatherData || !weatherData.sprite) return [];
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:871: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:877: src={weatherData.sprite}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:884:// --- Moves HUD (bottom-right) -----------------------------------
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:885:function buildMovesHUD(p: PokemonData, dbtn?: boolean): PNode[] {
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:899: // Toggle button position (left of moves)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:916: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:932: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:951: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:968: // Calculate y position from bottom (matching old scene.js: 440 - mps[i])
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:992: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:999: text={moveNum.toString()}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1013: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1023: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1029: text={moveName}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1032: {/* PP text - positioned inside capsule with padding */}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1033: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1040: text={ppDisplay}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1050:// Cache for sprite dimensions to avoid reloading images
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1051:const spriteDimensionCache = new LruCache<
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1058: spriteDimensions: spriteDimensionCache.size,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1062:// Known dimensions for substitute sprites (avoid loading them)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1065:// Helper to get sprite dimensions by loading the image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1067: spriteUrl: string,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1071: if (spriteDimensionCache.has(spriteUrl)) {
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1072: return spriteDimensionCache.get(spriteUrl)!;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1075: // Handle special cases (substitute sprites) - use cached dimensions
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1076: if (spriteUrl === "./img/sub-back.png" || spriteUrl === "./img/sub.png") {
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1077: spriteDimensionCache.set(spriteUrl, SUBSTITUTE_DIMENSIONS);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1081: if (decodedImageCache?.has(spriteUrl)) {
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1082: const cachedImage = decodedImageCache.get(spriteUrl)!;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1087: spriteDimensionCache.set(spriteUrl, cachedDimensions);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1091: // Parse sprite:// URL to spec
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1092: const spec = parseSpriteUrl(spriteUrl);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1096: // Fallback dimensions if sprite can't be loaded
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1098: spriteDimensionCache.set(spriteUrl, fallback);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1103: decodedImageCache?.set(spriteUrl, img);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1105: spriteDimensionCache.set(spriteUrl, dimensions);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1110: imageCache?: CacheStore<string, Image>;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1145: const spriteScale = isMultiBattle ? (activePerSide === 2 ? 0.7 : 0.55) : 1.0;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1146: const hudScale = activePerSide === 3 ? 0.82 : 1;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1148: activePerSide === 3 ? 77 * hudScale : 0;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1164: // Helper to get sprite URL
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1176: // Load sprite dimensions for all pokemon
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1177: const sprite1Urls = p1.map((poke, i) =>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1180: const sprite2Urls = p2.map((poke, i) =>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1183: const sprite1ReferenceUrls = p1.map((poke, i) =>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1186: const sprite2ReferenceUrls = p2.map((poke, i) =>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1191: ...sprite1Urls,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1192: ...sprite2Urls,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1193: ...sprite1ReferenceUrls,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1194: ...sprite2ReferenceUrls,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1197: allSpriteUrls.map((url) => getSpriteDimensions(url, options.imageCache)),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1210: // Calculate sprite positions and sizes
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1211: const spriteNodes: PNode[] = [];
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1212: const hudNodes: PNode[] = [];
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1214: // Player sprites (bottom)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1221: let s = 2.2 * spriteScale; // Base scale reduced for multi-battles
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1232: const spriteW = renderedDims.width;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1233: const spriteH = renderedDims.height;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1236: let x = 400 - 65 - spriteW;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1239: x = spacing * (i + 1) - spriteW / 2;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1243: if (spriteW > 480) x = 400 - spriteW;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1245: let y = 480 - 60 - spriteH;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1246: if (y < 100) y = 470 - spriteH;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1248: y = 480 - 40 - spriteH;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1252: spriteNodes.push(
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1254: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1257: w={spriteW}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1258: h={spriteH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1259: src={sprite1Urls[i]}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1266: // Player HUD
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1267: hudNodes.push(...buildPlayerHUD(poke, poke.t, hudScale, i));
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1270: // Enemy sprites (top)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1277: // Increase scale for 2v2 battles (opponent sprites were too small)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1278: let s = 1.6 * spriteScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1289: const spriteW = renderedDims.width;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1290: const spriteH = renderedDims.height;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1293: let x = 590 - spriteW / 2;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1296: x = spacing * (i + 1) - spriteW / 2;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1301: let y = 245 - spriteH;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1303: y = 180 - spriteH;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1307: spriteNodes.push(
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1309: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1312: w={spriteW}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1313: h={spriteH}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1314: src={sprite2Urls[i]}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1321: // Enemy HUD
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1322: hudNodes.push(...buildEnemyHUD(poke, poke.t, hudScale, p2.length - i - 1));
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1328: <image x={0} y={0} w={800} h={480} src={bgImg} fit="fill" z={0} />
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1331: ...spriteNodes,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1332: // Layer 3-4: HUDs
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1333: ...hudNodes,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1334: // Layer 5: Turn bar and Weather
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1339: // Layer 6: Moves HUD (only for single battles)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/battleScene.tsx:1341: nodes.push(...buildMovesHUD(p1[0], data.dbtn));
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:6:export const BAG_HUD_WIDTH = 920;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:7:export const BAG_HUD_HEIGHT = 640;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:8:const BAG_ARTWORK_SRC = "assets/images/bulbagarden/Bag_artwork.png";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:34: w={BAG_HUD_WIDTH - 36}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:35: h={BAG_HUD_HEIGHT - 36}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:43: h={BAG_HUD_HEIGHT - 56}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:50: w={BAG_HUD_WIDTH - 298}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:51: h={BAG_HUD_HEIGHT - 56}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:59: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:73: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:76: text="Bag"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:81: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:84: text={`${model.totalStacks} entr${model.totalStacks === 1 ? "y" : "ies"}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:88: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:91: text={model.selectedCategory.label}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:96: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:99: text={`${model.selectedCategory.totalStacks} entr${
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:105: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:108: text={`PAGE ${model.selectedPage}/${model.selectedCategory.totalPages}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:114: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:117: text={`${model.selectedCategory.totalStacks} entr${
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:133: const textColor = isSelected ? "#fff8ef" : "#655845";
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:153: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:161: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:164: text={category.shortLabel}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:167: color={textColor}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:169: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:172: text={String(category.totalStacks)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:175: color={textColor}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:186: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:189: text={`No items in ${model.selectedCategory.label}.`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:195: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:198: text="This pocket is empty."
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:221: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:229: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:232: text={truncateLabel(item.itemName, 31)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:237: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/bag.tsx:240: text={formatQuantity(item.quantity)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-mega.ts:9: * 2. Run the example and generate battle scene images
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-mega.ts:30: // __dirname in compiled output is dist/src/engine/hud/builders
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-mega.ts:39: imageCache: new Map(),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:9: * 2. Run the example and generate a 2v2 battle scene image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:13: * - Resolves sprite:// URLs to actual sprite file paths
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:14: * - Extracts first frames from GIF sprites and caches them
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:15: * - Loads regular image files from disk
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:142: // __dirname in compiled output is dist/src/engine/hud/builders
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:147: // Use DiskAssetProvider which now handles sprite:// URLs with caching
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:149: console.log("Initializing asset provider with sprite caching...");
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:156: imageCache: new Map(),
/Users/dj/Developer/PokeOne/src/engine/hud/builders/example-battle-scene-2.ts:161: console.log("Rendering scene with sprite loading...");
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:5: type CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:38: // decoded image cache: key -> Image
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:39: imageCache?: CacheStore<string, Image>;
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:86: const ctx = canvas.getContext("2d");
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:115: const ctx = canvas.getContext("2d");
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:116: const imageData = ctx.getImageData(0, 0, width, height);
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:117: const data = imageData.data;
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:155: const croppedCtx = cropped.getContext("2d");
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:165: ctx: CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:222: ctx: CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:240: // create offscreen canvas of exact size (rect/image) or full
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:246: const offCtx = off.getContext("2d");
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:256: case "text":
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:259: case "image":
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:290: case "text":
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:293: case "image":
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:307:function drawRect(ctx: CanvasRenderingContext2D, node: PRect, env: RenderEnv) {
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:358: ctx: CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:409: ctx: CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:439:function drawText(ctx: CanvasRenderingContext2D, node: PText) {
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:445: ctx.textAlign = node.align ?? "left";
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:447: // Use middle baseline for centered text, top for others (matches old renderer)
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:449: ctx.textBaseline = "middle";
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:451: ctx.textBaseline = "middle";
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:454: if (node.maxWidth && node.text.length > 0) {
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:457: truncateTextToWidth(ctx, node.text, node.maxWidth),
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:464: node.text,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:472: ctx.fillText(node.text, node.x, node.y);
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:477: ctx: CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:478: text: string,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:481: if (maxWidth <= 0 || text.length === 0) {
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:485: if (ctx.measureText(text).width <= maxWidth) {
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:486: return text;
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:494: let output = text;
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:506: ctx: CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:507: text: string,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:513: const words = text.split(" ");
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:534: ctx: CanvasRenderingContext2D,
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:538: // get decoded image (with cache)
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:539: if (!env.imageCache) env.imageCache = new Map();
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:540: const imageCacheKey = node.trimTransparency ? `${node.src}::trim` : node.src;
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:541: let img = env.imageCache.get(imageCacheKey);
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:548: env.imageCache.set(imageCacheKey, img);
/Users/dj/Developer/PokeOne/src/engine/hud/renderer.ts:596: ctx.imageSmoothingEnabled = !node.pixelated;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:40: spriteSrc: string;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:427: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:436: </text>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:439: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:444: color={palette.text}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:449: </text>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:471: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:476: src={member.spriteSrc}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:655: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:660: color={palette.text}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:664: </text>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:686: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:732: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:740: </text>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:741: <text x={10} y={212} fontSize={14} color={palette.text}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:743: </text>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/trainerCard.tsx:750: fill={palette.panelAlt}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:15:// Box background images (matching box.js)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:84:// Get box background image path
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:122: spriteSrc: string; // Pokémon sprite URL
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:123: spriteTrimmedWidth?: number;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:124: spriteTrimmedHeight?: number;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:159:// Team Pokémon positions (bottom of box)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:215: spriteSize: number,
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:219: const spriteTrimmedWidth = poke.spriteTrimmedWidth ?? spriteSize;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:220: const spriteTrimmedHeight = poke.spriteTrimmedHeight ?? spriteSize;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:222: spriteSize / Math.max(spriteTrimmedWidth, spriteTrimmedHeight);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:223: const renderedHeight = spriteTrimmedHeight * renderedScale;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:224: return centerY - baseLift - (spriteSize - renderedHeight) * 0.35;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:279:// Build a single box Pokémon sprite
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:287: const spriteSize = Math.min(bounds.w, bounds.h) - 6;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:288: const spriteCenterY = getContainedSpriteCenterY(centerY, spriteSize, poke, 5);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:292: <group x={centerX} y={spriteCenterY} z={2}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:293: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:294: x={-spriteSize / 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:295: y={-spriteSize / 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:296: w={spriteSize}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:297: h={spriteSize}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:298: src={poke.spriteSrc}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:315: <image x={0} y={0} w={20} h={20} src={itemUrl} fit="contain" />
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:325:// Build a single team Pokémon sprite
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:332: const spriteSize = 76;
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:333: const spriteCenterY = getContainedSpriteCenterY(centerY, spriteSize, poke, 5);
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:337: <group x={centerX} y={spriteCenterY} z={2}>
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:338: <image
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:339: x={-spriteSize / 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:340: y={-spriteSize / 2}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:341: w={spriteSize}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:342: h={spriteSize}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:343: src={poke.spriteSrc}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:360: x={centerX - spriteSize / 2 - 6}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:361: y={spriteCenterY - spriteSize / 2 + 6}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:364: <image x={0} y={0} w={30} h={30} src={itemUrl} fit="contain" />
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:442: // Header text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:444: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:451: text="Party"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:556: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:563: text={slotLabel}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:597: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:604: text={`T${index + 1}`}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:623: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:630: text={String.fromCharCode(97 + row)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:636: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:643: text={String.fromCharCode(97 + row)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:654: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:661: text={String(col + 1)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:667: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:674: text={String(col + 1)}
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:686: // Background image (left side)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:694: <image x={0} y={0} w={296} h={300} src={bgPath} fit="cover" />
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:699: // Side UI panel (right side)
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:703: // Box name text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:705: // Font: 24px sans-serif, textBaseline="top", textAlign="center"
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:711: <text
/Users/dj/Developer/PokeOne/src/engine/hud/builders/box.tsx:717: text={boxName}
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:20:const imageDimensionsCache = new Map<
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:44: if (imageDimensionsCache.has(src)) {
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:45: return imageDimensionsCache.get(src)!;
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:48: const imagePath = resolveImagePath(src);
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:49: if (!imagePath) {
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:50: imageDimensionsCache.set(src, null);
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:55: const buffer = await fs.readFile(imagePath);
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:56: const extension = path.extname(imagePath).toLowerCase();
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:65: const image = await loadImage(buffer);
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:66: return { width: image.width, height: image.height };
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:69: imageDimensionsCache.set(src, dimensions);
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:72: imageDimensionsCache.set(src, null);
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:84: const imagePath = resolveImagePath(src);
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:85: if (!imagePath || path.extname(imagePath).toLowerCase() !== ".png") {
/Users/dj/Developer/PokeOne/src/engine/hud/imageMetadata.ts:91: const buffer = await fs.readFile(imagePath);
I’ve got the usage shape: lots of image-heavy HUDs, precise text sizing, truncation, badges, layered panels, and sprite reuse. I’m now pinning crate versions and then I’ll write the first failing tests around XML parsing, layout, templating, and deterministic raster output so the implementation grows under coverage rather than by scaffolding alone.
>cargo search skia-safe --limit 1Exit code: 0
Wall time: 0.5 seconds
Output:
skia-safe = "0.93.1" # Safe Skia Bindings for Rust
... and 21 crates more (use --limit N to see more)
note: to learn more about a package, run `cargo info <name>`
>cargo search taffy --limit 3Exit code: 0
Wall time: 0.5 seconds
Output:
taffy = "0.10.0" # A flexible UI layout library
egui_taffy = "0.12.0" # Grid, Flexbox, Block layout support for egui using taffy
taffy_blueprint = "0.1.4" # Declarative Tree and Json hot reloading for Taffy.
... and 65 crates more (use --limit N to see more)
Blocking waiting for file lock on package cache
note: to learn more about a package, run `cargo info <name>`
>cargo search napi --limit 3Exit code: 0
Wall time: 0.6 seconds
Output:
napi = "3.8.4" # N-API bindings
yuuang-test-napi = "1.7.6" # N-API bindings
napi-rs = "0.0.0" # N-API bindings
... and 555 crates more (use --limit N to see more)
Blocking waiting for file lock on package cache
note: to learn more about a package, run `cargo info <name>`
>cargo search napi-derive --limit 3Exit code: 0
Wall time: 0.5 seconds
Output:
napi-derive = "3.5.3" # N-API procedural macros
axum_napi_bridge = "0.1.0" # A bridge to use axum handlers in Node.js
napi-derive-backend = "5.0.2" # Codegen backend for napi procedural macro
... and 18 crates more (use --limit N to see more)
Blocking waiting for file lock on package cache
note: to learn more about a package, run `cargo info <name>`
>cargo info skia-safeExit code: 0
Wall time: 2.3 seconds
Output:
skia-safe #skia #rust-bindings #vulkan #opengl #pdf
Safe Skia Bindings for Rust
version: 0.93.1
license: MIT
rust-version: 1.82
documentation: https://rust-skia.github.io/doc/skia_safe
homepage: https://github.com/rust-skia/rust-skia
repository: https://github.com/rust-skia/rust-skia
crates.io: https://crates.io/crates/skia-safe/0.93.1
features:
+default = [binary-cache, embed-icudtl, pdf]
binary-cache = [skia-bindings/binary-cache]
embed-icudtl = [skia-bindings/embed-icudtl]
pdf = [skia-bindings/pdf]
all-linux = [gl, egl, vulkan, x11, wayland, textlayout, svg, skottie, webp]
all-macos = [gl, vulkan, metal, textlayout, svg, skottie, webp]
all-windows = [gl, vulkan, d3d, textlayout, svg, skottie, webp]
d3d = [gpu, windows, skia-bindings/d3d]
egl = [gl, skia-bindings/egl]
embed-freetype = [skia-bindings/embed-freetype]
freetype-woff2 = [skia-bindings/freetype-woff2]
gl = [gpu, skia-bindings/gl]
gpu = []
metal = [gpu, skia-bindings/metal]
no-compile = [skia-bindings/no-compile]
save-svg-images = []
skia-svg-macros = [dep:skia-svg-macros]
skottie = [skia-bindings/skottie, textlayout, dep:base64, dep:percent-encoding]
svg = [skia-bindings/svg, dep:base64, dep:percent-encoding, skia-svg-macros]
textlayout = [skia-bindings/textlayout]
ureq = [dep:ureq]
use-system-jpeg-turbo = [skia-bindings/use-system-jpeg-turbo]
vulkan = [gpu, skia-bindings/vulkan]
wayland = [egl, skia-bindings/wayland]
webp = [webp-encode, webp-decode]
webp-decode = [skia-bindings/webp-decode]
webp-encode = [skia-bindings/webp-encode]
windows = [dep:windows]
x11 = [gl, skia-bindings/x11]
Blocking waiting for file lock on package cache
Updating crates.io index
Downloading crates ...
Downloaded skia-safe v0.93.1
>cargo info taffyExit code: 0
Wall time: 1.1 seconds
Output:
taffy #cross-platform #layout #flexbox #css-grid #grid
A flexible UI layout library
version: 0.10.0
license: MIT
rust-version: 1.71
documentation: https://docs.rs/taffy/0.10.0
repository: https://github.com/DioxusLabs/taffy
crates.io: https://crates.io/crates/taffy/0.10.0
features:
+default = [std, taffy_tree, flexbox, grid, block_layout, float_layout, calc, content_size, detailed_layout_info, parse, parse_faster]
alloc = [serde?/alloc]
block_layout = []
calc = []
content_size = []
detailed_layout_info = []
flexbox = []
float_layout = []
grid = [alloc, dep:grid]
parse = [dep:cssparser]
parse_faster = [parse, cssparser/fast_match_byte]
std = [grid?/std, serde?/std, slotmap?/std]
taffy_tree = [dep:slotmap]
debug = [std]
document-features = [dep:document-features]
profile = [std]
serde = [dep:serde]
strict_provenance = []
Updating crates.io index
Downloading crates ...
Downloaded taffy v0.10.0
>cargo info napiExit code: 0
Wall time: 2.7 seconds
Output:
napi #NodeJS #Node #FFI #NAPI #n-api
N-API bindings
version: 3.8.4
license: MIT
rust-version: 1.88
documentation: https://docs.rs/napi/3.8.4
repository: https://github.com/napi-rs/napi-rs
crates.io: https://crates.io/crates/napi/3.8.4
features:
+default = [napi4, dyn-symbols]
dyn-symbols = [napi-sys/dyn-symbols]
napi1 = []
napi2 = [napi1, napi-sys/napi2]
napi3 = [napi2, napi-sys/napi3]
napi4 = [napi3, napi-sys/napi4]
42 deactivated features
Blocking waiting for file lock on package cache
Updating crates.io index
Downloading crates ...
Downloaded napi v3.8.4
The dependency surface looks workable: skia-safe 0.93.1 with binary-cache and textlayout, taffy 0.10.0, and napi 3.8.x. I’m moving into scaffold mode now: workspace layout, benchmark target, and the first red tests for parser/layout/render/template caching.
>cargo info napi --verboseExit code: 0
Wall time: 0.3 seconds
Output:
napi #NodeJS #Node #FFI #NAPI #n-api
N-API bindings
version: 3.8.4
license: MIT
rust-version: 1.88
documentation: https://docs.rs/napi/3.8.4
repository: https://github.com/napi-rs/napi-rs
crates.io: https://crates.io/crates/napi/3.8.4
features:
+default = [napi4, dyn-symbols]
dyn-symbols = [napi-sys/dyn-symbols]
napi1 = []
napi2 = [napi1, napi-sys/napi2]
napi3 = [napi2, napi-sys/napi3]
napi4 = [napi3, napi-sys/napi4]
anyhow = [dep:anyhow]
async = [tokio_rt]
chrono = [dep:chrono]
chrono_date = [chrono, napi5]
compat-mode = []
deferred_trace = [napi4]
encoding_rs = [dep:encoding_rs]
error_anyhow = [anyhow]
experimental = [napi-sys/experimental]
full = [latin1, napi10, async, serde-json, experimental, chrono_date]
futures-core = [dep:futures-core]
indexmap = [dep:indexmap]
latin1 = [encoding_rs]
napi10 = [napi9, napi-sys/napi10]
napi5 = [napi4, napi-sys/napi5]
napi6 = [napi5, napi-sys/napi6]
napi7 = [napi6, napi-sys/napi7]
napi8 = [napi7, napi-sys/napi8]
napi9 = [napi8, napi-sys/napi9]
node_version_detect = []
noop = []
object_indexmap = [indexmap]
serde = [dep:serde]
serde-json = [serde, serde_json]
serde-json-ordered = [serde-json, serde_json/preserve_order]
serde_json = [dep:serde_json]
tokio = [dep:tokio]
tokio-stream = [dep:tokio-stream]
tokio_fs = [tokio/fs]
tokio_full = [tokio/full]
tokio_io_std = [tokio/io-std]
tokio_io_util = [tokio/io-util]
tokio_macros = [tokio/macros]
tokio_net = [tokio/net]
tokio_process = [tokio/process]
tokio_rt = [tokio, napi4]
tokio_signal = [tokio/signal]
tokio_sync = [tokio/sync]
tokio_test_util = [tokio/test-util]
tokio_time = [tokio/time]
tracing = [dep:tracing]
web_stream = [futures-core, tokio-stream, napi4, tokio_rt]
dependencies:
+bitflags@2
+ctor@0.8.0
+futures@0.3
+napi-sys@3.2.1
+nohash-hasher@0.2.0
+rustc-hash@2.1.1
anyhow@1
chrono@0.4
encoding_rs@0.8
futures-core@0.3
indexmap@2
serde@1
serde_json@1
tokio@1
tokio@1
tokio-stream@0.1
tracing@0.1
build-dependencies:
+napi-build@2.3.1
Updating crates.io index
>cargo info napi-derive --verboseExit code: 0
Wall time: 0.5 seconds
Output:
napi-derive #NodeJS #FFI #NAPI #n-api
N-API procedural macros
version: 3.5.3
license: MIT
rust-version: 1.88
documentation: https://docs.rs/napi-derive/3.5.3
repository: https://github.com/napi-rs/napi-rs
crates.io: https://crates.io/crates/napi-derive/3.5.3
features:
+default = [type-def, strict]
ctor = [dep:ctor]
strict = [napi-derive-backend/strict]
type-def = [napi-derive-backend/type-def, ctor]
compat-mode = []
full = [type-def, strict, compat-mode]
noop = [napi-derive-backend/noop]
tracing = [napi-derive-backend/tracing]
dependencies:
+convert_case@0.11
+napi-derive-backend@5.0.2
+proc-macro2@1
+quote@1
+syn@2
ctor@0.8
Blocking waiting for file lock on package cache
Updating crates.io index
Downloading crates ...
Downloaded napi-derive v3.5.3
Plan for the first implementation slice:
taffy-canvas-core and taffy-canvas-node.core, define the document model, XML parser, style system, template compiler, asset/text measurement traits, and a CPU raster renderer using Skia.node, expose sync and async render/template APIs via napi-rs, with a thread-pool-backed renderer handle.I’m going to scaffold the workspace and write the first failing tests now.
I’m creating the workspace skeleton now, then I’ll immediately replace the defaults with test targets so the implementation starts red.
>cargo new --lib crates/taffy-canvas-coreExit code: 0
Wall time: 0.4 seconds
Output:
Creating library `taffy-canvas-core` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
>cargo new --lib crates/taffy-canvas-nodeExit code: 0
Wall time: 0.3 seconds
Output:
Creating library `taffy-canvas-node` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
>find . -maxdepth 3 -type f | sortExit code: 0
Wall time: 0 seconds
Output:
./crates/taffy-canvas-core/.gitignore
./crates/taffy-canvas-core/Cargo.toml
./crates/taffy-canvas-node/.gitignore
./crates/taffy-canvas-node/Cargo.toml
>sed -n '1,200p' crates/taffy-canvas-core/Cargo.tomlExit code: 0
Wall time: 0 seconds
Output:
[package]
name = "taffy-canvas-core"
version = "0.1.0"
edition = "2024"
[dependencies]
>sed -n '1,200p' crates/taffy-canvas-node/Cargo.tomlExit code: 0
Wall time: 0 seconds
Output:
[package]
name = "taffy-canvas-node"
version = "0.1.0"
edition = "2024"
[dependencies]
>sed -n '1,200p' crates/taffy-canvas-core/src/lib.rsExit code: 0
Wall time: 0 seconds
Output:
pub fn add(left: u64, right: u64) -> u64 {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}
>sed -n '1,200p' crates/taffy-canvas-node/src/lib.rsExit code: 0
Wall time: 0 seconds
Output:
pub fn add(left: u64, right: u64) -> u64 {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}
I’ve got the minimal viable slice defined tightly enough to code against: XML view/text/image, CSS-like layout props, template placeholders, CPU raster via Skia, and an async pool surface. I’m editing the workspace manifests and adding the first failing tests now.
>rg -n "pub enum Position|MeasureFunc|new_leaf_with_context|compute_layout_with_measure|compute_layout" ~/.cargo/registry/src -g '*/taffy-0.10.0/src/*.rs'Exit code: 1
Wall time: 0.4 seconds
Output:
>rg -n "pub struct Paragraph|layout\(|paint\(|FontCollection" ~/.cargo/registry/src -g '*/skia-safe-0.93.1/src/textlayout/*.rs'Exit code: 1
Wall time: 0.4 seconds
Output:
Tip for XML parsing: specialize it for our use-case to squeeze performance out of it.
I’m taking that as a requirement, not just an optimization note. I’ll keep the XML parser purpose-built for this schema instead of building a generic DOM parser, so we can avoid excess allocation and parse directly into our node arena/template segments.
>find ~/.cargo/registry/src -maxdepth 2 -type d | head -20Exit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/match_cfg-0.1.0
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/polyval-0.6.2
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cranelift-isle-0.116.1
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustcrypto-group-0.14.0-rc.0
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/raffia_macro-0.1.1
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crossbeam-deque-0.8.5
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/md-5-0.10.6
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unicode-xid-0.2.6
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/fxhash-0.2.1
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bit-vec-0.8.0
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/moka-0.12.10
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sha3-0.10.8
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/resb-0.1.1
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libz-sys-1.1.20
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bit-set-0.8.0
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sqlformat-0.3.5
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/target-lexicon-0.13.2
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/const-oid-0.9.6
>rg -n "new_leaf_with_context|compute_layout\(|MeasureFunc|AvailableSpace|TaffyTree" ~/.cargo/registry/src/*/taffy-0.10.0/srcExit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/prelude.rs:6: AlignContent, AlignItems, AlignSelf, AvailableSpace, BoxSizing, CompactLength, Dimension, Display,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/prelude.rs:30:pub use crate::TaffyTree;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/lib.rs:28://! The high-level API consists of the [`TaffyTree`] struct which contains a tree implementation and provides methods that allow you to construct
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/lib.rs:29://! a tree of UI nodes. Once constructed, you can call the [`compute_layout_with_measure`](crate::TaffyTree::compute_layout_with_measure) method to compute the layout (passing in a "measure function" closure which is used to compute the size of leaf nodes), and then access
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/lib.rs:30://! the layout of each node using the [`layout`](crate::TaffyTree::layout) method.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/lib.rs:33://! See the [`TaffyTree`] struct for more details on this API.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/lib.rs:121:pub use crate::tree::TaffyTree;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/test.rs:3:use taffy::{AvailableSpace, NodeId, Size, Style};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/test.rs:61: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/test.rs:122: available_space: taffy::Size<taffy::AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/test.rs:147: AvailableSpace::MinContent => min_line_length as f32 * H_WIDTH,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/test.rs:148: AvailableSpace::MaxContent => max_line_length as f32 * H_WIDTH,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/test.rs:149: AvailableSpace::Definite(inline_size) => inline_size.min(max_line_length as f32 * H_WIDTH),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:15:pub enum AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:23:impl TaffyZero for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:26:impl TaffyMaxContent for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:29:impl TaffyMinContent for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:32:impl FromLength for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:39:impl FromCss for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:51:from_str_from_css!(AvailableSpace);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:53:impl AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:56: matches!(self, AvailableSpace::Definite(_))
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:63: AvailableSpace::Definite(value) => Some(value),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:80: pub fn or(self, default: AvailableSpace) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:82: AvailableSpace::Definite(_) => self,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:88: pub fn or_else(self, default_cb: impl FnOnce() -> AvailableSpace) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:90: AvailableSpace::Definite(_) => self,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:100: /// If passed value is Some then return AvailableSpace::Definite containing that value, else return self
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:101: pub fn maybe_set(self, value: Option<f32>) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:103: Some(value) => AvailableSpace::Definite(value),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:108: /// If passed value is Some then return AvailableSpace::Definite containing that value, else return self
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:109: pub fn map_definite_value(self, map_function: impl FnOnce(f32) -> f32) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:111: AvailableSpace::Definite(value) => AvailableSpace::Definite(map_function(value)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:119: AvailableSpace::MaxContent => f32::INFINITY,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:120: AvailableSpace::MinContent => 0.0,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:121: AvailableSpace::Definite(available_space) => available_space - used_space,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:125: /// Compare equality with another AvailableSpace, treating definite values
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:127: pub fn is_roughly_equal(self, other: AvailableSpace) -> bool {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:128: use AvailableSpace::*;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:138:impl From<f32> for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:144:impl From<Option<f32>> for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:153:impl Size<AvailableSpace> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:154: /// Convert `Size<AvailableSpace>` into `Size<Option<f32>>`
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:159: /// If passed value is Some then return AvailableSpace::Definite containing that value, else return self
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/available_space.rs:160: pub fn maybe_set(self, value: Size<Option<f32>>) -> Size<AvailableSpace> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/traits.rs:133:use crate::style::{AvailableSpace, CoreStyle};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/traits.rs:330: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/traits.rs:359: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/traits.rs:385: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/mod.rs:3://! - For documentation on the high-level API, see the [`TaffyTree`] struct.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/mod.rs:30:pub use taffy_tree::{TaffyError, TaffyResult, TaffyTree};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/mod.rs:17:pub use self::available_space::AvailableSpace;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/layout.rs:3:use crate::style::AvailableSpace;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/layout.rs:133: pub available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/leaf.rs:4:use crate::style::{AvailableSpace, Overflow, Position};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/leaf.rs:15:pub fn compute_leaf_layout<MeasureFunction>(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/leaf.rs:19: measure_function: MeasureFunction,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/leaf.rs:22: MeasureFunction: FnOnce(Size<Option<f32>>, Size<AvailableSpace>) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/leaf.rs:114: .map(AvailableSpace::from)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/leaf.rs:124: .map(AvailableSpace::from)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:5:use crate::style::AvailableSpace;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:137:impl MaybeMath<f32, AvailableSpace> for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:138: fn maybe_min(self, rhs: f32) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:140: AvailableSpace::Definite(val) => AvailableSpace::Definite(val.min(rhs)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:141: AvailableSpace::MinContent => AvailableSpace::Definite(rhs),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:142: AvailableSpace::MaxContent => AvailableSpace::Definite(rhs),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:145: fn maybe_max(self, rhs: f32) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:147: AvailableSpace::Definite(val) => AvailableSpace::Definite(val.max(rhs)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:148: AvailableSpace::MinContent => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:149: AvailableSpace::MaxContent => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:153: fn maybe_clamp(self, min: f32, max: f32) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:155: AvailableSpace::Definite(val) => AvailableSpace::Definite(val.min(max).max(min)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:156: AvailableSpace::MinContent => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:157: AvailableSpace::MaxContent => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:161: fn maybe_add(self, rhs: f32) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:163: AvailableSpace::Definite(val) => AvailableSpace::Definite(val + rhs),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:164: AvailableSpace::MinContent => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:165: AvailableSpace::MaxContent => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:168: fn maybe_sub(self, rhs: f32) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:170: AvailableSpace::Definite(val) => AvailableSpace::Definite(val - rhs),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:171: AvailableSpace::MinContent => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:172: AvailableSpace::MaxContent => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:177:impl MaybeMath<Option<f32>, AvailableSpace> for AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:178: fn maybe_min(self, rhs: Option<f32>) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:180: (AvailableSpace::Definite(val), Some(rhs)) => AvailableSpace::Definite(val.min(rhs)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:181: (AvailableSpace::Definite(val), None) => AvailableSpace::Definite(val),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:182: (AvailableSpace::MinContent, Some(rhs)) => AvailableSpace::Definite(rhs),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:183: (AvailableSpace::MinContent, None) => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:184: (AvailableSpace::MaxContent, Some(rhs)) => AvailableSpace::Definite(rhs),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:185: (AvailableSpace::MaxContent, None) => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:188: fn maybe_max(self, rhs: Option<f32>) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:190: (AvailableSpace::Definite(val), Some(rhs)) => AvailableSpace::Definite(val.max(rhs)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:191: (AvailableSpace::Definite(val), None) => AvailableSpace::Definite(val),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:192: (AvailableSpace::MinContent, _) => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:193: (AvailableSpace::MaxContent, _) => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:197: fn maybe_clamp(self, min: Option<f32>, max: Option<f32>) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:199: (AvailableSpace::Definite(val), Some(min), Some(max)) => AvailableSpace::Definite(val.min(max).max(min)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:200: (AvailableSpace::Definite(val), None, Some(max)) => AvailableSpace::Definite(val.min(max)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:201: (AvailableSpace::Definite(val), Some(min), None) => AvailableSpace::Definite(val.max(min)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:202: (AvailableSpace::Definite(val), None, None) => AvailableSpace::Definite(val),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:203: (AvailableSpace::MinContent, _, _) => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:204: (AvailableSpace::MaxContent, _, _) => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:208: fn maybe_add(self, rhs: Option<f32>) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:210: (AvailableSpace::Definite(val), Some(rhs)) => AvailableSpace::Definite(val + rhs),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:211: (AvailableSpace::Definite(val), None) => AvailableSpace::Definite(val),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:212: (AvailableSpace::MinContent, _) => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:213: (AvailableSpace::MaxContent, _) => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:216: fn maybe_sub(self, rhs: Option<f32>) -> AvailableSpace {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:218: (AvailableSpace::Definite(val), Some(rhs)) => AvailableSpace::Definite(val - rhs),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:219: (AvailableSpace::Definite(val), None) => AvailableSpace::Definite(val),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:220: (AvailableSpace::MinContent, _) => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/util/math.rs:221: (AvailableSpace::MaxContent, _) => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/mod.rs:1://! Low-level access to the layout algorithms themselves. For a higher-level API, see the [`TaffyTree`](crate::TaffyTree) struct.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/mod.rs:54:use crate::style::{AvailableSpace, CoreStyle, Overflow};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/mod.rs:64:pub fn compute_root_layout(tree: &mut impl LayoutPartialTree, root: NodeId, available_space: Size<AvailableSpace>) {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/mod.rs:304: use crate::TaffyTree;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/mod.rs:308: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/cache.rs:3:use crate::style::AvailableSpace;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/cache.rs:16: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/cache.rs:73: fn compute_cache_slot(known_dimensions: Size<Option<f32>>, available_space: Size<AvailableSpace>) -> usize {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/cache.rs:74: use AvailableSpace::{Definite, MaxContent, MinContent};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1://! Contains [TaffyTree](crate::tree::TaffyTree): the default implementation of [LayoutTree](crate::tree::LayoutTree), and the error type for Taffy.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:11:use crate::style::{AvailableSpace, Display, Style};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:52: /// The parent node was not found in the [`TaffyTree`](crate::TaffyTree) instance.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:54: /// The child node was not found in the [`TaffyTree`](crate::TaffyTree) instance.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:56: /// The supplied node was not found in the [`TaffyTree`](crate::TaffyTree) instance.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:67: write!(f, "Parent Node {parent:?} is not in the TaffyTree instance")
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:69: TaffyError::InvalidChildNode(child) => write!(f, "Child Node {child:?} is not in the TaffyTree instance"),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:70: TaffyError::InvalidInputNode(node) => write!(f, "Supplied Node {node:?} is not in the TaffyTree instance"),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:78:/// Global configuration values for a TaffyTree instance
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:93:/// Stored in a [`TaffyTree`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:147:pub struct TaffyTree<NodeContext = ()> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:168:impl Default for TaffyTree {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:169: fn default() -> TaffyTree<()> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:170: TaffyTree::new()
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:175:pub struct TaffyTreeChildIter<'a>(core::slice::Iter<'a, NodeId>);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:176:impl Iterator for TaffyTreeChildIter<'_> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:185:// TraversePartialTree impl for TaffyTree
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:186:impl<NodeContext> TraversePartialTree for TaffyTree<NodeContext> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:188: = TaffyTreeChildIter<'a>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:194: TaffyTreeChildIter(self.children[parent_node_id.into()].iter())
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:208:// TraverseTree impl for TaffyTree
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:209:impl<NodeContext> TraverseTree for TaffyTree<NodeContext> {}
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:211:// CacheTree impl for TaffyTree
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:212:impl<NodeContext> CacheTree for TaffyTree<NodeContext> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:226:// PrintTree impl for TaffyTree
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:227:impl<NodeContext> PrintTree for TaffyTree<NodeContext> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:263:/// and implements LayoutTree. This allows the context to be stored outside of the TaffyTree struct
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:265:pub(crate) struct TaffyView<'t, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:267: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:268: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:270: /// A reference to the TaffyTree
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:271: pub(crate) taffy: &'t mut TaffyTree<NodeContext>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:273: pub(crate) measure_function: MeasureFunction,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:276:impl<NodeContext, MeasureFunction> TaffyView<'_, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:278: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:279: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:334:impl<NodeContext, MeasureFunction> TraversePartialTree for TaffyView<'_, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:336: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:337: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:340: = TaffyTreeChildIter<'a>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:361:impl<NodeContext, MeasureFunction> TraverseTree for TaffyView<'_, NodeContext, MeasureFunction> where
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:362: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:363: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:368:impl<NodeContext, MeasureFunction> LayoutPartialTree for TaffyView<'_, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:370: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:371: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:406:impl<NodeContext, MeasureFunction> CacheTree for TaffyView<'_, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:408: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:409: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:425:impl<NodeContext, MeasureFunction> LayoutBlockContainer for TaffyView<'_, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:427: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:428: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:461:impl<NodeContext, MeasureFunction> LayoutFlexboxContainer for TaffyView<'_, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:463: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:464: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:487:impl<NodeContext, MeasureFunction> LayoutGridContainer for TaffyView<'_, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:489: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:490: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:519:impl<NodeContext, MeasureFunction> RoundTree for TaffyView<'_, NodeContext, MeasureFunction>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:521: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:522: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:536:impl<NodeContext> TaffyTree<NodeContext> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:537: /// Creates a new [`TaffyTree`]
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:539: /// The default capacity of a [`TaffyTree`] is 16 nodes.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:545: /// Creates a new [`TaffyTree`] that can store `capacity` nodes before reallocation
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:548: TaffyTree {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:581: pub fn new_leaf_with_context(&mut self, layout: Style, context: NodeContext) -> TaffyResult<NodeId> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:905: pub fn compute_layout_with_measure<MeasureFunction>(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:908: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:909: measure_function: MeasureFunction,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:912: MeasureFunction:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:913: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:925: pub fn compute_layout(&mut self, node: NodeId, available_space: Size<AvailableSpace>) -> Result<(), TaffyError> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:935: /// Returns an instance of LayoutTree representing the TaffyTree
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:952: _available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:963: let taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:973: let taffy: TaffyTree<()> = TaffyTree::with_capacity(CAPACITY);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:982: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:993: fn new_leaf_with_context() {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:994: let mut taffy: TaffyTree<Size<f32>> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:996: let res = taffy.new_leaf_with_context(Style::default(), Size::ZERO);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1007: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1020: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1029: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1050: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1062: let mut taffy: TaffyTree<Size<f32>> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1063: let node = taffy.new_leaf_with_context(Style::default(), Size { width: 200.0, height: 200.0 }).unwrap();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1074: let mut taffy: TaffyTree<Size<f32>> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1087: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1102: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1129: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1151: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1168: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1185: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1208: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1223: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1238: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1250: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1263: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1279: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1289: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1301: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1311: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1316: taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1327: taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1336: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1343: let layout_result = taffy.compute_layout(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1345: Size { width: AvailableSpace::Definite(100.), height: AvailableSpace::Definite(100.) },
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1354: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1379: taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rs:1396: let mut taffy: TaffyTree<()> = TaffyTree::new();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/float.rs:31:use crate::{debug::debug_log, sys::Vec, AvailableSpace, Clear, FloatDirection, Point, Size};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/float.rs:526: available_width: AvailableSpace,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/float.rs:533: pub fn new(available_width: AvailableSpace) -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/float.rs:540: AvailableSpace::Definite(_) => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/float.rs:543: AvailableSpace::MinContent => self.contribution = self.contribution.max(width),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/float.rs:544: AvailableSpace::MaxContent => self.contribution += width,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/mod.rs:5:use crate::style::{AlignItems, AlignSelf, AvailableSpace, Overflow, Position};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/mod.rs:112: .map(|size| size.map(AvailableSpace::Definite))
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:3:use crate::style::{AvailableSpace, CoreStyle, LengthPercentageAuto, Overflow, Position};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:616: available_width: AvailableSpace,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:618: let available_space = Size { width: available_width, height: AvailableSpace::MinContent };
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:683: Size { width: AvailableSpace::Definite(container_inner_width), height: AvailableSpace::MinContent };
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:851: available_space: available_space.map_width(|_| AvailableSpace::Definite(stretch_width)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:1157: width: AvailableSpace::Definite(area_width.maybe_clamp(min_size.width, max_size.width)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:1158: height: AvailableSpace::Definite(area_height.maybe_clamp(min_size.height, max_size.height)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:1171: width: AvailableSpace::Definite(area_width.maybe_clamp(min_size.width, max_size.width)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/block.rs:1172: height: AvailableSpace::Definite(area_height.maybe_clamp(min_size.height, max_size.height)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:5:use crate::style::{AlignContent, AlignSelf, AvailableSpace};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:276: available_grid_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:336: // something like stretch alignment), not just any available space. To do this we map definite available space to AvailableSpace::MaxContent
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:339: AvailableSpace::Definite(available_space)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:342: AvailableSpace::MinContent => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:343: AvailableSpace::MaxContent | AvailableSpace::Definite(_) => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:529: axis_available_grid_space: AvailableSpace,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:597: AvailableSpace::MinContent | AvailableSpace::MaxContent
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:692: AvailableSpace::MinContent | AvailableSpace::MaxContent
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:784: if axis_available_grid_space == AvailableSpace::MaxContent {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:1144: axis_available_grid_space: AvailableSpace,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:1177: axis_available_space_for_expansion: AvailableSpace,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:1187: AvailableSpace::Definite(available_space) => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:1197: AvailableSpace::MinContent => 0.0,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:1199: AvailableSpace::MaxContent => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/track_sizing.rs:1335: axis_available_space_for_expansion: AvailableSpace,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/alignment.rs:5:use crate::style::{AlignContent, AlignItems, AlignSelf, AvailableSpace, CoreStyle, GridItemStyle, Overflow, Position};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/alignment.rs:216: grid_area_minus_item_margins_size.map(AvailableSpace::Definite),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/alignment.rs:229: grid_area_minus_item_margins_size.map(AvailableSpace::Definite),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:1://! Computes the [flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) layout algorithm on [`TaffyTree`](crate::TaffyTree) according to the [spec](https://www.w3.org/TR/css-flexbox-1/)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:5: AlignContent, AlignItems, AlignSelf, AvailableSpace, FlexWrap, JustifyContent, LengthPercentageAuto, Overflow,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:597: outer_available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:599:) -> Size<AvailableSpace> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:602: Some(node_width) => AvailableSpace::Definite(node_width - constants.content_box_inset.horizontal_axis_sum()),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:610: Some(node_height) => AvailableSpace::Definite(node_height - constants.content_box_inset.vertical_axis_sum()),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:651: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:669: let cross_axis_available_space: AvailableSpace = match available_space.cross(dir) {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:670: AvailableSpace::Definite(val) => AvailableSpace::Definite(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:673: AvailableSpace::MinContent => match child_min_cross {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:674: Some(min) => AvailableSpace::Definite(min),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:675: None => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:677: AvailableSpace::MaxContent => match child_max_cross {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:678: Some(max) => AvailableSpace::Definite(max),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:679: None => AvailableSpace::MaxContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:757: // Map AvailableSpace::Definite to AvailableSpace::MaxContent
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:758: if available_space.main(dir) == AvailableSpace::MinContent {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:759: AvailableSpace::MinContent
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:761: AvailableSpace::MaxContent
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:859: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:868: Some(max_size) => AvailableSpace::Definite(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:881: AvailableSpace::MaxContent => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:888: AvailableSpace::MinContent => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:898: AvailableSpace::Definite(main_axis_available_space) => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:933: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:942: AvailableSpace::Definite(main_axis_available_space) => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:968: AvailableSpace::MinContent if constants.is_wrap => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:989: AvailableSpace::MinContent | AvailableSpace::MaxContent => {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:1041: let cross_axis_available_space: AvailableSpace = available_space
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:1375: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:1424: available_space: Size<AvailableSpace>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:2229: width: AvailableSpace::Definite(container_width.maybe_clamp(min_size.width, max_size.width)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:2230: height: AvailableSpace::Definite(container_height.maybe_clamp(min_size.height, max_size.height)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:2242: width: AvailableSpace::Definite(container_width.maybe_clamp(min_size.width, max_size.width)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/flexbox.rs:2243: height: AvailableSpace::Definite(container_height.maybe_clamp(min_size.height, max_size.height)),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/types/grid_item.rs:6:use crate::style::{AlignItems, AlignSelf, AvailableSpace, Dimension, LengthPercentageAuto, Overflow};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/types/grid_item.rs:387: Some(size) => AvailableSpace::Definite(size),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/types/grid_item.rs:388: None => AvailableSpace::MinContent,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/types/grid_item.rs:426: Some(size) => AvailableSpace::Definite(size),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/compute/grid/types/grid_item.rs:427: None => AvailableSpace::MaxContent,
>rg -n "pub struct Paragraph|pub struct ParagraphBuilder|FontCollection|layout\(|paint\(" ~/.cargo/registry/src/*/skia-safe-0.93.1/src/textlayoutExit code: 1
Wall time: 0 seconds
Output:
zsh:1: no matches found: /Users/dj/.cargo/registry/src/*/skia-safe-0.93.1/src/textlayout
>find ~/.cargo/registry/src -path '*skia-safe-0.93.1/src/textlayout*' -type f | sort | head -50Exit code: 0
Wall time: 1.1 seconds
Output:
>sed -n '1,220p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rsExit code: 0
Wall time: 0 seconds
Output:
//! Contains [TaffyTree](crate::tree::TaffyTree): the default implementation of [LayoutTree](crate::tree::LayoutTree), and the error type for Taffy.
#[cfg(not(feature = "std"))]
use slotmap::SecondaryMap;
#[cfg(feature = "std")]
use slotmap::SparseSecondaryMap as SecondaryMap;
use slotmap::{DefaultKey, SlotMap};
#[cfg(feature = "block_layout")]
use crate::block::BlockContext;
use crate::geometry::Size;
use crate::style::{AvailableSpace, Display, Style};
use crate::sys::DefaultCheapStr;
use crate::tree::{
Cache, ClearState, Layout, LayoutInput, LayoutOutput, LayoutPartialTree, NodeId, PrintTree, RoundTree, RunMode,
TraversePartialTree, TraverseTree,
};
use crate::util::debug::{debug_log, debug_log_node};
use crate::util::sys::{new_vec_with_capacity, ChildrenVec, Vec};
use crate::compute::{
compute_cached_layout, compute_hidden_layout, compute_leaf_layout, compute_root_layout, round_layout,
};
use crate::CacheTree;
#[cfg(feature = "block_layout")]
use crate::{compute::compute_block_layout, LayoutBlockContainer};
#[cfg(feature = "flexbox")]
use crate::{compute::compute_flexbox_layout, LayoutFlexboxContainer};
#[cfg(feature = "grid")]
use crate::{compute::compute_grid_layout, LayoutGridContainer};
#[cfg(all(feature = "detailed_layout_info", feature = "grid"))]
use crate::compute::grid::DetailedGridInfo;
#[cfg(feature = "detailed_layout_info")]
use crate::tree::layout::DetailedLayoutInfo;
/// The error Taffy generates on invalid operations
pub type TaffyResult<T> = Result<T, TaffyError>;
/// An error that occurs while trying to access or modify a node's children by index.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TaffyError {
/// The parent node does not have a child at `child_index`. It only has `child_count` children
ChildIndexOutOfBounds {
/// The parent node whose child was being looked up
parent: NodeId,
/// The index that was looked up
child_index: usize,
/// The total number of children the parent has
child_count: usize,
},
/// The parent node was not found in the [`TaffyTree`](crate::TaffyTree) instance.
InvalidParentNode(NodeId),
/// The child node was not found in the [`TaffyTree`](crate::TaffyTree) instance.
InvalidChildNode(NodeId),
/// The supplied node was not found in the [`TaffyTree`](crate::TaffyTree) instance.
InvalidInputNode(NodeId),
}
impl core::fmt::Display for TaffyError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count } => {
write!(f, "Index (is {child_index}) should be < child_count ({child_count}) for parent node {parent:?}")
}
TaffyError::InvalidParentNode(parent) => {
write!(f, "Parent Node {parent:?} is not in the TaffyTree instance")
}
TaffyError::InvalidChildNode(child) => write!(f, "Child Node {child:?} is not in the TaffyTree instance"),
TaffyError::InvalidInputNode(node) => write!(f, "Supplied Node {node:?} is not in the TaffyTree instance"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for TaffyError {}
/// Global configuration values for a TaffyTree instance
#[derive(Debug, Clone, Copy)]
pub(crate) struct TaffyConfig {
/// Whether to round layout values
pub(crate) use_rounding: bool,
}
impl Default for TaffyConfig {
fn default() -> Self {
Self { use_rounding: true }
}
}
/// Layout information for a given [`Node`](crate::node::Node)
///
/// Stored in a [`TaffyTree`].
#[derive(Debug, Clone, PartialEq)]
struct NodeData {
/// The layout strategy used by this node
pub(crate) style: Style,
/// The always unrounded results of the layout computation. We must store this separately from the rounded
/// layout to avoid errors from rounding already-rounded values. See <https://github.com/DioxusLabs/taffy/issues/501>.
pub(crate) unrounded_layout: Layout,
/// The final results of the layout computation.
/// These may be rounded or unrounded depending on what the `use_rounding` config setting is set to.
pub(crate) final_layout: Layout,
/// Whether the node has context data associated with it or not
pub(crate) has_context: bool,
/// The cached results of the layout computation
pub(crate) cache: Cache,
/// The computation result from layout algorithm
#[cfg(feature = "detailed_layout_info")]
pub(crate) detailed_layout_info: DetailedLayoutInfo,
}
impl NodeData {
/// Create the data for a new node
#[must_use]
pub const fn new(style: Style) -> Self {
Self {
style,
cache: Cache::new(),
unrounded_layout: Layout::new(),
final_layout: Layout::new(),
has_context: false,
#[cfg(feature = "detailed_layout_info")]
detailed_layout_info: DetailedLayoutInfo::None,
}
}
/// Marks a node and all of its ancestors as requiring relayout
///
/// This clears any cached data and signals that the data must be recomputed.
/// If the node was already marked as dirty, returns true
#[inline]
pub fn mark_dirty(&mut self) -> ClearState {
self.cache.clear()
}
}
/// An entire tree of UI nodes. The entry point to Taffy's high-level API.
///
/// Allows you to build a tree of UI nodes, run Taffy's layout algorithms over that tree, and then access the resultant layout.]
#[derive(Debug, Clone)]
pub struct TaffyTree<NodeContext = ()> {
/// The [`NodeData`] for each node stored in this tree
nodes: SlotMap<DefaultKey, NodeData>,
/// Functions/closures that compute the intrinsic size of leaf nodes
node_context_data: SecondaryMap<DefaultKey, NodeContext>,
/// The children of each node
///
/// The indexes in the outer vector correspond to the position of the parent [`NodeData`]
children: SlotMap<DefaultKey, ChildrenVec<NodeId>>,
/// The parents of each node
///
/// The indexes in the outer vector correspond to the position of the child [`NodeData`]
parents: SlotMap<DefaultKey, Option<NodeId>>,
/// Layout mode configuration
config: TaffyConfig,
}
impl Default for TaffyTree {
fn default() -> TaffyTree<()> {
TaffyTree::new()
}
}
/// Iterator that wraps a slice of nodes, lazily converting them to u64
pub struct TaffyTreeChildIter<'a>(core::slice::Iter<'a, NodeId>);
impl Iterator for TaffyTreeChildIter<'_> {
type Item = NodeId;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next().copied()
}
}
// TraversePartialTree impl for TaffyTree
impl<NodeContext> TraversePartialTree for TaffyTree<NodeContext> {
type ChildIter<'a>
= TaffyTreeChildIter<'a>
where
Self: 'a;
#[inline(always)]
fn child_ids(&self, parent_node_id: NodeId) -> Self::ChildIter<'_> {
TaffyTreeChildIter(self.children[parent_node_id.into()].iter())
}
#[inline(always)]
fn child_count(&self, parent_node_id: NodeId) -> usize {
self.children[parent_node_id.into()].len()
}
#[inline(always)]
fn get_child_id(&self, parent_node_id: NodeId, id: usize) -> NodeId {
self.children[parent_node_id.into()][id]
}
}
// TraverseTree impl for TaffyTree
impl<NodeContext> TraverseTree for TaffyTree<NodeContext> {}
// CacheTree impl for TaffyTree
impl<NodeContext> CacheTree for TaffyTree<NodeContext> {
fn cache_get(&self, node_id: NodeId, input: &LayoutInput) -> Option<LayoutOutput> {
self.nodes[node_id.into()].cache.get(input)
}
fn cache_store(&mut self, node_id: NodeId, input: &LayoutInput, layout_output: LayoutOutput) {
self.nodes[node_id.into()].cache.store(input, layout_output)
}
And also initialize git repo as needed. Keep committing incrementally as you work
I’m incorporating both new constraints: the XML parser will stay specialized and I’ll keep the repo history incremental rather than dumping one large commit at the end. I’m initializing git now, then I’ll land the red-test scaffold as the first commit before moving green.
>git init -b mainExit code: 0
Wall time: 0.1 seconds
Output:
Initialized empty Git repository in /Users/dj/Developer/taffy-canvas/.git/
>git status --shortExit code: 128
Wall time: 0.1 seconds
Output:
fatal: not a git repository (or any of the parent directories): .git
>rg -n "pub struct FontCollection|pub struct ParagraphBuilder|pub struct ParagraphStyle|pub struct TextStyle|layout\(|paint\(" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src -g '*.rs'Exit code: 0
Wall time: 0.1 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:303: pub fn set_foreground_paint(&mut self, paint: &Paint) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:308: #[deprecated(since = "0.64.0", note = "use set_foreground_paint()")]
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:310: self.set_foreground_paint(paint)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:326: pub fn set_background_paint(&mut self, paint: &Paint) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:331: #[deprecated(since = "0.64.0", note = "use set_background_paint()")]
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:333: self.set_background_paint(paint)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/stroke_rec.rs:57: pub fn from_paint(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/stroke_rec.rs:163: pub fn apply_to_paint(&self, paint: &mut Paint) {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rs:74: pub fn layout(&mut self, width: scalar) {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rs:75: unsafe { sb::C_Paragraph_layout(self.native_mut(), width) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rs:78: pub fn paint(&self, canvas: &Canvas, p: impl Into<Point>) {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rs:80: unsafe { sb::C_Paragraph_paint(self.native_mut_force(), canvas.native_mut(), p.x, p.y) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rs:715: paragraph.layout(100.0);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rs:760: paragraph.layout(256.0);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rs:776: paragraph.layout(200.);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:101: pub fn paint(mut self, paint: &'a Paint) -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1262: pub fn draw_paint(&self, paint: &Paint) -> &Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/svg/fe/types.rs:67: pub fn fill_paint() -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/svg/fe/types.rs:74: pub fn stroke_paint() -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/vk/vulkan_mutable_texture_state.rs:16: pub fn get_vk_image_layout(state: &MutableTextureState) -> sb::VkImageLayout {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/mutable_texture_state.rs:28: &crate::gpu::vk::mutable_texture_states::get_vk_image_layout(self),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/mutable_texture_state.rs:59: note = "use gpu::vk::mutable_texture_states::get_vk_image_layout()"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/mutable_texture_state.rs:61: pub fn vk_image_layout(&self) -> sb::VkImageLayout {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/mutable_texture_state.rs:62: crate::gpu::vk::mutable_texture_states::get_vk_image_layout(self)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/ganesh/backend_surface.rs:357: pub fn set_vulkan_image_layout(&mut self, layout: vk::ImageLayout) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/ganesh/backend_surface.rs:358: gpu::backend_textures::set_vk_image_layout(self, layout)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/ganesh/backend_surface.rs:535: pub fn set_vulkan_image_layout(&mut self, layout: vk::ImageLayout) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/ganesh/backend_surface.rs:536: gpu::backend_render_targets::set_vk_image_layout(self, layout)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/ganesh/vk/vk_backend_surface.rs:94: pub fn set_vk_image_layout(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/gpu/ganesh/vk/vk_backend_surface.rs:126: pub fn set_vk_image_layout(
>rg -n "encode_to_data|Image::from_encoded|Surface::new_raster_n32_premul|draw_str|RRect" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src -g '*.rs'Exit code: 0
Wall time: 0.1 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/utils/camera.rs:182: let mut surface = Surface::new_raster_n32_premul((100, 100)).unwrap();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/utils/text_utils.rs:8:pub fn draw_str(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/utils/text_utils.rs:45: pub fn draw_str_align(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core.rs:152:pub use rrect::RRect;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:8: PathFillType, PathVerb, Point, RRect, Rect, Vector,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:256: pub fn rrect(rect: impl AsRef<RRect>, dir: impl Into<Option<PathDirection>>) -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:258: sb::C_SkPath_RRect(path, rect.as_ref().native(), dir.into().unwrap_or_default())
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:263: rect: impl AsRef<RRect>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:268: sb::C_SkPath_RRectWithStartIndex(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:436: /// Returns [`RRect`] if path is representable as [`RRect`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:439: /// Returns: [`RRect`] if [`Path`] contains only [`RRect`]
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:441: /// example: <https://fiddle.skia.org/c/@Path_isRRect>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:442: pub fn is_rrect(&self) -> Option<RRect> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:443: let mut rrect = RRect::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path.rs:444: unsafe { self.native().isRRect(rrect.native_mut()) }.then_some(rrect)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:2:use skia_bindings::{self as sb, SkRRect};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:5:pub use skia_bindings::SkRRect_Type as Type;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:8:pub use skia_bindings::SkRRect_Corner as Corner;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:13:pub struct RRect(SkRRect);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:15:native_transmutable!(SkRRect, RRect);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:17:impl PartialEq for RRect {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:19: unsafe { sb::C_SkRRect_Equals(self.native(), rhs.native()) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:23:impl Default for RRect {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:29:impl fmt::Debug for RRect {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:31: f.debug_struct("RRect")
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:47:impl AsRef<RRect> for RRect {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:48: fn as_ref(&self) -> &RRect {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:53:impl RRect {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:55: RRect::construct(|rr| unsafe { sb::C_SkRRect_Construct(rr) })
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:59: unsafe { sb::C_SkRRect_getType(self.native()) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:103: unsafe { sb::C_SkRRect_setRect(self.native_mut(), rect.as_ref().native()) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rs:272: unsafe { sb::C_SkRRect_dumpToString(self.native(), as_hex, str.native_mut()) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1275: pub fn encode_to_data_with_context(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1285: /// See [`Self::encode_to_data_with_quality`]
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1288: note = "Support for encoding GPU backed images without a context was removed, use `encode_to_data_with_context` instead"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1290: pub fn encode_to_data(&self, image_format: EncodedImageFormat) -> Option<Data> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1319: note = "Support for encoding GPU backed images without a context was removed, use `encode_to_data_with_context` instead"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1321: pub fn encode_to_data_with_quality(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:4: path, prelude::*, scalar, Matrix, Path, PathDirection, PathFillType, PathVerb, Point, RRect,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:766: /// Appends [`RRect`] to [`PathBuilder`], creating a new closed contour. If dir is [`PathDirection::CW`],
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:767: /// [`RRect`] winds clockwise. If dir is [`PathDirection::CCW`], [`RRect`] winds counterclockwise.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:769: /// After appending, [`PathBuilder`] may be empty, or may contain: [`Rect`], oval, or [`RRect`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:771: /// - `rect`: [`RRect`] to add
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:772: /// - `dir`: [`PathDirection`] to wind [`RRect`]
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:773: /// - `start_index`: index of initial point of [`RRect`]
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:779: rect: impl AsRef<RRect>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/path_builder.rs:790: self.native_mut().addRRect(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:14: Picture, Pixmap, Point, QuickReject, RRect, RSXform, Rect, Region, SamplingOptions, Shader,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1109: /// - `rrect` [`RRect`] to combine with clip
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1113: /// example: <https://fiddle.skia.org/c/@Canvas_clipRRect>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1116: rrect: impl AsRef<RRect>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1121: self.native_mut().clipRRect(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1403: /// Draws [`RRect`] rrect using clip, [`Matrix`], and [`Paint`] `paint`.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1410: /// - `rrect` [`RRect`] with up to eight corner radii to draw
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1413: /// example: <https://fiddle.skia.org/c/@Canvas_drawRRect>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1414: pub fn draw_rrect(&self, rrect: impl AsRef<RRect>, paint: &Paint) -> &Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1417: .drawRRect(rrect.as_ref().native(), paint.native())
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1422: /// Draws [`RRect`] outer and inner
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1425: /// In paint: [`crate::paint::Style`] determines if [`RRect`] is stroked or filled;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1427: /// If stroked and [`RRect`] corner has zero length radii, [`crate::paint::Join`] can
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1434: /// - `outer` [`RRect`] outer bounds to draw
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1435: /// - `inner` [`RRect`] inner bounds to draw
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1438: /// example: <https://fiddle.skia.org/c/@Canvas_drawDRRect_a>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1439: /// example: <https://fiddle.skia.org/c/@Canvas_drawDRRect_b>
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1442: outer: impl AsRef<RRect>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1443: inner: impl AsRef<RRect>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1447: self.native_mut().drawDRRect(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1539: /// Draws [`RRect`] bounded by [`Rect`] rect, with corner radii `(rx, ry)` using clip,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1542: /// In `paint`: [`crate::paint::Style`] determines if [`RRect`] is stroked or filled;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1546: /// If `rx` and `ry` are zero, [`RRect`] is drawn as [`Rect`] and if stroked is affected by
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1549: /// - `rect` [`Rect`] bounds of [`RRect`] to draw
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1572: /// In `paint`: [`crate::paint::Style`] determines if [`RRect`] is stroked or filled:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:1774: pub fn draw_str(
>sed -n '1,220p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_builder.rsExit code: 0
Wall time: 0 seconds
Output:
use std::{fmt, os::raw, ptr, str};
use skia_bindings as sb;
use super::{FontCollection, Paragraph, ParagraphStyle, PlaceholderStyle, TextStyle};
use crate::prelude::*;
pub type ParagraphBuilder = RefHandle<sb::skia_textlayout_ParagraphBuilder>;
unsafe_send_sync!(ParagraphBuilder);
impl NativeDrop for sb::skia_textlayout_ParagraphBuilder {
fn drop(&mut self) {
unsafe { sb::C_ParagraphBuilder_delete(self) }
}
}
impl fmt::Debug for ParagraphBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ParagraphBuilder").finish()
}
}
impl ParagraphBuilder {
pub fn push_style(&mut self, style: &TextStyle) -> &mut Self {
unsafe { sb::C_ParagraphBuilder_pushStyle(self.native_mut(), style.native()) }
self
}
pub fn pop(&mut self) -> &mut Self {
unsafe { sb::C_ParagraphBuilder_pop(self.native_mut()) }
self
}
pub fn peek_style(&mut self) -> TextStyle {
let mut ts = TextStyle::default();
unsafe { sb::C_ParagraphBuilder_peekStyle(self.native_mut(), ts.native_mut()) }
ts
}
pub fn add_text(&mut self, str: impl AsRef<str>) -> &mut Self {
let str = str.as_ref();
unsafe {
sb::C_ParagraphBuilder_addText(
self.native_mut(),
str.as_ptr() as *const raw::c_char,
str.len(),
)
}
self
}
pub fn add_placeholder(&mut self, placeholder_style: &PlaceholderStyle) -> &mut Self {
unsafe {
sb::C_ParagraphBuilder_addPlaceholder(self.native_mut(), placeholder_style.native())
}
self
}
pub fn build(&mut self) -> Paragraph {
Paragraph::from_ptr(unsafe { sb::C_ParagraphBuilder_Build(self.native_mut()) }).unwrap()
}
pub fn get_text(&mut self) -> &str {
unsafe {
let mut ptr = ptr::null_mut();
let mut len = 0;
sb::C_ParagraphBuilder_getText(self.native_mut(), &mut ptr, &mut len);
// ptr may indeed be `null` if there is no text.
str::from_utf8_unchecked(safer::from_raw_parts(ptr as *const u8, len))
}
}
pub fn get_paragraph_style(&self) -> ParagraphStyle {
ParagraphStyle::from_ptr(unsafe { sb::C_ParagraphBuilder_getParagraphStyle(self.native()) })
.unwrap()
}
// TODO: Wrap SetWords*, SetGraphemeBreaks*, setLineBreaks*, getClientICUData, setUnicode.
pub fn reset(&mut self) {
unsafe { sb::C_ParagraphBuilder_Reset(self.native_mut()) }
}
pub fn new(style: &ParagraphStyle, font_collection: impl Into<FontCollection>) -> Self {
#[cfg(feature = "embed-icudtl")]
crate::icu::init();
Self::from_ptr(unsafe {
sb::C_ParagraphBuilder_make(style.native(), font_collection.into().into_ptr())
})
.expect("Unicode initialization error")
}
}
>sed -n '1,220p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rsExit code: 0
Wall time: 0 seconds
Output:
use std::{ffi, fmt, ops::Range};
use skia_bindings as sb;
use super::{
LineMetrics, PositionWithAffinity, RectHeightStyle, RectWidthStyle, TextBox, TextDirection,
TextIndex, TextRange,
};
use crate::{
interop::{Sink, VecSink},
prelude::*,
scalar, Canvas, Font, GlyphId, Path, Point, Rect, Size, TextBlob, Unichar,
};
pub type Paragraph = RefHandle<sb::skia_textlayout_Paragraph>;
// <https://github.com/rust-skia/rust-skia/issues/537>
// unsafe_send_sync!(Paragraph);
impl NativeDrop for sb::skia_textlayout_Paragraph {
fn drop(&mut self) {
unsafe { sb::C_Paragraph_delete(self) }
}
}
impl fmt::Debug for Paragraph {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Paragraph")
.field("max_width", &self.max_width())
.field("height", &self.height())
.field("min_intrinsic_width", &self.min_intrinsic_width())
.field("max_intrinsic_width", &self.max_intrinsic_width())
.field("alphabetic_baseline", &self.alphabetic_baseline())
.field("ideographic_baseline", &self.ideographic_baseline())
.field("longest_line", &self.longest_line())
.field("did_exceed_max_lines", &self.did_exceed_max_lines())
.field("line_number", &self.line_number())
.finish()
}
}
impl Paragraph {
pub fn max_width(&self) -> scalar {
self.native().fWidth
}
pub fn height(&self) -> scalar {
self.native().fHeight
}
pub fn min_intrinsic_width(&self) -> scalar {
self.native().fMinIntrinsicWidth
}
pub fn max_intrinsic_width(&self) -> scalar {
self.native().fMaxIntrinsicWidth
}
pub fn alphabetic_baseline(&self) -> scalar {
self.native().fAlphabeticBaseline
}
pub fn ideographic_baseline(&self) -> scalar {
self.native().fIdeographicBaseline
}
pub fn longest_line(&self) -> scalar {
self.native().fLongestLine
}
pub fn did_exceed_max_lines(&self) -> bool {
self.native().fExceededMaxLines
}
pub fn layout(&mut self, width: scalar) {
unsafe { sb::C_Paragraph_layout(self.native_mut(), width) }
}
pub fn paint(&self, canvas: &Canvas, p: impl Into<Point>) {
let p = p.into();
unsafe { sb::C_Paragraph_paint(self.native_mut_force(), canvas.native_mut(), p.x, p.y) }
}
/// Returns a vector of bounding boxes that enclose all text between
/// start and end glyph indexes, including start and excluding end
pub fn get_rects_for_range(
&self,
range: Range<usize>,
rect_height_style: RectHeightStyle,
rect_width_style: RectWidthStyle,
) -> Vec<TextBox> {
let mut result: Vec<TextBox> = Vec::new();
let mut set_tb = |tbs: &[sb::skia_textlayout_TextBox]| {
result = tbs.iter().map(TextBox::from_native_ref).cloned().collect();
};
unsafe {
sb::C_Paragraph_getRectsForRange(
self.native_mut_force(),
range.start.try_into().unwrap(),
range.end.try_into().unwrap(),
rect_height_style.into_native(),
rect_width_style.into_native(),
VecSink::new(&mut set_tb).native_mut(),
);
}
result
}
pub fn get_rects_for_placeholders(&self) -> Vec<TextBox> {
let mut result = Vec::new();
let mut set_tb = |tbs: &[sb::skia_textlayout_TextBox]| {
result = tbs.iter().map(TextBox::from_native_ref).cloned().collect();
};
unsafe {
sb::C_Paragraph_getRectsForPlaceholders(
self.native_mut_force(),
VecSink::new(&mut set_tb).native_mut(),
)
}
result
}
/// Returns the index of the glyph that corresponds to the provided coordinate,
/// with the top left corner as the origin, and +y direction as down
pub fn get_glyph_position_at_coordinate(&self, p: impl Into<Point>) -> PositionWithAffinity {
let p = p.into();
let mut r = Default::default();
unsafe {
sb::C_Paragraph_getGlyphPositionAtCoordinate(self.native_mut_force(), p.x, p.y, &mut r)
}
r
}
/// Finds the first and last glyphs that define a word containing
/// the glyph at index offset
pub fn get_word_boundary(&self, offset: u32) -> Range<usize> {
let mut range: [usize; 2] = Default::default();
unsafe {
sb::C_Paragraph_getWordBoundary(self.native_mut_force(), offset, range.as_mut_ptr())
}
range[0]..range[1]
}
pub fn get_line_metrics(&self) -> Vec<LineMetrics> {
let mut result: Vec<LineMetrics> = Vec::new();
let mut set_lm = |lms: &[sb::skia_textlayout_LineMetrics]| {
result = lms.iter().map(LineMetrics::from_native_ref).collect();
};
unsafe {
sb::C_Paragraph_getLineMetrics(
self.native_mut_force(),
VecSink::new(&mut set_lm).native_mut(),
)
}
result
}
pub fn line_number(&self) -> usize {
unsafe { sb::C_Paragraph_lineNumber(self.native_mut_force()) }
}
pub fn mark_dirty(&mut self) {
unsafe { sb::C_Paragraph_markDirty(self.native_mut()) }
}
/// This function will return the number of unresolved glyphs or
/// `None` if not applicable (has not been shaped yet - valid case)
pub fn unresolved_glyphs(&mut self) -> Option<usize> {
unsafe { sb::C_Paragraph_unresolvedGlyphs(self.native_mut()) }
.try_into()
.ok()
}
pub fn unresolved_codepoints(&mut self) -> Vec<Unichar> {
let mut result = Vec::new();
let mut set_chars = |chars: &[Unichar]| {
result = chars.to_vec();
};
unsafe {
sb::C_Paragraph_unresolvedCodepoints(
self.native_mut_force(),
VecSink::new(&mut set_chars).native_mut(),
)
}
result
}
pub fn visit<'a, F>(&mut self, mut visitor: F)
where
F: FnMut(usize, Option<&'a VisitorInfo>),
{
unsafe {
sb::C_Paragraph_visit(
self.native_mut(),
&mut visitor as *mut F as *mut _,
Some(visitor_trampoline::<'a, F>),
);
}
unsafe extern "C" fn visitor_trampoline<'a, F: FnMut(usize, Option<&'a VisitorInfo>)>(
ctx: *mut ffi::c_void,
index: usize,
info: *const sb::skia_textlayout_Paragraph_VisitorInfo,
) {
let info = if info.is_null() {
None
} else {
Some(VisitorInfo::from_native_ref(&*info))
};
(*(ctx as *mut F))(index, info)
}
}
>sed -n '1,240p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/font_collection.rsExit code: 0
Wall time: 0 seconds
Output:
use crate::{
interop::{self, FromStrs, VecSink},
prelude::*,
textlayout::ParagraphCache,
FontMgr, FontStyle, Typeface, Unichar,
};
use skia_bindings::{self as sb, skia_textlayout_FontCollection};
use std::{ffi, fmt, ptr};
use super::FontArguments;
pub type FontCollection = RCHandle<skia_textlayout_FontCollection>;
impl NativeRefCountedBase for skia_textlayout_FontCollection {
type Base = sb::SkRefCntBase;
}
impl fmt::Debug for FontCollection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FontCollection")
.field("font_managers_count", &self.font_managers_count())
.field("fallback_manager", &self.fallback_manager())
.field("font_fallback_enabled", &self.font_fallback_enabled())
.field("paragraph_cache", &self.paragraph_cache())
.finish()
}
}
impl FontCollection {
pub fn new() -> Self {
Self::from_ptr(unsafe { sb::C_FontCollection_new() }).unwrap()
}
pub fn font_managers_count(&self) -> usize {
unsafe { self.native().getFontManagersCount() }
}
pub fn set_asset_font_manager(&mut self, font_manager: impl Into<Option<FontMgr>>) {
unsafe {
sb::C_FontCollection_setAssetFontManager(
self.native_mut(),
font_manager.into().into_ptr_or_null(),
)
}
}
pub fn set_dynamic_font_manager(&mut self, font_manager: impl Into<Option<FontMgr>>) {
unsafe {
sb::C_FontCollection_setDynamicFontManager(
self.native_mut(),
font_manager.into().into_ptr_or_null(),
)
}
}
pub fn set_test_font_manager(&mut self, font_manager: impl Into<Option<FontMgr>>) {
unsafe {
sb::C_FontCollection_setTestFontManager(
self.native_mut(),
font_manager.into().into_ptr_or_null(),
)
}
}
pub fn set_default_font_manager<'a>(
&mut self,
font_manager: impl Into<Option<FontMgr>>,
default_family_name: impl Into<Option<&'a str>>,
) {
let font_manager = font_manager.into();
unsafe {
match default_family_name.into() {
Some(name) => {
let name = ffi::CString::new(name).unwrap();
sb::C_FontCollection_setDefaultFontManager2(
self.native_mut(),
font_manager.into_ptr_or_null(),
name.as_ptr(),
)
}
None => sb::C_FontCollection_setDefaultFontManager(
self.native_mut(),
font_manager.into_ptr_or_null(),
),
}
}
}
pub fn set_default_font_manager_and_family_names(
&mut self,
font_manager: impl Into<Option<FontMgr>>,
family_names: &[impl AsRef<str>],
) {
let font_manager = font_manager.into();
let family_names = interop::Strings::from_strs(family_names);
unsafe {
sb::C_FontCollection_setDefaultFontManager3(
self.native_mut(),
font_manager.into_ptr_or_null(),
family_names.native(),
)
}
}
pub fn fallback_manager(&self) -> Option<FontMgr> {
FontMgr::from_ptr(unsafe { sb::C_FontCollection_getFallbackManager(self.native()) })
}
pub fn find_typefaces(
&mut self,
family_names: &[impl AsRef<str>],
font_style: FontStyle,
) -> Vec<Typeface> {
self.find_typefaces_with_font_arguments(family_names, font_style, None)
}
pub fn find_typefaces_with_font_arguments<'fa>(
&mut self,
family_names: &[impl AsRef<str>],
font_style: FontStyle,
font_args: impl Into<Option<&'fa FontArguments>>,
) -> Vec<Typeface> {
let family_names = interop::Strings::from_strs(family_names);
let mut typefaces: Vec<Typeface> = Vec::new();
let mut set_typefaces = |tfs: &mut [sb::sk_sp<sb::SkTypeface>]| {
typefaces = tfs
.iter_mut()
.filter_map(|sp| {
let ptr = sp.fPtr;
sp.fPtr = ptr::null_mut();
Typeface::from_ptr(ptr)
})
.collect()
};
unsafe {
sb::C_FontCollection_findTypefaces(
self.native_mut(),
family_names.native(),
font_style.into_native(),
font_args.into().native_ptr_or_null(),
VecSink::new_mut(&mut set_typefaces).native_mut(),
)
};
typefaces
}
pub fn default_fallback_char<'fa>(
&mut self,
unicode: Unichar,
font_style: FontStyle,
locale: impl AsRef<str>,
font_args: impl Into<Option<&'fa FontArguments>>,
) -> Option<Typeface> {
self.default_fallback_char_and_families(
unicode,
&[] as &[&str],
font_style,
locale,
font_args,
)
}
pub fn default_fallback_char_and_families<'fa>(
&mut self,
unicode: Unichar,
family_names: &[impl AsRef<str>],
font_style: FontStyle,
locale: impl AsRef<str>,
font_args: impl Into<Option<&'fa FontArguments>>,
) -> Option<Typeface> {
let family_names = interop::Strings::from_strs(family_names);
let locale = interop::String::from_str(locale.as_ref());
Typeface::from_ptr(unsafe {
sb::C_FontCollection_defaultFallback(
self.native_mut(),
unicode,
family_names.native(),
font_style.into_native(),
locale.native(),
font_args.into().native_ptr_or_null(),
)
})
}
pub fn default_fallback(&mut self) -> Option<Typeface> {
Typeface::from_ptr(unsafe { sb::C_FontCollection_defaultFallback2(self.native_mut()) })
}
pub fn default_emoji_fallback(
&mut self,
emoji_start: Unichar,
font_style: FontStyle,
locale: impl AsRef<str>,
) -> Option<Typeface> {
let locale = interop::String::from_str(locale.as_ref());
Typeface::from_ptr(unsafe {
sb::C_FontCollection_defaultEmojiFallback(
self.native_mut(),
emoji_start,
font_style.into_native(),
locale.native(),
)
})
}
pub fn disable_font_fallback(&mut self) {
unsafe { self.native_mut().disableFontFallback() }
}
pub fn enable_font_fallback(&mut self) {
unsafe { self.native_mut().enableFontFallback() }
}
pub fn font_fallback_enabled(&self) -> bool {
unsafe { sb::C_FontCollection_fontFallbackEnabled(self.native()) }
}
pub fn paragraph_cache(&self) -> &ParagraphCache {
ParagraphCache::from_native_ref(unsafe {
&*sb::C_FontCollection_paragraphCache(self.native_mut_force())
})
}
pub fn paragraph_cache_mut(&mut self) -> &mut ParagraphCache {
ParagraphCache::from_native_ref_mut(unsafe {
&mut *sb::C_FontCollection_paragraphCache(self.native_mut())
})
}
pub fn clear_caches(&mut self) {
unsafe { self.native_mut().clearCaches() }
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use crate::textlayout::FontCollection;
>rg -n "read_pixels\(|peek_pixels\(|Pixmap" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core -g '*.rs'Exit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:5:use skia_bindings::{self as sb, SkPixmap};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:9:pub struct Pixmap<'a> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:10: inner: Handle<SkPixmap>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:14:impl NativeDrop for SkPixmap {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:16: unsafe { sb::C_SkPixmap_destruct(self) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:20:impl Default for Pixmap<'_> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:22: Self::from_native_c(SkPixmap {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:30:impl fmt::Debug for Pixmap<'_> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:32: f.debug_struct("Pixmap")
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:39:impl<'pixels> Pixmap<'pixels> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:48: Some(Pixmap::from_native_c(SkPixmap {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:64: sb::C_SkPixmap_setColorSpace(self.native_mut(), color_space.into().into_ptr_or_null())
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:71: let mut pixmap = Pixmap::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:231: /// [`Pixel::matches_color_type()`] when matched against the [`ColorType`] of this Pixmap's
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:248: pub fn read_pixels_to_pixmap(&self, dst: &mut Pixmap, src: impl Into<IPoint>) -> bool {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:252: self.read_pixels(dst.info(), dst_bytes, dst.row_bytes(), src)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:255: pub fn scale_pixels(&self, dst: &mut Pixmap, sampling: impl Into<SamplingOptions>) -> bool {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:278: fn from_native_c(pixmap: SkPixmap) -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:286: pub(crate) fn from_native_ref(n: &SkPixmap) -> &Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:291: pub(crate) fn from_native_ptr(np: *const SkPixmap) -> *const Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:292: // Should be safe as long `Pixmap` is represented with repr(Transparent).
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:296: pub(crate) fn native_mut(&mut self) -> &mut SkPixmap {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:300: pub(crate) fn native(&self) -> &SkPixmap {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:305:/// Implement this trait to use a pixel type in [`Handle<Pixmap>::pixels()`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:310:/// [`ColorType`] or fail to match the alignment of the pixels stored in [`Handle<Pixmap>`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:395: let mut pixmap = Pixmap::new(&info, &mut pixels, info.min_row_bytes()).unwrap();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rs:404: let pixmap = Pixmap::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:7: ImageInfo, Matrix, Paint, PixelRef, Pixmap, SamplingOptions, Shader, TileMode,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:76: /// Returns a constant reference to the [`Pixmap`] holding the [`Bitmap`] pixel address, row
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:78: pub fn pixmap(&self) -> &Pixmap {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:79: Pixmap::from_native_ref(&self.native().fPixmap)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:455: // TODO: wrap installPixels with SkPixmap&
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:694: pub unsafe fn read_pixels(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:706: // TODO: read_pixels(Pixmap)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:707: // TODO: write_pixels(Pixmap)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:730: /// available, and returns `Some(Pixmap)`. If pixel address is not available, return `None`
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:734: pub fn peek_pixels(&self) -> Option<Pixmap> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/bitmap.rs:735: let mut pixmap = Pixmap::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:14: Picture, Pixmap, Point, QuickReject, RRect, RSXform, Rect, Region, SamplingOptions, Shader,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:294: /// To access pixels after drawing, call `flush()` or [`Self::peek_pixels()`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:330: /// To access pixels after drawing, call `flush()` or [`Self::peek_pixels()`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:579: /// Returns [`Pixmap`] if [`Canvas`] has direct access to pixels
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:582: pub fn peek_pixels(&self) -> Option<Pixmap> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:583: let mut pixmap = Pixmap::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:624: pub fn read_pixels(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:672: /// - [`Pixmap`] pixels could not be allocated.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rs:682: pub fn read_pixels_to_pixmap(&self, pixmap: &mut Pixmap, src: impl Into<IPoint>) -> bool {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image_generator.rs:3:use crate::{prelude::*, yuva_pixmap_info, Data, ImageInfo, Recorder, YUVAPixmapInfo};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image_generator.rs:61: // TODO: m86: get_pixels(&Pixmap)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image_generator.rs:66: ) -> Option<YUVAPixmapInfo> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image_generator.rs:67: YUVAPixmapInfo::new_if_valid(|info| unsafe {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:1:use crate::{prelude::*, ColorType, Data, ImageInfo, Pixmap, YUVAInfo, YUVColorSpace};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:2:use skia_bindings::{self as sb, SkYUVAPixmapInfo, SkYUVAPixmaps};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:10:/// [YUVAInfo] combined with per-plane [ColorType]s and row bytes. Fully specifies the [Pixmap]`s
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:12:pub type YUVAPixmapInfo = Handle<SkYUVAPixmapInfo>;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:13:unsafe_send_sync!(YUVAPixmapInfo);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:15:impl NativeDrop for SkYUVAPixmapInfo {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:17: unsafe { sb::C_SkYUVAPixmapInfo_destruct(self) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:21:impl NativePartialEq for SkYUVAPixmapInfo {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:23: unsafe { sb::C_SkYUVAPixmapInfo_equals(self, rhs) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:27:impl fmt::Debug for YUVAPixmapInfo {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:31: f.debug_struct("YUVAPixmapInfo")
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:40:impl YUVAPixmapInfo {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:44: /// Initializes the [YUVAPixmapInfo] from a [YUVAInfo] with per-plane color types and row bytes.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:78: SkYUVAPixmapInfo::new(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:104: let info = unsafe { SkYUVAPixmapInfo::new1(info.native(), data_type, row_bytes_ptr) };
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:117: /// The number of [Pixmap] planes.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:128: /// [YUVAPixmapInfo] is invalid.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:131: sb::C_SkYUVAPixmapInfo_rowBytes(self.native(), i.try_into().unwrap())
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:144: &*sb::C_SkYUVAPixmapInfo_planeInfo(self.native(), i.try_into().unwrap())
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:173: /// [YUVAPixmapInfo] not valid.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:178: ) -> Option<[Pixmap; Self::MAX_PLANES]> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:179: // Can't return a Vec<Pixmap> because Pixmaps can't be cloned.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:180: let mut pixmaps: [Pixmap; Self::MAX_PLANES] = Default::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:182: .initPixmapsFromSingleAllocation(memory, pixmaps[0].native_mut())
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:192: set_pixmap_info: impl Fn(&mut SkYUVAPixmapInfo) -> bool,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:197: .then(|| YUVAPixmapInfo::from_native_c(pixmap_info))
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:202: fn native_is_valid(info: *const SkYUVAPixmapInfo) -> bool {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:203: unsafe { sb::C_SkYUVAPixmapInfo_isValid(info) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:207: fn new_invalid() -> SkYUVAPixmapInfo {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:208: construct(|pi| unsafe { sb::C_SkYUVAPixmapInfo_Construct(pi) })
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:212:/// Helper to store [Pixmap] planes as described by a [YUVAPixmapInfo]. Can be responsible for
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:214:pub type YUVAPixmaps = Handle<SkYUVAPixmaps>;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:215:unsafe_send_sync!(YUVAPixmaps);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:217:impl NativeDrop for SkYUVAPixmaps {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:219: unsafe { sb::C_SkYUVAPixmaps_destruct(self) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:223:impl NativeClone for SkYUVAPixmaps {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:225: construct(|pixmaps| unsafe { sb::C_SkYUVAPixmaps_MakeCopy(self, pixmaps) })
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:229:impl fmt::Debug for YUVAPixmaps {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:231: f.debug_struct("YUVAPixmaps")
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:239:impl YUVAPixmaps {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:240: pub const MAX_PLANES: usize = YUVAPixmapInfo::MAX_PLANES;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:243: ColorType::from_native_c(unsafe { sb::SkYUVAPixmaps::RecommendedRGBAColorType(dt) })
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:246: /// Allocate space for pixmaps' pixels in the [YUVAPixmaps].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:247: pub fn allocate(info: &YUVAPixmapInfo) -> Option<Self> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:249: sb::C_SkYUVAPixmaps_Allocate(pixmaps, info.native());
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:255: /// [YUVAPixmaps].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:256: pub fn from_data(info: &YUVAPixmapInfo, data: impl Into<Data>) -> Option<Self> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:258: sb::C_SkYUVAPixmaps_FromData(pixmaps, info.native(), data.into().into_ptr());
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:265: /// [YUVAPixmapInfo::computeTotalBytes(&self)] allocated starting at memory.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:267: pub unsafe fn from_external_memory(info: &YUVAPixmapInfo, memory: *mut c_void) -> Option<Self> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:269: sb::C_SkYUVAPixmaps_FromExternalMemory(pixmaps, info.native(), memory);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:274: /// Wraps existing `Pixmap`s. The [YUVAPixmaps] will have no ownership of the [Pixmap]s' pixel
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:276: /// the [YUVAInfo] isn't compatible with the [Pixmap] array (number of planes, plane dimensions,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:281: pixmaps: &[Pixmap; Self::MAX_PLANES],
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:284: sb::C_SkYUVAPixmaps_FromExternalPixmaps(pms, info.native(), pixmaps[0].native());
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:297: pub fn pixmaps_info(&self) -> YUVAPixmapInfo {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:298: YUVAPixmapInfo::construct(|info| unsafe {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:299: sb::C_SkYUVAPixmaps_pixmapsInfo(self.native(), info)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:308: /// Access the [Pixmap] planes.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:309: pub fn planes(&self) -> &[Pixmap] {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:311: let planes = Pixmap::from_native_ptr(sb::C_SkYUVAPixmaps_planes(self.native()));
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:316: /// Get the ith [Pixmap] plane. `Pixmap` will be default initialized if i >= numPlanes.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:317: pub fn plane(&self, i: usize) -> &Pixmap {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:321: pub(crate) fn native_is_valid(pixmaps: *const SkYUVAPixmaps) -> bool {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:322: unsafe { sb::C_SkYUVAPixmaps_isValid(pixmaps) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:328: use skia_bindings::{self as sb, SkYUVAPixmapInfo_SupportedDataTypes};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:336: pub use skia_bindings::SkYUVAPixmapInfo_DataType as DataType;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:338: pub type SupportedDataTypes = Handle<SkYUVAPixmapInfo_SupportedDataTypes>;
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:341: impl NativeDrop for SkYUVAPixmapInfo_SupportedDataTypes {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:343: unsafe { sb::C_SkYUVAPixmapInfo_SupportedDataTypes_destruct(self) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:351: sb::C_SkYUVAPixmapInfo_SupportedDataTypes_Construct(sdt)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:367: Self::construct(|sdt| unsafe { sb::C_SkYUVAPixmapInfo_SupportedDataTypes_All(sdt) })
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:373: unsafe { sb::C_SkYUVAPixmapInfo_SupportedDataTypes_supported(self.native(), pc, dt) }
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:390: sb::C_SkYUVAPixmapInfo_DefaultColorTypeForDataType(dt, num_channels.try_into().unwrap())
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:401: sb::C_SkYUVAPixmapInfo_NumChannelsAndDataType(color_type.into_native(), &mut data_type)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:409: use crate::{ColorType, YUVAPixmaps};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/yuva_pixmaps.rs:414: YUVAPixmaps::recommended_rgba_color_type(super::DataType::Float16),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:6: gpu, prelude::*, Bitmap, Canvas, IPoint, IRect, ISize, Image, ImageInfo, Paint, Pixmap, Point,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:98: /// initialized. To access pixels after drawing, [`Surface::peek_pixels()`] or
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:99: /// [`Surface::read_pixels()`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:135: // TODO: WrapPixels(&Pixmap)
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:184: /// To access pixels after drawing, [`Self::peek_pixels()`] or [`Self::read_pixels()`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:753: pub fn peek_pixels(&mut self) -> Option<Pixmap> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:754: let mut pm = Pixmap::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:781: /// - [`Pixmap`] pixels could not be allocated.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:791: pub fn read_pixels_to_pixmap(&mut self, dst: &Pixmap, src: impl Into<IPoint>) -> bool {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:827: pub fn read_pixels(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:894: /// Copies [`crate::Rect`] of pixels from the src [`Pixmap`] to the [`Surface`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rs:908: pub fn write_pixels_from_pixmap(&mut self, src: &Pixmap, dst: impl Into<IPoint>) {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:3: IRect, ISize, ImageFilter, ImageGenerator, ImageInfo, Matrix, Paint, Picture, Pixmap, Recorder,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:167: // TODO: RasterFromPixmapCopy
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:168: // TODO: RasterFromPixmap
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:271:/// [`Image`] may be created from [`Bitmap`], [`Pixmap`], [`crate::Surface`], [`Picture`], encoded streams,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:583: pixmap: &Pixmap,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:625: pixmap: &Pixmap,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:698: /// Creates [`Image`] from [`crate::YUVAPixmaps`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:703: /// [`crate::YUVAPixmaps`] has a [`crate::YUVAInfo`] which specifies the transformation from YUV to RGB.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:710: /// [`crate::YUVAPixmaps`] does not need to remain valid after this returns.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:728: yuva_pixmaps: &crate::YUVAPixmaps,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:919: pub fn peek_pixels(&self) -> Option<Pixmap> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:920: let mut pixmap = Pixmap::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1134: /// - `dst` destination [`Pixmap`]:[`ImageInfo`], pixels, row bytes
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1144: dst: &Pixmap,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1195: dst: &Pixmap,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1230: /// - `dst` destination [`Pixmap`]:[`ImageInfo`], pixels, row bytes
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:1236: dst: &Pixmap,
>rg -n "draw_image_rect|SamplingOptions" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rsExit code: 0
Wall time: 0 seconds
Output:
14: Picture, Pixmap, Point, QuickReject, RRect, RSXform, Rect, Region, SamplingOptions, Shader,
146:/// [`Canvas::draw_image_rect()`] when there is any filtering. If kStrict is set, then extra code is
1594: self.draw_image_with_sampling_options(image, left_top, SamplingOptions::default(), paint)
1597: pub fn draw_image_rect(
1604: self.draw_image_rect_with_sampling_options(
1608: SamplingOptions::default(),
1617: sampling: impl Into<SamplingOptions>,
1633: pub fn draw_image_rect_with_sampling_options(
1638: sampling: impl Into<SamplingOptions>,
2091: /// * `sampling` - [`SamplingOptions`] used when sampling from the atlas image
2102: sampling: impl Into<SamplingOptions>,
>rg -n "from_encoded\(|new_copy\(" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/data.rsExit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/data.rs:73: pub fn new_copy(data: &[u8]) -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/data.rs:151: let d1 = Data::new_copy(x);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/data.rs:152: let d2 = Data::new_copy(x);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rs:365: pub fn from_encoded(data: impl Into<Data>) -> Option<Image> {
>sed -n '1,140p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/data.rsExit code: 0
Wall time: 0 seconds
Output:
use std::{
ffi::{CStr, CString},
fmt, io,
ops::Deref,
path::Path,
};
use skia_bindings::{self as sb, SkData};
use crate::{interop::RustStream, prelude::*};
pub type Data = RCHandle<SkData>;
unsafe_send_sync!(Data);
require_base_type!(SkData, sb::SkNVRefCnt);
impl NativeRefCounted for SkData {
fn _ref(&self) {
unsafe { sb::C_SkData_ref(self) }
}
fn _unref(&self) {
unsafe { sb::C_SkData_unref(self) }
}
fn unique(&self) -> bool {
unsafe { sb::C_SkData_unique(self) }
}
}
impl Deref for Data {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_bytes()
}
}
impl PartialEq for Data {
// Although there is an implementation in SkData for equality testing, we
// prefer to stay on the Rust side for that.
fn eq(&self, other: &Self) -> bool {
self.deref() == other.deref()
}
}
impl fmt::Debug for Data {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Data").field("size", &self.size()).finish()
}
}
impl Data {
pub fn size(&self) -> usize {
self.native().fSpan.fSize
}
pub fn is_empty(&self) -> bool {
self.size() == 0
}
pub fn as_bytes(&self) -> &[u8] {
unsafe { safer::from_raw_parts(self.native().fSpan.fPtr as _, self.size()) }
}
// TODO:
// pub unsafe fn writable_data(&mut self) -> &mut [u8]
pub fn copy_range(&self, offset: usize, buffer: &mut [u8]) -> &Self {
buffer.copy_from_slice(&self.as_bytes()[offset..offset + buffer.len()]);
self
}
// TODO: rename to copy_from() ? or from_bytes()?
pub fn new_copy(data: &[u8]) -> Self {
Data::from_ptr(unsafe { sb::C_SkData_MakeWithCopy(data.as_ptr() as _, data.len()) })
.unwrap()
}
/// Constructs Data from a given byte slice without copying it.
///
/// Users must make sure that the underlying slice will outlive the lifetime of the Data.
#[allow(clippy::missing_safety_doc)]
pub unsafe fn new_bytes(data: &[u8]) -> Self {
Data::from_ptr(sb::C_SkData_MakeWithoutCopy(data.as_ptr() as _, data.len())).unwrap()
}
#[allow(clippy::missing_safety_doc)]
pub unsafe fn new_uninitialized(length: usize) -> Data {
Data::from_ptr(sb::C_SkData_MakeUninitialized(length)).unwrap()
}
pub fn new_zero_initialized(length: usize) -> Data {
Data::from_ptr(unsafe { sb::C_SkData_MakeZeroInitialized(length) }).unwrap()
}
// TODO: use Range as stand in for offset / length?
pub fn new_subset(data: &Data, offset: usize, length: usize) -> Data {
Data::from_ptr(unsafe { sb::C_SkData_MakeSubset(data.native(), offset, length) }).unwrap()
}
/// Constructs Data from a copy of a &str.
///
/// Functions that use `Data` as a string container usually expect it to contain a c-string
/// including the terminating 0 byte, so this function converts the Rust `str` to a `CString`
/// and calls [`Self::new_cstr()`].
pub fn new_str(str: impl AsRef<str>) -> Data {
Self::new_cstr(&CString::new(str.as_ref()).unwrap())
}
/// Constructs Data from a &CStr by copying its contents.
pub fn new_cstr(cstr: &CStr) -> Data {
Data::from_ptr(unsafe { sb::C_SkData_MakeWithCString(cstr.as_ptr()) }).unwrap()
}
/// Create a new `Data` referencing the file with the specified path. If the file cannot be
/// opened, the path contains 0 bytes, or the path is not valid UTF-8, this returns `None`.
///
/// This function opens the file as a memory mapped file for the lifetime of `Data` returned.
pub fn from_filename(path: impl AsRef<Path>) -> Option<Self> {
let path = CString::new(path.as_ref().to_str()?).ok()?;
Data::from_ptr(unsafe { sb::C_SkData_MakeFromFileName(path.as_ptr()) })
}
// TODO: MakeFromFile (is there a way to wrap this safely?)
/// Attempt to read size bytes into a [`Data`]. If the read succeeds, return the data,
/// else return `None`. Either way the stream's cursor may have been changed as a result
/// of calling read().
pub fn from_stream(mut stream: impl io::Read, size: usize) -> Option<Self> {
let mut stream = RustStream::new(&mut stream);
Data::from_ptr(unsafe { sb::C_SkData_MakeFromStream(stream.stream_mut(), size) })
}
pub fn new_empty() -> Self {
Data::from_ptr(unsafe { sb::C_SkData_MakeEmpty() }).unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
>sed -n '140,240p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image.rsExit code: 0
Wall time: 0 seconds
Output:
/// * `bit_depth` - 8-bit integer or 16-bit float: per component
/// * `color_space` - range of colors; may be `None`
/// * `props` - props to use when rasterizing the picture
///
/// Returns: created [`Image`], or `None`
pub fn deferred_from_picture(
picture: impl Into<Picture>,
dimensions: impl Into<ISize>,
matrix: Option<&Matrix>,
paint: Option<&Paint>,
bit_depth: BitDepth,
color_space: impl Into<Option<ColorSpace>>,
props: impl Into<Option<SurfaceProps>>,
) -> Option<Image> {
Image::from_ptr(unsafe {
sb::C_SkImages_DeferredFromPicture(
picture.into().into_ptr(),
dimensions.into().native(),
matrix.native_ptr_or_null(),
paint.native_ptr_or_null(),
bit_depth,
color_space.into().into_ptr_or_null(),
props.into().unwrap_or_default().native(),
)
})
}
// TODO: RasterFromPixmapCopy
// TODO: RasterFromPixmap
/// Creates CPU-backed [`Image`] from pixel data described by info.
/// The pixels data will *not* be copied.
///
/// [`Image`] is returned if [`ImageInfo`] is valid. Valid [`ImageInfo`] parameters include:
/// dimensions are greater than zero;
/// each dimension fits in 29 bits;
/// [`ColorType`] and [`AlphaType`] are valid, and [`ColorType`] is not [`ColorType::Unknown`];
/// `row_bytes` are large enough to hold one row of pixels;
/// pixels is not `None`, and contains enough data for [`Image`].
///
/// * `info` - contains width, height, [`AlphaType`], [`ColorType`], [`ColorSpace`]
/// * `pixels` - address or pixel storage
/// * `row_bytes` - size of pixel row or larger
///
/// Returns: [`Image`] sharing pixels, or `None`
pub fn raster_from_data(
info: &ImageInfo,
pixels: impl Into<Data>,
row_bytes: usize,
) -> Option<Image> {
Image::from_ptr(unsafe {
sb::C_SkImages_RasterFromData(info.native(), pixels.into().into_ptr(), row_bytes)
})
}
/// Creates a filtered [`Image`] on the CPU. filter processes the src image, potentially
/// changing the color, position, and size. subset is the bounds of src that are processed by
/// filter. `clip_bounds` is the expected bounds of the filtered [`Image`]. `out_subset` is
/// required storage for the actual bounds of the filtered [`Image`]. `offset` is required
/// storage for translation of returned [`Image`].
///
/// Returns `None` a filtered result could not be created.
///
/// Useful for animation of [`ImageFilter`] that varies size from frame to frame. `out_subset`
/// describes the valid bounds of returned image. offset translates the returned [`Image`] to
/// keep subsequent animation frames aligned with respect to each other.
///
/// * `src` - the image to be filtered
/// * `filter` - the image filter to be applied
/// * `subset` - bounds of [`Image`] processed by filter
/// * `clip_bounds` - expected bounds of filtered [`Image`]
///
/// Returns filtered SkImage, or `None`:
/// * `out_subset` - storage for returned [`Image`] bounds
/// * `offset` - storage for returned [`Image`] translation Returns: filtered [`Image`], or
/// `None`
pub fn make_with_filter(
image: impl Into<Image>,
image_filter: &ImageFilter,
subset: impl AsRef<IRect>,
clip_bounds: impl AsRef<IRect>,
) -> Option<(Image, IRect, IPoint)> {
let mut out_subset = IRect::default();
let mut offset = IPoint::default();
unsafe {
Image::from_ptr(sb::C_SkImages_MakeWithFilter(
image.into().into_ptr(),
image_filter.native(),
subset.as_ref().native(),
clip_bounds.as_ref().native(),
out_subset.native_mut(),
offset.native_mut(),
))
}
.map(|i| (i, out_subset, offset));
None
}
}
/// CachingHint selects whether Skia may internally cache [`Bitmap`] generated by
>sed -n '820,870p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/surface.rsExit code: 0
Wall time: 0 seconds
Output:
/// * `dst_info` - width, height, [`crate::ColorType`], and [`crate::AlphaType`] of `dst_pixels`
/// * `dst_pixels` - storage for pixels; `dst_info.height()` times `dst_row_bytes`, or larger
/// * `dst_row_bytes` - size of one destination row; `dst_info.width()` times pixel size, or larger
/// * `src.x` - offset into readable pixels on x-axis; may be negative
/// * `src.y` - offset into readable pixels on y-axis; may be negative
///
/// Returns: `true` if pixels were copied
pub fn read_pixels(
&mut self,
dst_info: &ImageInfo,
dst_pixels: &mut [u8],
dst_row_bytes: usize,
src: impl Into<IPoint>,
) -> bool {
if !dst_info.valid_pixels(dst_row_bytes, dst_pixels) {
return false;
}
let src = src.into();
unsafe {
self.native_mut().readPixels1(
dst_info.native(),
dst_pixels.as_mut_ptr() as _,
dst_row_bytes,
src.x,
src.y,
)
}
}
// TODO: why is self mut?
// TODO: why is Bitmap immutable?
/// Copies [`crate::Rect`] of pixels from [`Surface`] into bitmap.
///
/// Source [`crate::Rect`] corners are (`src.x`, `src.y`) and [`Surface`] (width(), height()).
/// Destination [`crate::Rect`] corners are `(0, 0)` and `(bitmap.width(), bitmap.height())`.
/// Copies each readable pixel intersecting both rectangles, without scaling,
/// converting to `bitmap.color_type()` and `bitmap.alpha_type()` if required.
///
/// Pixels are readable when [`Surface`] is raster, or backed by a Ganesh GPU backend. Graphite
/// has deprecated this API in favor of the equivalent asynchronous API on
/// `skgpu::graphite::Context` (with an optional explicit synchonization).
///
/// The destination pixel storage must be allocated by the caller.
///
/// Pixel values are converted only if [`crate::ColorType`] and [`crate::AlphaType`]
/// do not match. Only pixels within both source and destination rectangles
/// are copied. dst contents outside [`crate::Rect`] intersection are unchanged.
///
/// Pass negative values for `src.x` or `src.y` to offset pixels across or down destination.
///
>sed -n '39,90p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/pixmap.rsExit code: 0
Wall time: 0 seconds
Output:
impl<'pixels> Pixmap<'pixels> {
pub fn new(info: &ImageInfo, pixels: &'pixels mut [u8], row_bytes: usize) -> Option<Self> {
if row_bytes < info.min_row_bytes() {
return None;
}
if pixels.len() < info.compute_byte_size(row_bytes) {
return None;
}
Some(Pixmap::from_native_c(SkPixmap {
fPixels: pixels.as_mut_ptr() as _,
fRowBytes: row_bytes,
fInfo: info.native().clone(),
}))
}
pub fn reset(&mut self) -> &mut Self {
unsafe { self.native_mut().reset() }
self
}
// TODO: reset() function that re-borrows pixels?
pub fn set_color_space(&mut self, color_space: impl Into<Option<ColorSpace>>) -> &mut Self {
unsafe {
sb::C_SkPixmap_setColorSpace(self.native_mut(), color_space.into().into_ptr_or_null())
}
self
}
#[must_use]
pub fn extract_subset(&self, area: impl AsRef<IRect>) -> Option<Self> {
let mut pixmap = Pixmap::default();
unsafe {
self.native()
.extractSubset(pixmap.native_mut(), area.as_ref().native())
}
.then_some(pixmap)
}
pub fn info(&self) -> &ImageInfo {
ImageInfo::from_native_ref(&self.native().fInfo)
}
pub fn row_bytes(&self) -> usize {
self.native().fRowBytes
}
pub fn addr(&self) -> *const c_void {
self.native().fPixels
}
I’m laying down the API and test targets before filling in behavior. The first test set is focused on the hot path you care about: compile once, substitute params, compute layout with absolute positioning, render deterministic pixels, and fan out work through a pool.
The red suite is in place. I’m running it now to surface the real compile and behavior gaps, then I’ll close them in the core crate before the first commit.
>cargo test -p taffy-canvas-coreExit code: 124
Wall time: 120 seconds
Output:
command timed out after 120018 milliseconds
Updating crates.io index
Locking 142 packages to latest Rust 1.92.0 compatible versions
Adding criterion v0.7.0 (available: v0.8.2)
Adding quick-xml v0.38.4 (available: v0.39.2)
Downloading crates ...
Downloaded anstyle v1.0.14
Downloaded anyhow v1.0.102
Downloaded itoa v1.0.18
Downloaded ciborium-ll v0.2.2
Downloaded anes v0.1.6
Downloaded plotters-backend v0.3.7
Downloaded cast v0.3.0
Downloaded cssparser-macros v0.7.0
Downloaded clap_lex v1.1.0
Downloaded ciborium-io v0.2.2
Downloaded plotters-svg v0.3.7
Downloaded arrayvec v0.7.6
Downloaded rustc-hash v2.1.2
Downloaded filetime v0.2.27
Downloaded criterion-plot v0.6.0
Downloaded oorandom v11.1.5
Downloaded toml_writer v1.1.1+spec-1.1.0
Downloaded thiserror-impl v2.0.18
Downloaded thiserror v2.0.18
Downloaded quote v1.0.45
Downloaded grid v1.0.0
Downloaded simd-adler32 v0.3.9
Downloaded tinytemplate v1.2.1
Downloaded toml_datetime v1.1.1+spec-1.1.0
Downloaded serde_spanned v1.1.1
Downloaded ciborium v0.2.2
Downloaded once_cell v1.21.4
Downloaded zmij v1.0.21
Downloaded toml_parser v1.1.2+spec-1.1.0
Downloaded cssparser v0.37.0
Downloaded proc-macro2 v1.0.106
Downloaded clap v4.6.0
Downloaded unicode-ident v1.0.24
Downloaded tar v0.4.45
Downloaded toml v1.1.2+spec-1.1.0
Downloaded slotmap v1.1.1
Downloaded bitflags v2.11.0
Downloaded zerocopy-derive v0.8.48
Downloaded skia-bindings v0.93.1
Downloaded indexmap v2.14.0
Downloaded criterion v0.7.0
Downloaded flate2 v1.1.9
Downloaded regex v1.12.3
Downloaded winnow v1.0.1
Downloaded hashbrown v0.17.0
Downloaded plotters v0.3.7
Downloaded clap_builder v4.6.0
Downloaded zerocopy v0.8.48
Downloaded memchr v2.8.0
Downloaded cc v1.2.59
Downloaded rustix v1.1.4
Downloaded regex-syntax v0.8.10
Downloaded regex-automata v0.4.14
Downloaded libc v0.2.184
Compiling proc-macro2 v1.0.106
Compiling unicode-ident v1.0.24
Compiling quote v1.0.45
Compiling cfg-if v1.0.4
Compiling libc v0.2.184
Compiling memchr v2.8.0
Compiling regex-syntax v0.8.10
Compiling zmij v1.0.21
Compiling itoa v1.0.18
Compiling serde_core v1.0.228
Compiling glob v0.3.3
Compiling serde_json v1.0.149
Compiling prettyplease v0.2.37
Compiling bitflags v2.11.0
Compiling clang-sys v1.8.1
Compiling rustix v1.1.4
Compiling aho-corasick v1.1.4
Compiling crossbeam-utils v0.8.21
Compiling crc32fast v1.5.0
Compiling minimal-lexical v0.2.1
Compiling nom v7.1.3
Compiling errno v0.3.14
Compiling regex-automata v0.4.14
Compiling libloading v0.8.9
Compiling either v1.15.0
Compiling shlex v1.3.0
Compiling syn v2.0.117
Compiling serde v1.0.228
Compiling adler2 v2.0.1
Compiling winnow v1.0.1
Compiling simd-adler32 v0.3.9
Compiling bindgen v0.72.1
Compiling toml_parser v1.1.2+spec-1.1.0
Compiling miniz_oxide v0.8.9
Compiling toml_datetime v1.1.1+spec-1.1.0
Compiling serde_spanned v1.1.1
Compiling regex v1.12.3
Compiling cexpr v0.6.0
Compiling itertools v0.13.0
Compiling filetime v0.2.27
Compiling toml_writer v1.1.1+spec-1.1.0
Compiling rustc-hash v2.1.2
Compiling zerocopy v0.8.48
Compiling find-msvc-tools v0.1.9
Compiling xattr v1.6.1
Compiling log v0.4.29
Compiling tar v0.4.45
Compiling cc v1.2.59
Compiling toml v1.1.2+spec-1.1.0
Compiling crossbeam-epoch v0.9.18
Compiling flate2 v1.1.9
Compiling heck v0.5.0
Compiling autocfg v1.5.0
Compiling pkg-config v0.3.32
Compiling rayon-core v1.13.0
Compiling version_check v0.9.5
Compiling num-traits v0.2.19
Compiling crossbeam-deque v0.8.6
Compiling slotmap v1.1.1
Compiling dtoa v1.0.11
Compiling dtoa-short v0.3.5
Compiling anstyle v1.0.14
Compiling ciborium-io v0.2.2
Compiling plotters-backend v0.3.7
Compiling clap_lex v1.1.0
Compiling thiserror v2.0.18
Compiling anyhow v1.0.102
Compiling smallvec v1.15.1
Compiling plotters-svg v0.3.7
Compiling clap_builder v4.6.0
Compiling rayon v1.11.0
Compiling cast v0.3.0
Compiling same-file v1.0.6
Compiling hashbrown v0.17.0
Compiling grid v1.0.0
Compiling arrayvec v0.7.6
Compiling equivalent v1.0.2
Compiling walkdir v2.5.0
Compiling plotters v0.3.7
Compiling serde_derive v1.0.228
Compiling zerocopy-derive v0.8.48
Compiling cssparser-macros v0.7.0
Compiling thiserror-impl v2.0.18
Compiling cssparser v0.37.0
Compiling criterion-plot v0.6.0
Compiling clap v4.6.0
Compiling indexmap v2.14.0
Compiling oorandom v11.1.5
Compiling base64 v0.22.1
Compiling anes v0.1.6
Compiling taffy v0.10.0
Compiling once_cell v1.21.4
Compiling tinytemplate v1.2.1
Compiling quick-xml v0.38.4
Compiling skia-bindings v0.93.1
Compiling half v2.7.1
Compiling ciborium-ll v0.2.2
Compiling ciborium v0.2.2
Compiling criterion v0.7.0
>git status --shortExit code: 0
Wall time: 0 seconds
Output:
?? .gitignore
?? Cargo.toml
?? crates/
The dependency build is still chewing through rust-skia, but I can already clean a few obvious compile issues in parallel so the next test run is signal rather than noise.
>rg -n "pub struct Style" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style -g '*.rs'Exit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/mod.rs:430:pub struct Style<S: CheapCloneStr = DefaultCheapStr> {
>sed -n '1,260p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/mod.rsExit code: 0
Wall time: 0 seconds
Output:
//! A typed representation of [CSS style properties](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) in Rust. Used as input to layout computation.
mod alignment;
mod available_space;
mod compact_length;
mod dimension;
#[cfg(feature = "block_layout")]
mod block;
#[cfg(feature = "flexbox")]
mod flex;
#[cfg(feature = "float_layout")]
mod float;
#[cfg(feature = "grid")]
mod grid;
pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
pub use self::available_space::AvailableSpace;
pub use self::compact_length::CompactLength;
pub use self::dimension::{Dimension, LengthPercentage, LengthPercentageAuto};
use crate::sys::DefaultCheapStr;
#[cfg(feature = "block_layout")]
pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign};
#[cfg(feature = "flexbox")]
pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};
#[cfg(feature = "float_layout")]
pub use self::float::{Clear, Float, FloatDirection};
#[cfg(feature = "grid")]
pub use self::grid::{
GenericGridPlacement, GenericGridTemplateComponent, GenericRepetition, GridAutoFlow, GridAutoTracks,
GridContainerStyle, GridItemStyle, GridPlacement, GridTemplateComponent, GridTemplateRepetition,
GridTemplateTracks, MaxTrackSizingFunction, MinTrackSizingFunction, RepetitionCount, TrackSizingFunction,
};
#[cfg(feature = "grid")]
pub(crate) use self::grid::{GridAreaAxis, GridAreaEnd};
#[cfg(feature = "grid")]
pub use self::grid::{GridTemplateArea, NamedGridLine, TemplateLineNames};
#[cfg(feature = "grid")]
pub(crate) use self::grid::{NonNamedGridPlacement, OriginZeroGridPlacement};
use crate::geometry::{Point, Rect, Size};
use crate::style_helpers::TaffyAuto as _;
use core::fmt::Debug;
#[cfg(feature = "grid")]
use crate::geometry::Line;
#[cfg(feature = "serde")]
use crate::style_helpers;
#[cfg(feature = "grid")]
use crate::util::sys::GridTrackVec;
use crate::sys::String;
/// Trait that represents a cheaply clonable string. If you're unsure what to use here
/// consider `Arc<str>` or `string_cache::Atom`.
#[cfg(any(feature = "alloc", feature = "std"))]
pub trait CheapCloneStr:
AsRef<str> + for<'a> From<&'a str> + From<String> + PartialEq + Eq + Clone + Default + Debug + 'static
{
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl<T> CheapCloneStr for T where
T: AsRef<str> + for<'a> From<&'a str> + From<String> + PartialEq + Eq + Clone + Default + Debug + 'static
{
}
/// Trait that represents a cheaply clonable string. If you're unsure what to use here
/// consider `Arc<str>` or `string_cache::Atom`.
#[cfg(not(any(feature = "alloc", feature = "std")))]
pub trait CheapCloneStr {}
#[cfg(not(any(feature = "alloc", feature = "std")))]
impl<T> CheapCloneStr for T {}
/// The core set of styles that are shared between all CSS layout nodes
///
/// Note that all methods come with a default implementation which simply returns the default value for that style property
/// but this is a just a convenience to save on boilerplate for styles that your implementation doesn't support. You will need
/// to override the default implementation for each style property that your style type actually supports.
pub trait CoreStyle {
/// The type of custom identifiers used to identify named grid lines and areas
type CustomIdent: CheapCloneStr;
/// Which box generation mode should be used
#[inline(always)]
fn box_generation_mode(&self) -> BoxGenerationMode {
BoxGenerationMode::DEFAULT
}
/// Is block layout?
#[inline(always)]
fn is_block(&self) -> bool {
false
}
/// Is it a compressible replaced element?
/// <https://drafts.csswg.org/css-sizing-3/#min-content-zero>
#[inline(always)]
fn is_compressible_replaced(&self) -> bool {
false
}
/// Which box do size styles apply to
#[inline(always)]
fn box_sizing(&self) -> BoxSizing {
BoxSizing::BorderBox
}
/// The direction of text, table and grid columns, and horizontal overflow.
#[inline(always)]
fn direction(&self) -> Direction {
Direction::Ltr
}
// Overflow properties
/// How children overflowing their container should affect layout
#[inline(always)]
fn overflow(&self) -> Point<Overflow> {
Style::<Self::CustomIdent>::DEFAULT.overflow
}
/// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
#[inline(always)]
fn scrollbar_width(&self) -> f32 {
0.0
}
// Position properties
/// What should the `position` value of this struct use as a base offset?
#[inline(always)]
fn position(&self) -> Position {
Style::<Self::CustomIdent>::DEFAULT.position
}
/// How should the position of this element be tweaked relative to the layout defined?
#[inline(always)]
fn inset(&self) -> Rect<LengthPercentageAuto> {
Style::<Self::CustomIdent>::DEFAULT.inset
}
// Size properies
/// Sets the initial size of the item
#[inline(always)]
fn size(&self) -> Size<Dimension> {
Style::<Self::CustomIdent>::DEFAULT.size
}
/// Controls the minimum size of the item
#[inline(always)]
fn min_size(&self) -> Size<Dimension> {
Style::<Self::CustomIdent>::DEFAULT.min_size
}
/// Controls the maximum size of the item
#[inline(always)]
fn max_size(&self) -> Size<Dimension> {
Style::<Self::CustomIdent>::DEFAULT.max_size
}
/// Sets the preferred aspect ratio for the item
/// The ratio is calculated as width divided by height.
#[inline(always)]
fn aspect_ratio(&self) -> Option<f32> {
Style::<Self::CustomIdent>::DEFAULT.aspect_ratio
}
// Spacing Properties
/// How large should the margin be on each side?
#[inline(always)]
fn margin(&self) -> Rect<LengthPercentageAuto> {
Style::<Self::CustomIdent>::DEFAULT.margin
}
/// How large should the padding be on each side?
#[inline(always)]
fn padding(&self) -> Rect<LengthPercentage> {
Style::<Self::CustomIdent>::DEFAULT.padding
}
/// How large should the border be on each side?
#[inline(always)]
fn border(&self) -> Rect<LengthPercentage> {
Style::<Self::CustomIdent>::DEFAULT.border
}
}
/// Sets the layout used for the children of this node
///
/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Display {
/// The children will follow the block layout algorithm
#[cfg(feature = "block_layout")]
Block,
/// The children will follow the flexbox layout algorithm
#[cfg(feature = "flexbox")]
Flex,
/// The children will follow the CSS Grid layout algorithm
#[cfg(feature = "grid")]
Grid,
/// The node is hidden, and it's children will also be hidden
None,
}
impl Display {
/// The default Display mode
#[cfg(feature = "flexbox")]
pub const DEFAULT: Display = Display::Flex;
/// The default Display mode
#[cfg(all(feature = "grid", not(feature = "flexbox")))]
pub const DEFAULT: Display = Display::Grid;
/// The default Display mode
#[cfg(all(feature = "block_layout", not(feature = "flexbox"), not(feature = "grid")))]
pub const DEFAULT: Display = Display::Block;
/// The default Display mode
#[cfg(all(not(feature = "flexbox"), not(feature = "grid"), not(feature = "block_layout")))]
pub const DEFAULT: Display = Display::None;
}
impl Default for Display {
fn default() -> Self {
Self::DEFAULT
}
}
#[cfg(feature = "parse")]
crate::util::parse::impl_parse_for_keyword_enum!(Display,
"none" => None,
#[cfg(feature = "flexbox")]
"flex" => Flex,
#[cfg(feature = "grid")]
"grid" => Grid,
#[cfg(feature = "block_layout")]
"block" => Block,
);
impl core::fmt::Display for Display {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Display::None => write!(f, "NONE"),
#[cfg(feature = "block_layout")]
Display::Block => write!(f, "BLOCK"),
#[cfg(feature = "flexbox")]
Display::Flex => write!(f, "FLEX"),
#[cfg(feature = "grid")]
Display::Grid => write!(f, "GRID"),
}
}
}
/// An abstracted version of the CSS `display` property where any value other than "none" is represented by "normal"
/// See: <https://www.w3.org/TR/css-display-3/#box-generation>
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum BoxGenerationMode {
/// The node generates a box in the regular way
Normal,
/// The node and it's descendants generate no boxes (they are hidden)
None,
}
impl BoxGenerationMode {
/// The default of BoxGenerationMode
pub const DEFAULT: BoxGenerationMode = BoxGenerationMode::Normal;
}
impl Default for BoxGenerationMode {
>sed -n '1,240p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/style.rsExit code: 1
Wall time: 0 seconds
Output:
sed: /Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/style.rs: No such file or directory
>rg -n "pub enum Position|pub enum FlexDirection|pub enum AlignItems|pub enum JustifyContent|pub enum LengthPercentageAuto|pub enum Dimension" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style -g '*.rs'Exit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/flex.rs:108:pub enum FlexDirection {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/mod.rs:277:pub enum Position {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/alignment.rs:10:pub enum AlignItems {
>sed -n '430,620p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/mod.rsExit code: 0
Wall time: 0 seconds
Output:
pub struct Style<S: CheapCloneStr = DefaultCheapStr> {
/// This is a dummy field which is necessary to make Taffy compile with the `grid` feature disabled
/// It should always be set to `core::marker::PhantomData`.
pub dummy: core::marker::PhantomData<S>,
/// What layout strategy should be used?
pub display: Display,
/// Whether a child is display:table or not. This affects children of block layouts.
/// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented
pub item_is_table: bool,
/// Is it a replaced element like an image or form field?
/// <https://drafts.csswg.org/css-sizing-3/#min-content-zero>
pub item_is_replaced: bool,
/// Should size styles apply to the content box or the border box of the node
pub box_sizing: BoxSizing,
/// Sets the direction of text, table and grid columns, and horizontal overflow.
pub direction: Direction,
// Overflow properties
/// How children overflowing their container should affect layout
pub overflow: Point<Overflow>,
/// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
pub scrollbar_width: f32,
#[cfg(feature = "float_layout")]
/// Should the box be floated
pub float: Float,
#[cfg(feature = "float_layout")]
/// Should the box clear floats
pub clear: Clear,
// Position properties
/// What should the `position` value of this struct use as a base offset?
pub position: Position,
/// How should the position of this element be tweaked relative to the layout defined?
#[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
pub inset: Rect<LengthPercentageAuto>,
// Size properties
/// Sets the initial size of the item
#[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
pub size: Size<Dimension>,
/// Controls the minimum size of the item
#[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
pub min_size: Size<Dimension>,
/// Controls the maximum size of the item
#[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
pub max_size: Size<Dimension>,
/// Sets the preferred aspect ratio for the item
///
/// The ratio is calculated as width divided by height.
pub aspect_ratio: Option<f32>,
// Spacing Properties
/// How large should the margin be on each side?
#[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
pub margin: Rect<LengthPercentageAuto>,
/// How large should the padding be on each side?
#[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
pub padding: Rect<LengthPercentage>,
/// How large should the border be on each side?
#[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
pub border: Rect<LengthPercentage>,
// Alignment properties
/// How this node's children aligned in the cross/block axis?
#[cfg(any(feature = "flexbox", feature = "grid"))]
pub align_items: Option<AlignItems>,
/// How this node should be aligned in the cross/block axis
/// Falls back to the parents [`AlignItems`] if not set
#[cfg(any(feature = "flexbox", feature = "grid"))]
pub align_self: Option<AlignSelf>,
/// How this node's children should be aligned in the inline axis
#[cfg(feature = "grid")]
pub justify_items: Option<AlignItems>,
/// How this node should be aligned in the inline axis
/// Falls back to the parents [`JustifyItems`] if not set
#[cfg(feature = "grid")]
pub justify_self: Option<AlignSelf>,
/// How should content contained within this item be aligned in the cross/block axis
#[cfg(any(feature = "flexbox", feature = "grid"))]
pub align_content: Option<AlignContent>,
/// How should content contained within this item be aligned in the main/inline axis
#[cfg(any(feature = "flexbox", feature = "grid"))]
pub justify_content: Option<JustifyContent>,
/// How large should the gaps between items in a grid or flex container be?
#[cfg(any(feature = "flexbox", feature = "grid"))]
#[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
pub gap: Size<LengthPercentage>,
// Block container properties
/// How items elements should aligned in the inline axis
#[cfg(feature = "block_layout")]
pub text_align: TextAlign,
// Flexbox container properties
/// Which direction does the main axis flow in?
#[cfg(feature = "flexbox")]
pub flex_direction: FlexDirection,
/// Should elements wrap, or stay in a single line?
#[cfg(feature = "flexbox")]
pub flex_wrap: FlexWrap,
// Flexbox item properties
/// Sets the initial main axis size of the item
#[cfg(feature = "flexbox")]
pub flex_basis: Dimension,
/// The relative rate at which this item grows when it is expanding to fill space
///
/// 0.0 is the default value, and this value must be positive.
#[cfg(feature = "flexbox")]
pub flex_grow: f32,
/// The relative rate at which this item shrinks when it is contracting to fit into space
///
/// 1.0 is the default value, and this value must be positive.
#[cfg(feature = "flexbox")]
pub flex_shrink: f32,
// Grid container properies
/// Defines the track sizing functions (heights) of the grid rows
#[cfg(feature = "grid")]
pub grid_template_rows: GridTrackVec<GridTemplateComponent<S>>,
/// Defines the track sizing functions (widths) of the grid columns
#[cfg(feature = "grid")]
pub grid_template_columns: GridTrackVec<GridTemplateComponent<S>>,
/// Defines the size of implicitly created rows
#[cfg(feature = "grid")]
pub grid_auto_rows: GridTrackVec<TrackSizingFunction>,
/// Defined the size of implicitly created columns
#[cfg(feature = "grid")]
pub grid_auto_columns: GridTrackVec<TrackSizingFunction>,
/// Controls how items get placed into the grid for auto-placed items
#[cfg(feature = "grid")]
pub grid_auto_flow: GridAutoFlow,
// Grid container named properties
/// Defines the rectangular grid areas
#[cfg(feature = "grid")]
pub grid_template_areas: GridTrackVec<GridTemplateArea<S>>,
/// The named lines between the columns
#[cfg(feature = "grid")]
pub grid_template_column_names: GridTrackVec<GridTrackVec<S>>,
/// The named lines between the rows
#[cfg(feature = "grid")]
pub grid_template_row_names: GridTrackVec<GridTrackVec<S>>,
// Grid child properties
/// Defines which row in the grid the item should start and end at
#[cfg(feature = "grid")]
pub grid_row: Line<GridPlacement<S>>,
/// Defines which column in the grid the item should start and end at
#[cfg(feature = "grid")]
pub grid_column: Line<GridPlacement<S>>,
}
impl<S: CheapCloneStr> Style<S> {
/// The [`Default`] layout, in a form that can be used in const functions
pub const DEFAULT: Style<S> = Style {
dummy: core::marker::PhantomData,
display: Display::DEFAULT,
item_is_table: false,
item_is_replaced: false,
box_sizing: BoxSizing::BorderBox,
direction: Direction::Ltr,
overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
scrollbar_width: 0.0,
#[cfg(feature = "float_layout")]
float: Float::None,
#[cfg(feature = "float_layout")]
clear: Clear::None,
position: Position::Relative,
inset: Rect::auto(),
margin: Rect::zero(),
padding: Rect::zero(),
border: Rect::zero(),
size: Size::auto(),
min_size: Size::auto(),
max_size: Size::auto(),
aspect_ratio: None,
#[cfg(any(feature = "flexbox", feature = "grid"))]
gap: Size::zero(),
// Alignment
#[cfg(any(feature = "flexbox", feature = "grid"))]
align_items: None,
#[cfg(any(feature = "flexbox", feature = "grid"))]
align_self: None,
#[cfg(feature = "grid")]
justify_items: None,
#[cfg(feature = "grid")]
justify_self: None,
#[cfg(any(feature = "flexbox", feature = "grid"))]
align_content: None,
>rg -n "set_text_style|set_max_lines|set_text_align|set_height|set_font_families|set_font_size|set_font_style|set_text_style" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph -g '*.rs'Exit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:69: pub fn set_font_families(&mut self, families: &[impl AsRef<str>]) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:82: pub fn set_font_style(&mut self, font_style: FontStyle) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:91: pub fn set_font_size(&mut self, font_size: scalar) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:96: pub fn set_height(&mut self, height: scalar) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:136: pub fn set_height_override(&mut self, height_override: bool) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:218: pub fn set_text_style(&mut self, text_style: &TextStyle) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:239: pub fn set_text_align(&mut self, align: TextAlign) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:251: pub fn set_max_lines(&mut self, lines: impl Into<Option<usize>>) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rs:271: pub fn set_height(&mut self, height: scalar) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:402: pub fn set_font_style(&mut self, font_style: FontStyle) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:465: pub fn set_font_size(&mut self, size: scalar) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:478: pub fn set_font_families(&mut self, families: &[impl AsRef<str>]) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:496: pub fn set_height(&mut self, height: scalar) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs:510: pub fn set_height_override(&mut self, height_override: bool) -> &mut Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph.rs:709: style.set_text_style(&ts);
>sed -n '1,220p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/paragraph_style.rsExit code: 0
Wall time: 0 seconds
Output:
use std::fmt;
use skia_bindings as sb;
use super::{FontFamilies, TextAlign, TextDirection, TextStyle};
use crate::{
interop::{self, AsStr, FromStrs, SetStr},
modules::paragraph::TextHeightBehavior,
prelude::*,
scalar, FontStyle,
};
pub type StrutStyle = Handle<sb::skia_textlayout_StrutStyle>;
unsafe_send_sync!(StrutStyle);
impl NativeDrop for sb::skia_textlayout_StrutStyle {
fn drop(&mut self) {
unsafe { sb::C_StrutStyle_destruct(self) }
}
}
impl NativeClone for sb::skia_textlayout_StrutStyle {
fn clone(&self) -> Self {
construct(|ss| unsafe { sb::C_StrutStyle_CopyConstruct(ss, self) })
}
}
impl NativePartialEq for sb::skia_textlayout_StrutStyle {
fn eq(&self, rhs: &Self) -> bool {
unsafe { sb::C_StrutStyle_equals(self, rhs) }
}
}
impl Default for StrutStyle {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for StrutStyle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("StrutStyle")
.field("font_families", &self.font_families())
.field("font_style", &self.font_style())
.field("font_size", &self.font_size())
.field("height", &self.height())
.field("leading", &self.leading())
.field("strut_enabled", &self.strut_enabled())
.field("force_strut_height", &self.force_strut_height())
.field("height_override", &self.height_override())
.field("half_leading", &self.half_leading())
.finish()
}
}
impl StrutStyle {
pub fn new() -> Self {
StrutStyle::construct(|ss| unsafe { sb::C_StrutStyle_Construct(ss) })
}
pub fn font_families(&self) -> FontFamilies {
unsafe {
let mut count = 0;
let ptr = sb::C_StrutStyle_getFontFamilies(self.native(), &mut count);
FontFamilies(safer::from_raw_parts(ptr, count))
}
}
pub fn set_font_families(&mut self, families: &[impl AsRef<str>]) -> &mut Self {
let families: Vec<interop::String> = FromStrs::from_strs(families);
let families = families.native();
unsafe {
sb::C_StrutStyle_setFontFamilies(self.native_mut(), families.as_ptr(), families.len());
}
self
}
pub fn font_style(&self) -> FontStyle {
FontStyle::from_native_c(self.native().fFontStyle)
}
pub fn set_font_style(&mut self, font_style: FontStyle) -> &mut Self {
self.native_mut().fFontStyle = font_style.into_native();
self
}
pub fn font_size(&self) -> scalar {
self.native().fFontSize
}
pub fn set_font_size(&mut self, font_size: scalar) -> &mut Self {
self.native_mut().fFontSize = font_size;
self
}
pub fn set_height(&mut self, height: scalar) -> &mut Self {
self.native_mut().fHeight = height;
self
}
pub fn height(&self) -> scalar {
self.native().fHeight
}
pub fn set_leading(&mut self, leading: scalar) -> &mut Self {
self.native_mut().fLeading = leading;
self
}
pub fn leading(&self) -> scalar {
self.native().fLeading
}
pub fn strut_enabled(&self) -> bool {
self.native().fEnabled
}
pub fn set_strut_enabled(&mut self, enabled: bool) -> &mut Self {
self.native_mut().fEnabled = enabled;
self
}
pub fn force_strut_height(&self) -> bool {
self.native().fForceHeight
}
pub fn set_force_strut_height(&mut self, force_height: bool) -> &mut Self {
self.native_mut().fForceHeight = force_height;
self
}
pub fn height_override(&self) -> bool {
self.native().fHeightOverride
}
pub fn set_height_override(&mut self, height_override: bool) -> &mut Self {
self.native_mut().fHeightOverride = height_override;
self
}
pub fn half_leading(&self) -> bool {
self.native().fHalfLeading
}
pub fn set_half_leading(&mut self, half_leading: bool) -> &mut Self {
self.native_mut().fHalfLeading = half_leading;
self
}
}
// Can't use `Handle<>` here, `std::u16string` maintains an interior pointer.
pub type ParagraphStyle = RefHandle<sb::skia_textlayout_ParagraphStyle>;
unsafe_send_sync!(ParagraphStyle);
impl NativeDrop for sb::skia_textlayout_ParagraphStyle {
fn drop(&mut self) {
unsafe { sb::C_ParagraphStyle_delete(self) }
}
}
impl Clone for ParagraphStyle {
fn clone(&self) -> Self {
Self::from_ptr(unsafe { sb::C_ParagraphStyle_newCopy(self.native()) }).unwrap()
}
}
impl NativePartialEq for sb::skia_textlayout_ParagraphStyle {
fn eq(&self, rhs: &Self) -> bool {
unsafe { sb::C_ParagraphStyle_Equals(self, rhs) }
}
}
impl Default for ParagraphStyle {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for ParagraphStyle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ParagraphStyle")
.field("strut_style", &self.strut_style())
.field("text_style", &self.text_style())
.field("text_direction", &self.text_direction())
.field("text_align", &self.text_align())
.field("max_lines", &self.max_lines())
.field("ellipsis", &self.ellipsis())
.field("height", &self.height())
.field("text_height_behavior", &self.text_height_behavior())
.field("unlimited_lines", &self.unlimited_lines())
.field("ellipsized", &self.ellipsized())
.field("effective_align", &self.effective_align())
.field("hinting_is_on", &self.hinting_is_on())
.field("replace_tab_characters", &self.replace_tab_characters())
.field("fake_missing_font_styles", &self.fake_missing_font_styles())
.finish()
}
}
impl ParagraphStyle {
pub fn new() -> Self {
Self::from_ptr(unsafe { sb::C_ParagraphStyle_new() }).unwrap()
}
pub fn strut_style(&self) -> &StrutStyle {
StrutStyle::from_native_ref(&self.native().fStrutStyle)
}
pub fn set_strut_style(&mut self, strut_style: StrutStyle) -> &mut Self {
self.native_mut().fStrutStyle.replace_with(strut_style);
self
}
pub fn text_style(&self) -> &TextStyle {
TextStyle::from_native_ref(&self.native().fDefaultTextStyle)
}
pub fn set_text_style(&mut self, text_style: &TextStyle) -> &mut Self {
// TODO: implement the assignment operator in C.
self.native_mut()
>sed -n '1,220p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rsExit code: 0
Wall time: 0 seconds
Output:
use super::{FontArguments, FontFamilies, TextBaseline, TextShadow};
use crate::{
font,
interop::{self, AsStr, FromStrs, SetStr},
prelude::*,
scalar,
textlayout::{RangeExtensions, EMPTY_INDEX, EMPTY_RANGE},
Color, FontHinting, FontMetrics, FontStyle, Paint, Typeface,
};
use skia_bindings as sb;
use std::{fmt, ops::Range};
bitflags! {
/// Multiple decorations can be applied at once. Ex: Underline and overline is
/// (0x1 | 0x2)
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TextDecoration: u32 {
const NO_DECORATION = sb::skia_textlayout_TextDecoration::kNoDecoration as _;
const UNDERLINE = sb::skia_textlayout_TextDecoration::kUnderline as _;
const OVERLINE = sb::skia_textlayout_TextDecoration::kOverline as _;
const LINE_THROUGH = sb::skia_textlayout_TextDecoration::kLineThrough as _;
}
}
pub const ALL_TEXT_DECORATIONS: TextDecoration = TextDecoration::ALL;
impl Default for TextDecoration {
fn default() -> Self {
TextDecoration::NO_DECORATION
}
}
impl TextDecoration {
pub const ALL: TextDecoration = TextDecoration::all();
}
pub use sb::skia_textlayout_TextDecorationStyle as TextDecorationStyle;
#[test]
fn text_decoration_style_naming() {
let _ = TextDecorationStyle::Solid;
}
pub use sb::skia_textlayout_TextDecorationMode as TextDecorationMode;
#[test]
fn text_decoration_mode_naming() {
let _ = TextDecorationMode::Gaps;
}
pub use sb::skia_textlayout_StyleType as StyleType;
#[test]
fn style_type_member_naming() {
let _ = StyleType::Foreground;
let _ = StyleType::LetterSpacing;
}
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Decoration {
pub ty: TextDecoration,
pub mode: TextDecorationMode,
pub color: Color,
pub style: TextDecorationStyle,
pub thickness_multiplier: scalar,
}
impl Default for Decoration {
fn default() -> Self {
Self {
ty: TextDecoration::default(),
mode: TextDecorationMode::default(),
color: Color::TRANSPARENT,
style: TextDecorationStyle::default(),
thickness_multiplier: 1.0,
}
}
}
native_transmutable!(sb::skia_textlayout_Decoration, Decoration);
/// Where to vertically align the placeholder relative to the surrounding text.
#[repr(i32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)]
pub enum PlaceholderAlignment {
/// Match the baseline of the placeholder with the baseline.
#[default]
Baseline,
/// Align the bottom edge of the placeholder with the baseline such that the
/// placeholder sits on top of the baseline.
AboveBaseline,
/// Align the top edge of the placeholder with the baseline specified in
/// such that the placeholder hangs below the baseline.
BelowBaseline,
/// Align the top edge of the placeholder with the top edge of the font.
/// When the placeholder is very tall, the extra space will hang from
/// the top and extend through the bottom of the line.
Top,
/// Align the bottom edge of the placeholder with the top edge of the font.
/// When the placeholder is very tall, the extra space will rise from
/// the bottom and extend through the top of the line.
Bottom,
/// Align the middle of the placeholder with the middle of the text. When the
/// placeholder is very tall, the extra space will grow equally from
/// the top and bottom of the line.
Middle,
}
native_transmutable!(
sb::skia_textlayout_PlaceholderAlignment,
PlaceholderAlignment
);
pub type FontFeature = Handle<sb::skia_textlayout_FontFeature>;
unsafe_send_sync!(FontFeature);
impl NativeDrop for sb::skia_textlayout_FontFeature {
fn drop(&mut self) {
unsafe { sb::C_FontFeature_destruct(self) }
}
}
impl NativeClone for sb::skia_textlayout_FontFeature {
fn clone(&self) -> Self {
construct(|ts| unsafe { sb::C_FontFeature_CopyConstruct(ts, self) })
}
}
impl PartialEq for FontFeature {
fn eq(&self, other: &Self) -> bool {
self.name() == other.name() && self.value() == other.value()
}
}
impl fmt::Debug for FontFeature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("FontFeature")
.field(&self.name())
.field(&self.value())
.finish()
}
}
impl FontFeature {
pub fn name(&self) -> &str {
self.native().fName.as_str()
}
pub fn value(&self) -> i32 {
self.native().fValue
}
}
#[repr(C)]
#[derive(Clone, Default, Debug)]
pub struct PlaceholderStyle {
pub width: scalar,
pub height: scalar,
pub alignment: PlaceholderAlignment,
pub baseline: TextBaseline,
/// Distance from the top edge of the rect to the baseline position. This
/// baseline will be aligned against the alphabetic baseline of the surrounding
/// text.
///
/// Positive values drop the baseline lower (positions the rect higher) and
/// small or negative values will cause the rect to be positioned underneath
/// the line. When baseline == height, the bottom edge of the rect will rest on
/// the alphabetic baseline.
pub baseline_offset: scalar,
}
native_transmutable!(sb::skia_textlayout_PlaceholderStyle, PlaceholderStyle);
impl PartialEq for PlaceholderStyle {
fn eq(&self, other: &Self) -> bool {
unsafe { self.native().equals(other.native()) }
}
}
impl PlaceholderStyle {
pub fn new(
width: scalar,
height: scalar,
alignment: PlaceholderAlignment,
baseline: TextBaseline,
offset: scalar,
) -> Self {
Self {
width,
height,
alignment,
baseline,
baseline_offset: offset,
}
}
}
pub type TextStyle = Handle<sb::skia_textlayout_TextStyle>;
unsafe_send_sync!(TextStyle);
impl NativeDrop for sb::skia_textlayout_TextStyle {
fn drop(&mut self) {
unsafe { sb::C_TextStyle_destruct(self) }
}
}
impl NativeClone for sb::skia_textlayout_TextStyle {
fn clone(&self) -> Self {
construct(|ts| unsafe { sb::C_TextStyle_CopyConstruct(ts, self) })
}
}
impl NativePartialEq for sb::skia_textlayout_TextStyle {
fn eq(&self, rhs: &Self) -> bool {
unsafe { self.equals(rhs) }
}
}
>rg -n "pub fn new_with_children|pub fn layout\(&self" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rsExit code: 0
Wall time: 0 seconds
Output:
595: pub fn new_with_children(&mut self, layout: Style, children: &[NodeId]) -> TaffyResult<NodeId> {
848: pub fn layout(&self, node: NodeId) -> TaffyResult<&Layout> {
>sed -n '560,660p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rsExit code: 0
Wall time: 0 seconds
Output:
pub fn enable_rounding(&mut self) {
self.config.use_rounding = true;
}
/// Disable rounding of layout values. Rounding is enabled by default.
pub fn disable_rounding(&mut self) {
self.config.use_rounding = false;
}
/// Creates and adds a new unattached leaf node to the tree, and returns the node of the new node
pub fn new_leaf(&mut self, layout: Style) -> TaffyResult<NodeId> {
let id = self.nodes.insert(NodeData::new(layout));
let _ = self.children.insert(new_vec_with_capacity(0));
let _ = self.parents.insert(None);
Ok(id.into())
}
/// Creates and adds a new unattached leaf node to the tree, and returns the [`NodeId`] of the new node
///
/// Creates and adds a new leaf node with a supplied context
pub fn new_leaf_with_context(&mut self, layout: Style, context: NodeContext) -> TaffyResult<NodeId> {
let mut data = NodeData::new(layout);
data.has_context = true;
let id = self.nodes.insert(data);
self.node_context_data.insert(id, context);
let _ = self.children.insert(new_vec_with_capacity(0));
let _ = self.parents.insert(None);
Ok(id.into())
}
/// Creates and adds a new node, which may have any number of `children`
pub fn new_with_children(&mut self, layout: Style, children: &[NodeId]) -> TaffyResult<NodeId> {
let id = NodeId::from(self.nodes.insert(NodeData::new(layout)));
for child in children {
self.parents[(*child).into()] = Some(id);
}
let _ = self.children.insert(children.iter().copied().collect::<_>());
let _ = self.parents.insert(None);
Ok(id)
}
/// Drops all nodes in the tree
pub fn clear(&mut self) {
self.nodes.clear();
self.children.clear();
self.parents.clear();
}
/// Remove a specific node from the tree and drop it
///
/// Returns the id of the node removed.
pub fn remove(&mut self, node: NodeId) -> TaffyResult<NodeId> {
let key = node.into();
if let Some(parent) = self.parents[key] {
if let Some(children) = self.children.get_mut(parent.into()) {
children.retain(|f| *f != node);
}
}
// Remove "parent" references to a node when removing that node
if let Some(children) = self.children.get(key) {
for child in children.iter().copied() {
self.parents[child.into()] = None;
}
}
let _ = self.children.remove(key);
let _ = self.parents.remove(key);
let _ = self.nodes.remove(key);
Ok(node)
}
/// Sets the context data associated with the node
#[inline]
pub fn set_node_context(&mut self, node: NodeId, measure: Option<NodeContext>) -> TaffyResult<()> {
let key = node.into();
if let Some(measure) = measure {
self.nodes[key].has_context = true;
self.node_context_data.insert(key, measure);
} else {
self.nodes[key].has_context = false;
self.node_context_data.remove(key);
}
self.mark_dirty(node)?;
Ok(())
}
/// Gets a reference to the the context data associated with the node
#[inline]
pub fn get_node_context(&self, node: NodeId) -> Option<&NodeContext> {
self.node_context_data.get(node.into())
>sed -n '900,940p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rsExit code: 0
Wall time: 0 seconds
Output:
pub fn dirty(&self, node: NodeId) -> TaffyResult<bool> {
Ok(self.nodes[node.into()].cache.is_empty())
}
/// Updates the stored layout of the provided `node` and its children
pub fn compute_layout_with_measure<MeasureFunction>(
&mut self,
node_id: NodeId,
available_space: Size<AvailableSpace>,
measure_function: MeasureFunction,
) -> Result<(), TaffyError>
where
MeasureFunction:
FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>, &Style) -> Size<f32>,
{
let use_rounding = self.config.use_rounding;
let mut taffy_view = TaffyView { taffy: self, measure_function };
compute_root_layout(&mut taffy_view, node_id, available_space);
if use_rounding {
round_layout(&mut taffy_view, node_id);
}
Ok(())
}
/// Updates the stored layout of the provided `node` and its children
pub fn compute_layout(&mut self, node: NodeId, available_space: Size<AvailableSpace>) -> Result<(), TaffyError> {
self.compute_layout_with_measure(node, available_space, |_, _, _, _, _| Size::ZERO)
}
/// Prints a debug representation of the tree's layout
#[cfg(feature = "std")]
pub fn print_tree(&mut self, root: NodeId) {
crate::util::print_tree(self, root)
}
/// Returns an instance of LayoutTree representing the TaffyTree
#[cfg(test)]
pub(crate) fn as_layout_tree(&mut self) -> impl LayoutPartialTree + CacheTree + '_ {
TaffyView { taffy: self, measure_function: |_, _, _, _, _| Size::ZERO }
}
}
>rg -n "config_mut\(\).*trim_text|read_event_into|Reader::from_str" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4 -g '*.rs' | head -40Exit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:20://! and [`Reader::read_event_into`]. You must listen
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:33://! [`Reader::read_event_into`]: crate::reader::Reader::read_event_into
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:73:/// let mut reader = Reader::from_str("\
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:385:/// let mut reader = Reader::from_str(r#"<element></element a1 = 'val1' a2="val2" >"#);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:507:/// let mut reader = Reader::from_str("\
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:713:/// let mut reader = Reader::from_str("<![CDATA[ CDATA section ]]>");
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:1016:/// let mut reader = Reader::from_str("<?processing instruction >:-<~ ?>");
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:1193:/// let mut reader = Reader::from_str("<?xml version = '1.0' ?>");
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:1474:/// let mut reader = Reader::from_str(r#"&entity;"#);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:1672:/// Event emitted by [`Reader::read_event_into`].
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/mod.rs:1674:/// [`Reader::read_event_into`]: crate::reader::Reader::read_event_into
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/writer.rs:28:/// let mut reader = Reader::from_str(xml);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/name.rs:770: /// let mut reader = NsReader::from_str(r#"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/name.rs:776: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/name.rs:866: /// let mut reader = NsReader::from_str(src);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/name.rs:867: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/name.rs:961: /// let mut reader = NsReader::from_str(src);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/name.rs:962: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:73: /// let mut reader = NsReader::from_str(src);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:74: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:288: /// let mut reader = NsReader::from_str("<tag xmlns='root namespace'/>");
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:340: /// let mut reader = NsReader::from_str("
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:346: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:396: /// let mut reader = NsReader::from_str(r#"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:402: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:408: /// match reader.read_event_into(&mut buf).unwrap() {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:433: pub fn read_event_into<'b>(&mut self, buf: &'b mut Vec<u8>) -> Result<Event<'b>> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:443: /// If you are not interested in namespaces, you can use [`read_event_into()`]
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:454: /// let mut reader = NsReader::from_str(r#"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:460: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:492: /// [`read_event_into()`]: Self::read_event_into
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:553: /// let mut reader = NsReader::from_str(r#"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:567: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:619: Self::new(Reader::from_str(s))
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:642: /// let mut reader = NsReader::from_str(r#"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:648: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:703: /// let mut reader = NsReader::from_str(r#"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:709: /// reader.config_mut().trim_text(true);
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:791: /// let mut reader = NsReader::from_str(r#"
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/reader/ns_reader.rs:805: /// reader.config_mut().trim_text(true);
>sed -n '1,140p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/README.mdExit code: 0
Wall time: 0 seconds
Output:
# quick-xml

[](https://crates.io/crates/quick-xml)
[](https://docs.rs/quick-xml)
[](https://codecov.io/gh/tafia/quick-xml)
[](https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html)
High performance xml pull reader/writer.
The reader:
- is almost zero-copy (use of `Cow` whenever possible)
- is easy on memory allocation (the API provides a way to reuse buffers)
- support various encoding (with `encoding` feature), namespaces resolution, special characters.
Syntax is inspired by [xml-rs](https://github.com/netvl/xml-rs).
## Example
### Reader
```rust
use quick_xml::events::Event;
use quick_xml::reader::Reader;
let xml = r#"<tag1 att1 = "test">
<tag2><!--Test comment-->Test</tag2>
<tag2>Test 2</tag2>
</tag1>"#;
let mut reader = Reader::from_str(xml);
reader.config_mut().trim_text(true);
let mut count = 0;
let mut txt = Vec::new();
let mut buf = Vec::new();
// The `Reader` does not implement `Iterator` because it outputs borrowed data (`Cow`s)
loop {
// NOTE: this is the generic case when we don't know about the input BufRead.
// when the input is a &str or a &[u8], we don't actually need to use another
// buffer, we could directly call `reader.read_event()`
match reader.read_event_into(&mut buf) {
Err(e) => panic!("Error at position {}: {:?}", reader.error_position(), e),
// exits the loop when reaching end of file
Ok(Event::Eof) => break,
Ok(Event::Start(e)) => {
match e.name().as_ref() {
b"tag1" => println!("attributes values: {:?}",
e.attributes().map(|a| a.unwrap().value)
.collect::<Vec<_>>()),
b"tag2" => count += 1,
_ => (),
}
}
Ok(Event::Text(e)) => txt.push(e.decode().unwrap().into_owned()),
// There are several other `Event`s we do not consider here
_ => (),
}
// if we don't keep a borrow elsewhere, we can clear the buffer to keep memory usage low
buf.clear();
}
```
### Writer
```rust
use quick_xml::events::{Event, BytesEnd, BytesStart};
use quick_xml::reader::Reader;
use quick_xml::writer::Writer;
use std::io::Cursor;
let xml = r#"<this_tag k1="v1" k2="v2"><child>text</child></this_tag>"#;
let mut reader = Reader::from_str(xml);
reader.config_mut().trim_text(true);
let mut writer = Writer::new(Cursor::new(Vec::new()));
loop {
match reader.read_event() {
Ok(Event::Start(e)) if e.name().as_ref() == b"this_tag" => {
// crates a new element ... alternatively we could reuse `e` by calling
// `e.into_owned()`
let mut elem = BytesStart::new("my_elem");
// collect existing attributes
elem.extend_attributes(e.attributes().map(|attr| attr.unwrap()));
// copy existing attributes, adds a new my-key="some value" attribute
elem.push_attribute(("my-key", "some value"));
// writes the event to the writer
assert!(writer.write_event(Event::Start(elem)).is_ok());
},
Ok(Event::End(e)) if e.name().as_ref() == b"this_tag" => {
assert!(writer.write_event(Event::End(BytesEnd::new("my_elem"))).is_ok());
},
Ok(Event::Eof) => break,
// we can either move or borrow the event to write, depending on your use-case
Ok(e) => assert!(writer.write_event(e).is_ok()),
Err(e) => panic!("Error at position {}: {:?}", reader.error_position(), e),
}
}
let result = writer.into_inner().into_inner();
let expected = r#"<my_elem k1="v1" k2="v2" my-key="some value"><child>text</child></my_elem>"#;
assert_eq!(result, expected.as_bytes());
```
## Serde
When using the `serialize` feature, quick-xml can be used with serde's `Serialize`/`Deserialize` traits.
The mapping between XML and Rust types, and in particular the syntax that allows you to specify the
distinction between *elements* and *attributes*, is described in detail in the documentation
for [deserialization](https://docs.rs/quick-xml/latest/quick_xml/de/).
### Credits
This has largely been inspired by [serde-xml-rs](https://github.com/RReverser/serde-xml-rs).
quick-xml follows its convention for deserialization, including the
[`$value`](https://github.com/RReverser/serde-xml-rs#parsing-the-value-of-a-tag) special name.
### Parsing the "value" of a tag
If you have an input of the form `<foo abc="xyz">bar</foo>`, and you want to get at the `bar`,
you can use either the special name `$text`, or the special name `$value`:
```rust,ignore
struct Foo {
#[serde(rename = "@abc")]
pub abc: String,
#[serde(rename = "$text")]
pub body: String,
}
```
Read about the difference in the [documentation](https://docs.rs/quick-xml/latest/quick_xml/de/index.html#difference-between-text-and-value-special-names).
### Performance
>sed -n '1,220p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/dimension.rsExit code: 0
Wall time: 0.1 seconds
Output:
//! Style types for representing lengths / sizes
use super::CompactLength;
use crate::geometry::Rect;
use crate::style_helpers::{FromLength, FromPercent, TaffyAuto, TaffyZero};
#[cfg(feature = "parse")]
use crate::util::parse::{from_str_from_css, parse_css_str_entirely, CssParseResult, FromCss, Parser, Token};
/// A unit of linear measurement
///
/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](crate::geometry::Size).
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LengthPercentage(pub(crate) CompactLength);
impl TaffyZero for LengthPercentage {
const ZERO: Self = Self(CompactLength::ZERO);
}
impl FromLength for LengthPercentage {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::length(value.into())
}
}
impl FromPercent for LengthPercentage {
fn from_percent<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::percent(value.into())
}
}
#[cfg(feature = "parse")]
impl FromCss for LengthPercentage {
fn from_css<'i>(parser: &mut Parser<'i, '_>) -> CssParseResult<'i, Self> {
match parser.next()?.clone() {
Token::Percentage { unit_value, .. } => Ok(Self::percent(unit_value)),
Token::Dimension { unit, value, .. } if unit == "px" => Ok(Self::length(value)),
token => Err(parser.new_unexpected_token_error(token))?,
}
}
}
#[cfg(feature = "parse")]
from_str_from_css!(LengthPercentage);
impl LengthPercentage {
/// An absolute length in some abstract units. Users of Taffy may define what they correspond
/// to in their application (pixels, logical pixels, mm, etc) as they see fit.
#[inline(always)]
pub const fn length(val: f32) -> Self {
Self(CompactLength::length(val))
}
/// A percentage length relative to the size of the containing block.
///
/// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
#[inline(always)]
pub const fn percent(val: f32) -> Self {
Self(CompactLength::percent(val))
}
/// A `calc()` value. The value passed here is treated as an opaque handle to
/// the actual calc representation and may be a pointer, index, etc.
///
/// The low 3 bits are used as a tag value and will be returned as 0.
#[inline(always)]
#[cfg(feature = "calc")]
pub fn calc(ptr: *const ()) -> Self {
Self(CompactLength::calc(ptr))
}
/// Create a LengthPercentage from a raw `CompactLength`.
/// # Safety
/// CompactLength must represent a valid variant for LengthPercentage
#[allow(unsafe_code)]
pub const unsafe fn from_raw(val: CompactLength) -> Self {
Self(val)
}
/// Get the underlying `CompactLength` representation of the value
pub const fn into_raw(self) -> CompactLength {
self.0
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for LengthPercentage {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let inner = CompactLength::deserialize(deserializer)?;
// Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported
if matches!(inner.tag(), CompactLength::LENGTH_TAG | CompactLength::PERCENT_TAG) {
Ok(Self(inner))
} else {
Err(serde::de::Error::custom("Invalid tag"))
}
}
}
/// A unit of linear measurement
///
/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](crate::geometry::Size).
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LengthPercentageAuto(pub(crate) CompactLength);
impl TaffyZero for LengthPercentageAuto {
const ZERO: Self = Self(CompactLength::ZERO);
}
impl TaffyAuto for LengthPercentageAuto {
const AUTO: Self = Self(CompactLength::AUTO);
}
impl FromLength for LengthPercentageAuto {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::length(value.into())
}
}
impl FromPercent for LengthPercentageAuto {
fn from_percent<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::percent(value.into())
}
}
impl From<LengthPercentage> for LengthPercentageAuto {
fn from(input: LengthPercentage) -> Self {
Self(input.0)
}
}
#[cfg(feature = "parse")]
impl FromCss for LengthPercentageAuto {
fn from_css<'i>(parser: &mut Parser<'i, '_>) -> CssParseResult<'i, Self> {
match parser.next()?.clone() {
Token::Percentage { unit_value, .. } => Ok(Self::percent(unit_value)),
Token::Dimension { unit, value, .. } if unit == "px" => Ok(Self::length(value)),
Token::Ident(ident) if ident == "auto" => Ok(Self::auto()),
token => Err(parser.new_unexpected_token_error(token))?,
}
}
}
#[cfg(feature = "parse")]
from_str_from_css!(LengthPercentageAuto);
impl LengthPercentageAuto {
/// An absolute length in some abstract units. Users of Taffy may define what they correspond
/// to in their application (pixels, logical pixels, mm, etc) as they see fit.
#[inline(always)]
pub const fn length(val: f32) -> Self {
Self(CompactLength::length(val))
}
/// A percentage length relative to the size of the containing block.
///
/// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
#[inline(always)]
pub const fn percent(val: f32) -> Self {
Self(CompactLength::percent(val))
}
/// The dimension should be automatically computed according to algorithm-specific rules
/// regarding the default size of boxes.
#[inline(always)]
pub const fn auto() -> Self {
Self(CompactLength::auto())
}
/// A `calc()` value. The value passed here is treated as an opaque handle to
/// the actual calc representation and may be a pointer, index, etc.
///
/// The low 3 bits are used as a tag value and will be returned as 0.
#[inline]
#[cfg(feature = "calc")]
pub fn calc(ptr: *const ()) -> Self {
Self(CompactLength::calc(ptr))
}
/// Create a LengthPercentageAuto from a raw `CompactLength`.
/// # Safety
/// CompactLength must represent a valid variant for LengthPercentageAuto
#[allow(unsafe_code)]
pub const unsafe fn from_raw(val: CompactLength) -> Self {
Self(val)
}
/// Get the underlying `CompactLength` representation of the value
pub const fn into_raw(self) -> CompactLength {
self.0
}
/// Returns:
/// - Some(length) for Length variants
/// - Some(resolved) using the provided context for Percent variants
/// - None for Auto variants
#[inline(always)]
pub fn resolve_to_option(self, context: f32, calc_resolver: impl Fn(*const (), f32) -> f32) -> Option<f32> {
match self.0.tag() {
CompactLength::LENGTH_TAG => Some(self.0.value()),
CompactLength::PERCENT_TAG => Some(context * self.0.value()),
CompactLength::AUTO_TAG => None,
#[cfg(feature = "calc")]
_ if self.0.is_calc() => Some(calc_resolver(self.0.calc_value(), context)),
_ => unreachable!("LengthPercentageAuto values cannot be constructed with other tags"),
}
}
/// Returns true if value is LengthPercentageAuto::Auto
#[inline(always)]
pub fn is_auto(self) -> bool {
self.0.is_auto()
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for LengthPercentageAuto {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let inner = CompactLength::deserialize(deserializer)?;
// Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported
if matches!(inner.tag(), CompactLength::LENGTH_TAG | CompactLength::PERCENT_TAG | CompactLength::AUTO_TAG) {
Ok(Self(inner))
} else {
Err(serde::de::Error::custom("Invalid tag"))
}
>sed -n '260,330p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/mod.rsExit code: 0
Wall time: 0.1 seconds
Output:
impl Default for BoxGenerationMode {
fn default() -> Self {
Self::DEFAULT
}
}
/// The positioning strategy for this item.
///
/// This controls both how the origin is determined for the [`Style::position`] field,
/// and whether or not the item will be controlled by flexbox's layout algorithm.
///
/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
/// which can be unintuitive.
///
/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Position {
/// The offset is computed relative to the final position given by the layout algorithm.
/// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
#[default]
Relative,
/// The offset is computed relative to this item's closest positioned ancestor, if any.
/// Otherwise, it is placed relative to the origin.
/// No space is created for the item in the page layout, and its size will not be altered.
///
/// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
Absolute,
}
#[cfg(feature = "parse")]
crate::util::parse::impl_parse_for_keyword_enum!(Position,
"relative" => Relative,
"absolute" => Absolute,
);
/// Specifies whether size styles for this node are assigned to the node's "content box" or "border box"
///
/// - The "content box" is the node's inner size excluding padding, border and margin
/// - The "border box" is the node's outer size including padding and border (but still excluding margin)
///
/// This property modifies the application of the following styles:
///
/// - `size`
/// - `min_size`
/// - `max_size`
/// - `flex_basis`
///
/// See <https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing>
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum BoxSizing {
/// Size styles such size, min_size, max_size specify the box's "border box" (the size excluding margin but including padding/border)
#[default]
BorderBox,
/// Size styles such size, min_size, max_size specify the box's "content box" (the size excluding padding/border/margin)
ContentBox,
}
#[cfg(feature = "parse")]
crate::util::parse::impl_parse_for_keyword_enum!(BoxSizing,
"border-box" => BorderBox,
"content-box" => ContentBox,
);
/// How children overflowing their container should affect layout
///
/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should
/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout,
/// the main ones being:
///
>sed -n '1,220p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/alignment.rsExit code: 0
Wall time: 0 seconds
Output:
//! Style types for controlling alignment
/// Used to control how child nodes are aligned.
/// For Flexbox it controls alignment in the cross axis
/// For Grid it controls alignment in the block axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlignItems {
/// Items are packed toward the start of the axis
Start,
/// Items are packed toward the end of the axis
End,
/// Items are packed towards the flex-relative start of the axis.
///
/// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
/// to End. In all other cases it is equivalent to Start.
FlexStart,
/// Items are packed towards the flex-relative end of the axis.
///
/// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
/// to Start. In all other cases it is equivalent to End.
FlexEnd,
/// Items are packed along the center of the cross axis
Center,
/// Items are aligned such as their baselines align
Baseline,
/// Stretch to fill the container
Stretch,
}
#[cfg(feature = "parse")]
crate::util::parse::impl_parse_for_keyword_enum!(AlignItems,
"start" => Start,
"end" => End,
"flex-start" => FlexStart,
"flex-end" => FlexEnd,
"center" => Center,
"baseline" => Baseline,
"stretch" => Stretch,
);
/// Used to control how child nodes are aligned.
/// Does not apply to Flexbox, and will be ignored if specified on a flex container
/// For Grid it controls alignment in the inline axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items)
pub type JustifyItems = AlignItems;
/// Controls alignment of an individual node
///
/// Overrides the parent Node's `AlignItems` property.
/// For Flexbox it controls alignment in the cross axis
/// For Grid it controls alignment in the block axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self)
pub type AlignSelf = AlignItems;
/// Controls alignment of an individual node
///
/// Overrides the parent Node's `JustifyItems` property.
/// Does not apply to Flexbox, and will be ignored if specified on a flex child
/// For Grid it controls alignment in the inline axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-self)
pub type JustifySelf = AlignItems;
/// Sets the distribution of space between and around content items
/// For Flexbox it controls alignment in the cross axis
/// For Grid it controls alignment in the block axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-content)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlignContent {
/// Items are packed toward the start of the axis
Start,
/// Items are packed toward the end of the axis
End,
/// Items are packed towards the flex-relative start of the axis.
///
/// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
/// to End. In all other cases it is equivalent to Start.
FlexStart,
/// Items are packed towards the flex-relative end of the axis.
///
/// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
/// to Start. In all other cases it is equivalent to End.
FlexEnd,
/// Items are centered around the middle of the axis
Center,
/// Items are stretched to fill the container
Stretch,
/// The first and last items are aligned flush with the edges of the container (no gap)
/// The gap between items is distributed evenly.
SpaceBetween,
/// The gap between the first and last items is exactly THE SAME as the gap between items.
/// The gaps are distributed evenly
SpaceEvenly,
/// The gap between the first and last items is exactly HALF the gap between items.
/// The gaps are distributed evenly in proportion to these ratios.
SpaceAround,
}
#[cfg(feature = "parse")]
crate::util::parse::impl_parse_for_keyword_enum!(AlignContent,
"start" => Start,
"end" => End,
"flex-start" => FlexStart,
"flex-end" => FlexEnd,
"center" => Center,
"stretch" => Stretch,
"space-between" => SpaceBetween,
"space-evenly" => SpaceEvenly,
"space-around" => SpaceAround,
);
impl AlignContent {
/// Returns the reversed alignment for RTL (right-to-left) contexts.
pub(crate) fn reversed(self) -> Self {
match self {
Self::Start => Self::End,
Self::End => Self::Start,
Self::FlexStart => Self::FlexEnd,
Self::FlexEnd => Self::FlexStart,
Self::Stretch => Self::End,
style => style,
}
}
}
/// Sets the distribution of space between and around content items
/// For Flexbox it controls alignment in the main axis
/// For Grid it controls alignment in the inline axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content)
pub type JustifyContent = AlignContent;
>rg -n "struct Attribute|decode_and_unescape_value|pub fn decoder" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/attributes.rsExit code: 0
Wall time: 0 seconds
Output:
19:/// want to access the value using one of the [`unescape_value`] and [`decode_and_unescape_value`]
23:/// [`decode_and_unescape_value`]: Self::decode_and_unescape_value
25:pub struct Attribute<'a> {
48: /// Libs should use [`decode_and_unescape_value()`](Self::decode_and_unescape_value)
76: /// Libs should use [`decode_and_unescape_value_with()`](Self::decode_and_unescape_value_with)
90: self.decode_and_unescape_value_with(Decoder::utf8(), resolve_entity)
97: pub fn decode_and_unescape_value(&self, decoder: Decoder) -> XmlResult<Cow<'a, str>> {
98: self.decode_and_unescape_value_with(decoder, resolve_predefined_entity)
105: pub fn decode_and_unescape_value_with<'entity>(
257:pub struct Attributes<'a> {
>sed -n '1,220p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.38.4/src/events/attributes.rsExit code: 0
Wall time: 0 seconds
Output:
//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use crate::encoding::Decoder;
use crate::errors::Result as XmlResult;
use crate::escape::{escape, resolve_predefined_entity, unescape_with};
use crate::name::{LocalName, Namespace, QName};
use crate::reader::NsReader;
use crate::utils::{is_whitespace, Bytes};
use std::fmt::{self, Debug, Display, Formatter};
use std::iter::FusedIterator;
use std::{borrow::Cow, ops::Range};
/// A struct representing a key/value XML attribute.
///
/// Field `value` stores raw bytes, possibly containing escape-sequences. Most users will likely
/// want to access the value using one of the [`unescape_value`] and [`decode_and_unescape_value`]
/// functions.
///
/// [`unescape_value`]: Self::unescape_value
/// [`decode_and_unescape_value`]: Self::decode_and_unescape_value
#[derive(Clone, Eq, PartialEq)]
pub struct Attribute<'a> {
/// The key to uniquely define the attribute.
///
/// If [`Attributes::with_checks`] is turned off, the key might not be unique.
pub key: QName<'a>,
/// The raw value of the attribute.
pub value: Cow<'a, [u8]>,
}
impl<'a> Attribute<'a> {
/// Decodes using UTF-8 then unescapes the value.
///
/// This is normally the value you are interested in. Escape sequences such as `>` are
/// replaced with their unescaped equivalents such as `>`.
///
/// This will allocate if the value contains any escape sequences.
///
/// See also [`unescape_value_with()`](Self::unescape_value_with)
///
/// <div style="background:rgba(120,145,255,0.45);padding:0.75em;">
///
/// NOTE: Because this method is available only if [`encoding`] feature is **not** enabled,
/// should only be used by applications.
/// Libs should use [`decode_and_unescape_value()`](Self::decode_and_unescape_value)
/// instead, because if lib will be used in a project which depends on quick_xml with
/// [`encoding`] feature enabled, the lib will fail to compile due to [feature unification].
///
/// </div>
///
/// [`encoding`]: ../../index.html#encoding
/// [feature unification]: https://doc.rust-lang.org/cargo/reference/features.html#feature-unification
#[cfg(any(doc, not(feature = "encoding")))]
pub fn unescape_value(&self) -> XmlResult<Cow<'a, str>> {
self.unescape_value_with(resolve_predefined_entity)
}
/// Decodes using UTF-8 then unescapes the value, using custom entities.
///
/// This is normally the value you are interested in. Escape sequences such as `>` are
/// replaced with their unescaped equivalents such as `>`.
/// A fallback resolver for additional custom entities can be provided via
/// `resolve_entity`.
///
/// This will allocate if the value contains any escape sequences.
///
/// See also [`unescape_value()`](Self::unescape_value)
///
/// <div style="background:rgba(120,145,255,0.45);padding:0.75em;">
///
/// NOTE: Because this method is available only if [`encoding`] feature is **not** enabled,
/// should only be used by applications.
/// Libs should use [`decode_and_unescape_value_with()`](Self::decode_and_unescape_value_with)
/// instead, because if lib will be used in a project which depends on quick_xml with
/// [`encoding`] feature enabled, the lib will fail to compile due to [feature unification].
///
/// </div>
///
/// [`encoding`]: ../../index.html#encoding
/// [feature unification]: https://doc.rust-lang.org/cargo/reference/features.html#feature-unification
#[cfg(any(doc, not(feature = "encoding")))]
#[inline]
pub fn unescape_value_with<'entity>(
&self,
resolve_entity: impl FnMut(&str) -> Option<&'entity str>,
) -> XmlResult<Cow<'a, str>> {
self.decode_and_unescape_value_with(Decoder::utf8(), resolve_entity)
}
/// Decodes then unescapes the value.
///
/// This will allocate if the value contains any escape sequences or in
/// non-UTF-8 encoding.
pub fn decode_and_unescape_value(&self, decoder: Decoder) -> XmlResult<Cow<'a, str>> {
self.decode_and_unescape_value_with(decoder, resolve_predefined_entity)
}
/// Decodes then unescapes the value with custom entities.
///
/// This will allocate if the value contains any escape sequences or in
/// non-UTF-8 encoding.
pub fn decode_and_unescape_value_with<'entity>(
&self,
decoder: Decoder,
resolve_entity: impl FnMut(&str) -> Option<&'entity str>,
) -> XmlResult<Cow<'a, str>> {
let decoded = decoder.decode_cow(&self.value)?;
match unescape_with(&decoded, resolve_entity)? {
// Because result is borrowed, no replacements was done and we can use original string
Cow::Borrowed(_) => Ok(decoded),
Cow::Owned(s) => Ok(s.into()),
}
}
/// If attribute value [represents] valid boolean values, returns `Some`, otherwise returns `None`.
///
/// The valid boolean representations are only `"true"`, `"false"`, `"1"`, and `"0"`.
///
/// # Examples
///
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
/// let attr = Attribute::from(("attr", "false"));
/// assert_eq!(attr.as_bool(), Some(false));
///
/// let attr = Attribute::from(("attr", "0"));
/// assert_eq!(attr.as_bool(), Some(false));
///
/// let attr = Attribute::from(("attr", "true"));
/// assert_eq!(attr.as_bool(), Some(true));
///
/// let attr = Attribute::from(("attr", "1"));
/// assert_eq!(attr.as_bool(), Some(true));
///
/// let attr = Attribute::from(("attr", "bot bool"));
/// assert_eq!(attr.as_bool(), None);
/// ```
///
/// [represents]: https://www.w3.org/TR/xmlschema11-2/#boolean
#[inline]
pub fn as_bool(&self) -> Option<bool> {
match self.value.as_ref() {
b"1" | b"true" => Some(true),
b"0" | b"false" => Some(false),
_ => None,
}
}
}
impl<'a> Debug for Attribute<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("Attribute")
.field("key", &Bytes(self.key.as_ref()))
.field("value", &Bytes(&self.value))
.finish()
}
}
impl<'a> From<(&'a [u8], &'a [u8])> for Attribute<'a> {
/// Creates new attribute from raw bytes.
/// Does not apply any transformation to both key and value.
///
/// # Examples
///
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
/// let features = Attribute::from(("features".as_bytes(), "Bells & whistles".as_bytes()));
/// assert_eq!(features.value, "Bells & whistles".as_bytes());
/// ```
fn from(val: (&'a [u8], &'a [u8])) -> Attribute<'a> {
Attribute {
key: QName(val.0),
value: Cow::from(val.1),
}
}
}
impl<'a> From<(&'a str, &'a str)> for Attribute<'a> {
/// Creates new attribute from text representation.
/// Key is stored as-is, but the value will be escaped.
///
/// # Examples
///
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
/// let features = Attribute::from(("features", "Bells & whistles"));
/// assert_eq!(features.value, "Bells & whistles".as_bytes());
/// ```
fn from(val: (&'a str, &'a str)) -> Attribute<'a> {
Attribute {
key: QName(val.0.as_bytes()),
value: match escape(val.1) {
Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
Cow::Owned(s) => Cow::Owned(s.into_bytes()),
},
}
}
}
impl<'a> From<(&'a str, Cow<'a, str>)> for Attribute<'a> {
/// Creates new attribute from text representation.
/// Key is stored as-is, but the value will be escaped.
///
/// # Examples
///
/// ```
/// # use std::borrow::Cow;
/// use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
>rg -n "new_n32_premul|Color4f|Color::from_argb|FontMgr::default|set_color\(|set_anti_alias|Style::Stroke" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src -g '*.rs' | head -50Exit code: 0
Wall time: 0 seconds
Output:
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/utils/ordered_font_mgr.rs:57: let ordered = OrderedFontMgr::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/utils/ordered_font_mgr.rs:63: let mut ordered = OrderedFontMgr::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/utils/ordered_font_mgr.rs:64: let another = OrderedFontMgr::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/utils/ordered_font_mgr.rs:76: let sys_mgr = FontMgr::default();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:1:use crate::{prelude::*, scalar, BlendMode, Color, Color4f, ColorSpace, NativeFlattenable};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:76: color: impl Into<Color4f>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:79: ) -> Color4f {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:80: Color4f::from_native_c(unsafe {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:81: sb::C_SkColorFilter_filterColor4f(
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:111: use crate::{prelude::*, Color4f, ColorSpace, ColorTable};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:127: c: impl Into<Color4f>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:244: use crate::{color_filters, BlendMode, Color, Color4f, ColorSpace};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color_filter.rs:273: Color4f::new(0.0, 0.0, 0.0, 0.0),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient.rs:1:use crate::{scalar, Color4f, ColorSpace, TileMode};
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient.rs:69: colors: &'a [Color4f],
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient.rs:84: colors: &'a [Color4f],
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient.rs:102: colors: &'a [Color4f],
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient.rs:110: pub fn colors(&self) -> &'a [Color4f] {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:2: gradient, scalar, shaders, Color, Color4f, ColorSpace, Matrix, Point, Shader, TileMode,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:38: colors: (&'a [Color4f], impl Into<Option<ColorSpace>>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:64: colors: (&'a [Color4f], impl Into<Option<ColorSpace>>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:116: colors: (&'a [Color4f], impl Into<Option<ColorSpace>>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:149: colors: (&'a [Color4f], impl Into<Option<ColorSpace>>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:195: // Convert Color to Color4f
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:196: let colors4f: Vec<Color4f> = colors.iter().map(|c| Color4f::from(*c)).collect();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:214: (colors, color_space): (&'a [Color4f], impl Into<Option<ColorSpace>>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:242: let colors4f: Vec<Color4f> = colors.iter().map(|c| Color4f::from(*c)).collect();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:260: (colors, color_space): (&'a [Color4f], impl Into<Option<ColorSpace>>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:291: let colors4f: Vec<Color4f> = colors.iter().map(|c| Color4f::from(*c)).collect();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:318: (colors, color_space): (&'a [Color4f], impl Into<Option<ColorSpace>>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:357: let colors4f: Vec<Color4f> = colors.iter().map(|c| Color4f::from(*c)).collect();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:376: (colors, color_space): (&'a [Color4f], impl Into<Option<ColorSpace>>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:397:/// Type that represents either a slice of [`Color`], or a slice of [`Color4f`] and a color space.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:399:/// a tuple of type `(&[Color4f], &ColorSpace)`.
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:403: ColorsInSpace(&'a [Color4f], Option<ColorSpace>),
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:426:impl<'a> From<(&'a [Color4f], ColorSpace)> for GradientShaderColors<'a> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:427: fn from(c: (&'a [Color4f], ColorSpace)) -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:432:impl<'a> From<(&'a [Color4f], Option<ColorSpace>)> for GradientShaderColors<'a> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:433: fn from(c: (&'a [Color4f], Option<ColorSpace>)) -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:438:impl<'a> From<&'a [Color4f]> for GradientShaderColors<'a> {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/gradient_shader.rs:439: fn from(c: &'a [Color4f]) -> Self {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/shader.rs:155: prelude::*, Blender, Color, Color4f, ColorSpace, Image, Matrix, Rect, SamplingOptions,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/shader.rs:168: pub fn color_in_space(color: impl AsRef<Color4f>, space: impl Into<ColorSpace>) -> Shader {
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/docs/pdf_document.rs:573: paint.set_color(Color::from_rgb(100, 150, 200));
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/docs/pdf_document.rs:578: paint.set_color(Color::from_rgb(200, 150, 100));
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/svg.rs:246: let dom = Dom::from_bytes(data.as_bytes(), FontMgr::default()).unwrap();
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/image_filters.rs:6: prelude::*, scalar, Blender, Color, Color4f, ColorChannel, ColorFilter, ColorSpace,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/image_filters.rs:243: color: impl Into<Color4f>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/effects/image_filters.rs:276: color: impl Into<Color4f>,
/Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/typeface.rs:357: let fm = FontMgr::default();
>sed -n '1,120p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/utils/text_utils.rsExit code: 0
Wall time: 0 seconds
Output:
use skia_bindings::SkTextUtils;
use crate::{prelude::*, Canvas, EncodedText, Font, Paint, Path, Point};
pub use skia_bindings::SkTextUtils_Align as Align;
variant_name!(Align::Center);
pub fn draw_str(
canvas: &Canvas,
text: impl AsRef<str>,
p: impl Into<Point>,
font: &Font,
paint: &Paint,
align: Align,
) {
draw_text(canvas, text.as_ref(), p, font, paint, align)
}
pub fn draw_text(
canvas: &Canvas,
text: impl EncodedText,
p: impl Into<Point>,
font: &Font,
paint: &Paint,
align: Align,
) {
let (ptr, size, encoding) = text.as_raw();
let p = p.into();
unsafe {
SkTextUtils::Draw(
canvas.native_mut(),
ptr,
size,
encoding.into_native(),
p.x,
p.y,
font.native(),
paint.native(),
align,
)
}
}
impl Canvas {
pub fn draw_str_align(
&self,
text: impl AsRef<str>,
p: impl Into<Point>,
font: &Font,
paint: &Paint,
align: Align,
) -> &Self {
self.draw_text_align(text.as_ref(), p, font, paint, align)
}
pub fn draw_text_align(
&self,
text: impl EncodedText,
p: impl Into<Point>,
font: &Font,
paint: &Paint,
align: Align,
) -> &Self {
draw_text(self, text, p, font, paint, align);
self
}
}
pub fn get_path(text: impl EncodedText, p: impl Into<Point>, font: &Font) -> Path {
let (ptr, size, encoding) = text.as_raw();
let p = p.into();
let mut path = Path::default();
unsafe {
SkTextUtils::GetPath(
ptr,
size,
encoding.into_native(),
p.x,
p.y,
font.native(),
path.native_mut(),
)
}
path
}
impl Path {
pub fn from_str(text: impl AsRef<str>, p: impl Into<Point>, font: &Font) -> Self {
get_path(text.as_ref(), p, font)
}
}
>rg -n "new_rect_xy|set_rect_xy|from_rect_xy" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rsExit code: 0
Wall time: 0 seconds
Output:
125: pub fn new_rect_xy(rect: impl AsRef<Rect>, x_rad: scalar, y_rad: scalar) -> Self {
127: rr.set_rect_xy(rect.as_ref(), x_rad, y_rad);
153: pub fn set_rect_xy(&mut self, rect: impl AsRef<Rect>, x_rad: scalar, y_rad: scalar) {
>sed -n '50,120p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/rrect.rsExit code: 0
Wall time: 0 seconds
Output:
}
}
impl RRect {
pub fn new() -> Self {
RRect::construct(|rr| unsafe { sb::C_SkRRect_Construct(rr) })
}
pub fn get_type(&self) -> Type {
unsafe { sb::C_SkRRect_getType(self.native()) }
}
pub fn is_empty(&self) -> bool {
self.get_type() == Type::Empty
}
pub fn is_rect(&self) -> bool {
self.get_type() == Type::Rect
}
pub fn is_oval(&self) -> bool {
self.get_type() == Type::Oval
}
pub fn is_simple(&self) -> bool {
self.get_type() == Type::Simple
}
pub fn is_nine_patch(&self) -> bool {
self.get_type() == Type::NinePatch
}
pub fn is_complex(&self) -> bool {
self.get_type() == Type::Complex
}
pub fn width(&self) -> scalar {
self.rect().width()
}
pub fn height(&self) -> scalar {
self.rect().height()
}
pub fn simple_radii(&self) -> Vector {
self.radii(Corner::UpperLeft)
}
pub fn set_empty(&mut self) {
*self = Self::new()
}
pub fn set_rect(&mut self, rect: impl AsRef<Rect>) {
unsafe { sb::C_SkRRect_setRect(self.native_mut(), rect.as_ref().native()) }
}
pub fn new_empty() -> Self {
Self::new()
}
// TODO: consider to rename all the following new_* function to from_* functions?
// is it possible to find a proper convention here (new_ vs from_?)?
pub fn new_rect(rect: impl AsRef<Rect>) -> Self {
let mut rr = Self::default();
rr.set_rect(rect);
rr
}
pub fn new_oval(oval: impl AsRef<Rect>) -> Self {
let mut rr = Self::default();
>rg -n "from_argb|from_rgb" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color.rsExit code: 0
Wall time: 0 seconds
Output:
27: Color::from_rgb(rgb.r, rgb.g, rgb.b)
74: pub const fn from_argb(a: u8, r: u8, g: u8, b: u8) -> Color {
78: pub const fn from_rgb(r: u8, g: u8, b: u8) -> Color {
79: Self::from_argb(0xff, r, g, b)
100: Self::from_argb(a, self.r(), self.g(), self.b())
340: Color::from_argb(a, r, g, b)
409: let c = Color::from_argb(1, 2, 3, 4);
>sed -n '1,120p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/color.rsExit code: 0
Wall time: 0 seconds
Output:
use crate::prelude::*;
use skia_bindings::{self as sb, SkColor, SkColor4f, SkHSVToColor, SkPMColor, SkRGBToHSV, U8CPU};
use std::ops::{BitAnd, BitOr, Index, IndexMut, Mul};
// TODO: What should we do with SkAlpha?
// It does not seem to be used, but if we want to export it, we'd
// like to define Alpha::TRANSPARENT and Alpha::OPAQUE.
// pub type Alpha = u8;
// Note: SkColor _is_ a u32, and therefore its components are
// endian dependent, so we can't expose it as (transmuted) individual
// argb fields.
#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
#[repr(transparent)]
pub struct Color(SkColor);
native_transmutable!(SkColor, Color);
impl From<u32> for Color {
fn from(argb: u32) -> Self {
Color::new(argb)
}
}
impl From<RGB> for Color {
fn from(rgb: RGB) -> Self {
Color::from_rgb(rgb.r, rgb.g, rgb.b)
}
}
//
// Bitwise operators.
//
impl BitOr for Color {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Color::from_native_c(self.native() | rhs.native())
}
}
impl BitAnd for Color {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Color::from_native_c(self.native() & rhs.native())
}
}
impl BitOr<u32> for Color {
type Output = Self;
fn bitor(self, rhs: u32) -> Self::Output {
self | Color::from_native_c(rhs)
}
}
impl BitAnd<u32> for Color {
type Output = Self;
fn bitand(self, rhs: u32) -> Self::Output {
self & (Color::from_native_c(rhs))
}
}
impl Color {
pub const fn new(argb: u32) -> Self {
Self(argb)
}
// Don't use the u8cpu type in the arguments here, because we trust the Rust compiler to
// optimize the storage type.
pub const fn from_argb(a: u8, r: u8, g: u8, b: u8) -> Color {
Self(((a as U8CPU) << 24) | ((r as U8CPU) << 16) | ((g as U8CPU) << 8) | (b as U8CPU))
}
pub const fn from_rgb(r: u8, g: u8, b: u8) -> Color {
Self::from_argb(0xff, r, g, b)
}
pub fn a(self) -> u8 {
(self.into_native() >> 24) as _
}
pub fn r(self) -> u8 {
(self.into_native() >> 16) as _
}
pub fn g(self) -> u8 {
(self.into_native() >> 8) as _
}
pub fn b(self) -> u8 {
self.into_native() as _
}
#[must_use]
pub fn with_a(self, a: u8) -> Self {
Self::from_argb(a, self.r(), self.g(), self.b())
}
pub const TRANSPARENT: Self = Self(sb::SK_ColorTRANSPARENT);
pub const BLACK: Self = Self(sb::SK_ColorBLACK);
pub const DARK_GRAY: Self = Self(sb::SK_ColorDKGRAY);
pub const GRAY: Self = Self(sb::SK_ColorGRAY);
pub const LIGHT_GRAY: Self = Self(sb::SK_ColorLTGRAY);
pub const WHITE: Self = Self(sb::SK_ColorWHITE);
pub const RED: Self = Self(sb::SK_ColorRED);
pub const GREEN: Self = Self(sb::SK_ColorGREEN);
pub const BLUE: Self = Self(sb::SK_ColorBLUE);
pub const YELLOW: Self = Self(sb::SK_ColorYELLOW);
pub const CYAN: Self = Self(sb::SK_ColorCYAN);
pub const MAGENTA: Self = Self(sb::SK_ColorMAGENTA);
pub fn to_rgb(self) -> RGB {
(self.r(), self.g(), self.b()).into()
}
pub fn to_hsv(self) -> HSV {
>rg -n "new_n32_premul" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image_info.rsExit code: 0
Wall time: 0 seconds
Output:
212: pub fn new_n32_premul(
>sed -n '80,120p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image_info.rsExit code: 0
Wall time: 0 seconds
Output:
}
pub fn is_gamma_close_to_srgb(&self) -> bool {
unsafe { self.native().gammaCloseToSRGB() }
}
#[must_use]
pub fn with_alpha_type(&self, new_alpha_type: AlphaType) -> Self {
Self::construct(|ci| unsafe {
sb::C_SkColorInfo_makeAlphaType(self.native(), new_alpha_type, ci)
})
}
#[must_use]
pub fn with_color_type(&self, new_color_type: ColorType) -> Self {
Self::construct(|ci| unsafe {
sb::C_SkColorInfo_makeColorType(self.native(), new_color_type.into_native(), ci)
})
}
#[must_use]
pub fn with_color_space(&self, cs: impl Into<Option<ColorSpace>>) -> Self {
let color_space: Option<ColorSpace> = cs.into();
Self::construct(|ci| unsafe {
sb::C_SkColorInfo_makeColorSpace(self.native(), color_space.into_ptr_or_null(), ci)
})
}
pub fn bytes_per_pixel(&self) -> usize {
unsafe { self.native().bytesPerPixel().try_into().unwrap() }
}
pub fn shift_per_pixel(&self) -> usize {
unsafe { self.native().shiftPerPixel().try_into().unwrap() }
}
}
pub type ImageInfo = Handle<SkImageInfo>;
unsafe_send_sync!(ImageInfo);
impl NativeDrop for SkImageInfo {
>sed -n '200,235p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/image_info.rsExit code: 0
Wall time: 0 seconds
Output:
ii,
)
})
}
pub fn new_s32(dimensions: impl Into<ISize>, at: AlphaType) -> ImageInfo {
let dimensions = dimensions.into();
Self::construct(|ii| unsafe {
sb::C_SkImageInfo_MakeS32(dimensions.width, dimensions.height, at, ii)
})
}
pub fn new_n32_premul(
dimensions: impl Into<ISize>,
cs: impl Into<Option<ColorSpace>>,
) -> ImageInfo {
let dimensions = dimensions.into();
Self::construct(|ii| unsafe {
sb::C_SkImageInfo_MakeN32Premul(
dimensions.width,
dimensions.height,
cs.into().into_ptr_or_null(),
ii,
)
})
}
pub fn new_a8(dimensions: impl Into<ISize>) -> ImageInfo {
let dimensions = dimensions.into();
Self::construct(|ii| unsafe {
sb::C_SkImageInfo_MakeA8(dimensions.width, dimensions.height, ii)
})
}
pub fn new_unknown(dimensions: Option<ISize>) -> ImageInfo {
let dimensions = dimensions.unwrap_or_default();
>sed -n '1590,1648p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/core/canvas.rsExit code: 0
Wall time: 0 seconds
Output:
left_top: impl Into<Point>,
paint: Option<&Paint>,
) -> &Self {
let left_top = left_top.into();
self.draw_image_with_sampling_options(image, left_top, SamplingOptions::default(), paint)
}
pub fn draw_image_rect(
&self,
image: impl AsRef<Image>,
src: Option<(&Rect, SrcRectConstraint)>,
dst: impl AsRef<Rect>,
paint: &Paint,
) -> &Self {
self.draw_image_rect_with_sampling_options(
image,
src,
dst,
SamplingOptions::default(),
paint,
)
}
pub fn draw_image_with_sampling_options(
&self,
image: impl AsRef<Image>,
left_top: impl Into<Point>,
sampling: impl Into<SamplingOptions>,
paint: Option<&Paint>,
) -> &Self {
let left_top = left_top.into();
unsafe {
self.native_mut().drawImage(
image.as_ref().native(),
left_top.x,
left_top.y,
sampling.into().native(),
paint.native_ptr_or_null(),
)
}
self
}
pub fn draw_image_rect_with_sampling_options(
&self,
image: impl AsRef<Image>,
src: Option<(&Rect, SrcRectConstraint)>,
dst: impl AsRef<Rect>,
sampling: impl Into<SamplingOptions>,
paint: &Paint,
) -> &Self {
let sampling = sampling.into();
match src {
Some((src, constraint)) => unsafe {
self.native_mut().drawImageRect(
image.as_ref().native(),
src.native(),
dst.as_ref().native(),
sampling.native(),
>rg -n "set_color\(|set_color_foreground|set_font_style\(" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rs | head -30Exit code: 0
Wall time: 0 seconds
Output:
290: pub fn set_color(&mut self, color: impl Into<Color>) -> &mut Self {
402: pub fn set_font_style(&mut self, font_style: FontStyle) -> &mut Self {
>sed -n '284,490p' ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/skia-safe-0.93.1/src/modules/paragraph/text_style.rsExit code: 0
Wall time: 0 seconds
Output:
}
pub fn color(&self) -> Color {
Color::from_native_c(self.native().fColor)
}
pub fn set_color(&mut self, color: impl Into<Color>) -> &mut Self {
self.native_mut().fColor = color.into().into_native();
self
}
pub fn has_foreground(&self) -> bool {
self.native().fHasForeground
}
pub fn foreground(&self) -> Paint {
Paint::construct(|p| unsafe { sb::C_TextStyle_getForeground(self.native(), p) })
}
pub fn set_foreground_paint(&mut self, paint: &Paint) -> &mut Self {
unsafe { sb::C_TextStyle_setForegroundPaint(self.native_mut(), paint.native()) };
self
}
#[deprecated(since = "0.64.0", note = "use set_foreground_paint()")]
pub fn set_foreground_color(&mut self, paint: &Paint) -> &mut Self {
self.set_foreground_paint(paint)
}
pub fn clear_foreground_color(&mut self) -> &mut Self {
self.native_mut().fHasForeground = false;
self
}
pub fn has_background(&self) -> bool {
self.native().fHasBackground
}
pub fn background(&self) -> Paint {
Paint::construct(|p| unsafe { sb::C_TextStyle_getBackground(self.native(), p) })
}
pub fn set_background_paint(&mut self, paint: &Paint) -> &mut Self {
unsafe { sb::C_TextStyle_setBackgroundPaint(self.native_mut(), paint.native()) };
self
}
#[deprecated(since = "0.64.0", note = "use set_background_paint()")]
pub fn set_background_color(&mut self, paint: &Paint) -> &mut Self {
self.set_background_paint(paint)
}
pub fn clear_background_color(&mut self) -> &mut Self {
self.native_mut().fHasBackground = false;
self
}
pub fn decoration(&self) -> &Decoration {
Decoration::from_native_ref(&self.native().fDecoration)
}
pub fn decoration_type(&self) -> TextDecoration {
self.decoration().ty
}
pub fn decoration_mode(&self) -> TextDecorationMode {
self.decoration().mode
}
pub fn decoration_color(&self) -> Color {
self.decoration().color
}
pub fn decoration_style(&self) -> TextDecorationStyle {
self.decoration().style
}
pub fn decoration_thickness_multiplier(&self) -> scalar {
self.decoration().thickness_multiplier
}
pub fn set_decoration(&mut self, decoration: &Decoration) {
*self.decoration_mut_internal() = *decoration;
}
pub fn set_decoration_type(&mut self, decoration: TextDecoration) {
self.decoration_mut_internal().ty = decoration;
}
pub fn set_decoration_mode(&mut self, mode: TextDecorationMode) {
self.decoration_mut_internal().mode = mode;
}
pub fn set_decoration_style(&mut self, style: TextDecorationStyle) {
self.decoration_mut_internal().style = style;
}
pub fn set_decoration_color(&mut self, color: impl Into<Color>) {
self.decoration_mut_internal().color = color.into();
}
pub fn set_decoration_thickness_multiplier(&mut self, multiplier: scalar) {
self.decoration_mut_internal().thickness_multiplier = multiplier;
}
#[deprecated(since = "0.63.1", note = "use set_decoration()")]
pub fn decoration_mut(&mut self) -> &mut Decoration {
self.decoration_mut_internal()
}
fn decoration_mut_internal(&mut self) -> &mut Decoration {
Decoration::from_native_ref_mut(&mut self.native_mut().fDecoration)
}
pub fn font_style(&self) -> FontStyle {
FontStyle::from_native_c(self.native().fFontStyle)
}
pub fn set_font_style(&mut self, font_style: FontStyle) -> &mut Self {
self.native_mut().fFontStyle = font_style.into_native();
self
}
pub fn shadows(&self) -> &[TextShadow] {
unsafe {
let mut count = 0;
let ptr = sb::C_TextStyle_getShadows(&self.native().fTextShadows, &mut count);
safer::from_raw_parts(TextShadow::from_native_ptr(ptr), count)
}
}
pub fn add_shadow(&mut self, shadow: TextShadow) -> &mut Self {
unsafe { sb::C_TextStyle_addShadow(self.native_mut(), shadow.native()) }
self
}
pub fn reset_shadows(&mut self) -> &mut Self {
unsafe { sb::C_TextStyle_resetShadows(self.native_mut()) }
self
}
pub fn font_features(&self) -> &[FontFeature] {
unsafe {
let mut count = 0;
let ptr = sb::C_TextStyle_getFontFeatures(&self.native().fFontFeatures, &mut count);
safer::from_raw_parts(FontFeature::from_native_ptr(ptr), count)
}
}
pub fn add_font_feature(&mut self, font_feature: impl AsRef<str>, value: i32) {
let font_feature = interop::String::from_str(font_feature);
unsafe { sb::C_TextStyle_addFontFeature(self.native_mut(), font_feature.native(), value) }
}
pub fn reset_font_features(&mut self) {
unsafe { sb::C_TextStyle_resetFontFeatures(self.native_mut()) }
}
pub fn font_arguments(&self) -> Option<&FontArguments> {
unsafe { sb::C_TextStyle_getFontArguments(self.native()) }
.into_non_null()
.map(|ptr| FontArguments::from_native_ref(unsafe { ptr.as_ref() }))
}
/// The contents of the [`crate::FontArguments`] will be copied into the [`TextStyle`].
pub fn set_font_arguments<'fa>(
&mut self,
arguments: impl Into<Option<&'fa crate::FontArguments<'fa, 'fa>>>,
) {
unsafe {
sb::C_TextStyle_setFontArguments(
self.native_mut(),
arguments.into().native_ptr_or_null(),
)
}
}
pub fn font_size(&self) -> scalar {
self.native().fFontSize
}
pub fn set_font_size(&mut self, size: scalar) -> &mut Self {
self.native_mut().fFontSize = size;
self
}
pub fn font_families(&self) -> FontFamilies {
unsafe {
let mut count = 0;
let ptr = sb::C_TextStyle_getFontFamilies(self.native(), &mut count);
FontFamilies(safer::from_raw_parts(ptr, count))
}
}
pub fn set_font_families(&mut self, families: &[impl AsRef<str>]) -> &mut Self {
let families: Vec<interop::String> = FromStrs::from_strs(families);
let families = families.native();
unsafe {
sb::C_TextStyle_setFontFamilies(self.native_mut(), families.as_ptr(), families.len())
}
self
}
pub fn baseline_shift(&self) -> scalar {
self.native().fBaselineShift
}
>rg -n "pub fn children\(" ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/tree/taffy_tree.rsExit code: 0
Wall time: 0 seconds
Output:
828: pub fn children(&self, parent: NodeId) -> TaffyResult<Vec<NodeId>> {
The core implementation is now in place for the first slice: specialized template parsing, param substitution, style parsing, Taffy layout, Skia raster drawing, and pooled renders. I’m running the suite again with a longer timeout because rust-skia’s first build is the slow part.
>cargo test -p taffy-canvas-coreExit code: 101
Wall time: 45.2 seconds
Output:
Compiling skia-bindings v0.93.1
Compiling skia-safe v0.93.1
Compiling taffy-canvas-core v0.1.0 (/Users/dj/Developer/taffy-canvas/crates/taffy-canvas-core)
error[E0252]: the name `TextMeasurer` is defined multiple times
--> crates/taffy-canvas-core/src/layout.rs:13:42
|
9 | text::{TextMeasurer, TextMetrics},
| ------------ previous import of the trait `TextMeasurer` here
...
13 | pub use crate::text::{FixedTextMeasurer, TextMeasurer};
| ^^^^^^^^^^^^ `TextMeasurer` reimported here
|
= note: `TextMeasurer` must be defined only once in the type namespace of this module
error[E0432]: unresolved import `taffy::prelude::Point`
--> crates/taffy-canvas-core/src/layout.rs:2:145
|
2 | ...tent, LengthPercentage, LengthPercentageAuto, Line, Point, Rect, Size, Style, TaffyTree},
| ^^^^^ no `Point` in `prelude`
|
= help: consider importing one of these structs instead:
skia_safe::Point
taffy::Point
error[E0603]: trait import `TextMeasurer` is private
--> crates/taffy-canvas-core/src/render.rs:10:31
|
10 | layout::{layout_document, TextMeasurer},
| ^^^^^^^^^^^^ private trait import
|
note: the trait import `TextMeasurer` is defined here...
--> crates/taffy-canvas-core/src/layout.rs:9:12
|
9 | text::{TextMeasurer, TextMetrics},
| ^^^^^^^^^^^^
note: ...and refers to the trait `TextMeasurer` which is defined here
--> crates/taffy-canvas-core/src/text.rs:9:1
|
9 | pub trait TextMeasurer: Send + Sync {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly
help: import `TextMeasurer` through the re-export
|
10 | layout::{layout_document, text::TextMeasurer},
| ++++++
error[E0603]: trait import `TextMeasurer` is private
--> crates/taffy-canvas-core/src/lib.rs:18:54
|
18 | pub use layout::{layout_document, FixedTextMeasurer, TextMeasurer};
| ^^^^^^^^^^^^ private trait import
|
note: the trait import `TextMeasurer` is defined here...
--> crates/taffy-canvas-core/src/layout.rs:9:12
|
9 | text::{TextMeasurer, TextMetrics},
| ^^^^^^^^^^^^
note: ...and refers to the trait `TextMeasurer` which is defined here
--> crates/taffy-canvas-core/src/text.rs:9:1
|
9 | pub trait TextMeasurer: Send + Sync {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly
help: import `TextMeasurer` through the re-export
|
18 | pub use layout::{layout_document, FixedTextMeasurer, text::TextMeasurer};
| ++++++
warning: unused import: `Line`
--> crates/taffy-canvas-core/src/layout.rs:2:139
|
2 | ...rection, JustifyContent, LengthPercentage, LengthPercentageAuto, Line, Point, Rect, Size, Style, TaffyTree},
| ^^^^
|
= note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default
warning: unused import: `TextMeasurer`
--> crates/taffy-canvas-core/src/layout.rs:13:42
|
13 | pub use crate::text::{FixedTextMeasurer, TextMeasurer};
| ^^^^^^^^^^^^
Some errors have detailed explanations: E0252, E0432, E0603.
For more information about an error, try `rustc --explain E0252`.
warning: `taffy-canvas-core` (lib) generated 2 warnings
error: could not compile `taffy-canvas-core` (lib) due to 4 previous errors; 2 warnings emitted
warning: build failed, waiting for other jobs to finish...
The first post-implementation run is useful now: this is down to normal Rust API mismatches, not design gaps. I’m fixing the import/export issues and rerunning immediately.
>cargo test -p taffy-canvas-coreExit code: 101
Wall time: 0.5 seconds
Output:
Compiling taffy-canvas-core v0.1.0 (/Users/dj/Developer/taffy-canvas/crates/taffy-canvas-core)
error[E0599]: no associated item named `Auto` found for struct `Dimension` in the current scope
--> crates/taffy-canvas-core/src/layout.rs:123:72
|
123 | width: style.width.map(Dimension::length).unwrap_or(Dimension::Auto),
| ^^^^ associated item not found in `Dimension`
|
help: there is an associated function `auto` with a similar name
--> /Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/dimension.rs:290:5
|
290 | pub const fn auto() -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0599]: no associated item named `Auto` found for struct `Dimension` in the current scope
--> crates/taffy-canvas-core/src/layout.rs:124:74
|
124 | height: style.height.map(Dimension::length).unwrap_or(Dimension::Auto),
| ^^^^ associated item not found in `Dimension`
|
help: there is an associated function `auto` with a similar name
--> /Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/dimension.rs:290:5
|
290 | pub const fn auto() -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0599]: no associated item named `Auto` found for struct `Dimension` in the current scope
--> crates/taffy-canvas-core/src/layout.rs:127:76
|
127 | width: style.min_width.map(Dimension::length).unwrap_or(Dimension::Auto),
| ^^^^ associated item not found in `Dimension`
|
help: there is an associated function `auto` with a similar name
--> /Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/dimension.rs:290:5
|
290 | pub const fn auto() -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0599]: no associated item named `Auto` found for struct `Dimension` in the current scope
--> crates/taffy-canvas-core/src/layout.rs:128:78
|
128 | height: style.min_height.map(Dimension::length).unwrap_or(Dimension::Auto),
| ^^^^ associated item not found in `Dimension`
|
help: there is an associated function `auto` with a similar name
--> /Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/dimension.rs:290:5
|
290 | pub const fn auto() -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0599]: no associated item named `Auto` found for struct `Dimension` in the current scope
--> crates/taffy-canvas-core/src/layout.rs:131:76
|
131 | width: style.max_width.map(Dimension::length).unwrap_or(Dimension::Auto),
| ^^^^ associated item not found in `Dimension`
|
help: there is an associated function `auto` with a similar name
--> /Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/dimension.rs:290:5
|
290 | pub const fn auto() -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0599]: no associated item named `Auto` found for struct `Dimension` in the current scope
--> crates/taffy-canvas-core/src/layout.rs:132:78
|
132 | height: style.max_height.map(Dimension::length).unwrap_or(Dimension::Auto),
| ^^^^ associated item not found in `Dimension`
|
help: there is an associated function `auto` with a similar name
--> /Users/dj/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/taffy-0.10.0/src/style/dimension.rs:290:5
|
290 | pub const fn auto() -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated associated function `skia_safe::surface::<impl skia_safe::RCHandle<skia_bindings::SkSurface>>::new_raster_n32_premul`: use surfaces::raster_n32_premul()
--> crates/taffy-canvas-core/src/render.rs:37:32
|
37 | let mut surface = Surface::new_raster_n32_premul((layout.width as i32, layout.height as i32))
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
warning: use of deprecated method `skia_safe::image::<impl skia_safe::RCHandle<skia_bindings::SkImage>>::encode_to_data`: Support for encoding GPU backed images without a context was removed, use `encode_to_data_with_context` instead
--> crates/taffy-canvas-core/src/render.rs:46:10
|
46 | .encode_to_data(EncodedImageFormat::PNG)
| ^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> crates/taffy-canvas-core/src/template.rs:71:57
|
59 | match reader.read_event_into(&mut buffer) {
| ----------------------------------- this expression has type `std::result::Result<Event<'_>, quick_xml::Error>`
...
71 | Ok(Event::Text(text)) | Ok(Event::CData(text)) => {
| ---- ^^^^ expected `BytesText<'_>`, found `BytesCData<'_>`
| |
| first introduced with type `BytesText<'_>` here
|
= note: in the same arm, a binding must have the same type in all alternatives
Some errors have detailed explanations: E0308, E0599.
For more information about an error, try `rustc --explain E0308`.
warning: `taffy-canvas-core` (lib) generated 2 warnings
error: could not compile `taffy-canvas-core` (lib) due to 7 previous errors; 2 warnings emitted
warning: build failed, waiting for other jobs to finish...
warning: `taffy-canvas-core` (lib test) generated 2 warnings (2 duplicates)
error: could not compile `taffy-canvas-core` (lib test) due to 7 previous errors; 2 warnings emitted
>cargo test -p taffy-canvas-coreExit code: 101
Wall time: 2.1 seconds
Output:
Compiling taffy-canvas-core v0.1.0 (/Users/dj/Developer/taffy-canvas/crates/taffy-canvas-core)
warning: use of deprecated associated function `skia_safe::surface::<impl skia_safe::RCHandle<skia_bindings::SkSurface>>::new_raster_n32_premul`: use surfaces::raster_n32_premul()
--> crates/taffy-canvas-core/src/render.rs:37:32
|
37 | let mut surface = Surface::new_raster_n32_premul((layout.width as i32, layout.height as i32))
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
warning: use of deprecated method `skia_safe::image::<impl skia_safe::RCHandle<skia_bindings::SkImage>>::encode_to_data`: Support for encoding GPU backed images without a context was removed, use `encode_to_data_with_context` instead
--> crates/taffy-canvas-core/src/render.rs:46:10
|
46 | .encode_to_data(EncodedImageFormat::PNG)
| ^^^^^^^^^^^^^^
warning: field `source` is never read
--> crates/taffy-canvas-core/src/template.rs:19:16
|
18 | pub struct Template {
| -------- field in this struct
19 | pub(crate) source: String,
| ^^^^^^
|
= note: `Template` has derived impls for the traits `Debug` and `Clone`, but these are intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
warning: `taffy-canvas-core` (lib test) generated 3 warnings (3 duplicates)
warning: `taffy-canvas-core` (lib) generated 3 warnings
error: prefix `ffffff` is unknown
--> crates/taffy-canvas-core/tests/core_flow.rs:17:25
|
17 | <text color="#ffffff">Hello {{name}}</text>
| ^^^^^^ unknown prefix
|
= note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
|
17 | <text color="#ffffff ">Hello {{name}}</text>
| +
error: prefix `ff0000` is unknown
--> crates/taffy-canvas-core/tests/core_flow.rs:37:92
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| ^^^^^^ unknown prefix
|
= note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000 " />
| +
error: prefix `ff3366` is unknown
--> crates/taffy-canvas-core/tests/core_flow.rs:57:91
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| ^^^^^^ unknown prefix
|
= note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366 " />
| +
error: prefix `ffffff` is unknown
--> crates/taffy-canvas-core/tests/core_flow.rs:82:25
|
82 | <text color="#ffffff">Hello {{name}}</text>
| ^^^^^^ unknown prefix
|
= note: prefixed identifiers and literals are reserved since Rust 2021
help: consider inserting whitespace here
|
82 | <text color="#ffffff ">Hello {{name}}</text>
| +
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `112233`
--> crates/taffy-canvas-core/tests/core_flow.rs:16:53
|
16 | <view width="320" height="180" background="#112233">
| -^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `">
<text color="`
--> crates/taffy-canvas-core/tests/core_flow.rs:16:59
|
16 | <view width="320" height="180" background="#112233">
| ^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| ___________________________________________________________help: missing `,`
| |
17 | | <text color="#ffffff">Hello {{name}}</text>
| |_______________________^ unexpected token
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `#`
--> crates/taffy-canvas-core/tests/core_flow.rs:17:24
|
17 | <text color="#ffffff">Hello {{name}}</text>
| ^ expected one of `)`, `,`, `.`, `?`, or an operator
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `">
<view width="`
--> crates/taffy-canvas-core/tests/core_flow.rs:36:59
|
36 | <view width="200" height="100" background="#ffffff">
| ^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| ___________________________________________________________help: missing `,`
| |
37 | | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| |_______________________^ unexpected token
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `50`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:24
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" height="`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:26
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^^^^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `20`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:36
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" position="absolute`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:38
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^^^^^^^^^^^^^^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" left="`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:58
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `10`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:66
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" top="`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:68
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `12`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:75
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" background="`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:77
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| -^^^^^^^^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `#`
--> crates/taffy-canvas-core/tests/core_flow.rs:37:91
|
37 | <view width="50" height="20" position="absolute" left="10" top="12" background="#ff0000" />
| ^ expected one of `)`, `,`, `.`, `?`, or an operator
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `101820`
--> crates/taffy-canvas-core/tests/core_flow.rs:56:51
|
56 | <view width="64" height="64" background="#101820">
| -^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `">
<view width="`
--> crates/taffy-canvas-core/tests/core_flow.rs:56:57
|
56 | <view width="64" height="64" background="#101820">
| ^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| _________________________________________________________help: missing `,`
| |
57 | | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| |_______________________^ unexpected token
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `20`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:24
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| -^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" height="`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:26
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| -^^^^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `20`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:36
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| -^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" position="absolute`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:38
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| -^^^^^^^^^^^^^^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" left="`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:58
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| -^^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `8`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:66
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| ^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" top="`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:67
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| -^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `10`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:74
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| -^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `" background="`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:76
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| -^^^^^^^^^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `#`
--> crates/taffy-canvas-core/tests/core_flow.rs:57:90
|
57 | <view width="20" height="20" position="absolute" left="8" top="10" background="#ff3366" />
| ^ expected one of `)`, `,`, `.`, `?`, or an operator
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `0b0f19`
--> crates/taffy-canvas-core/tests/core_flow.rs:81:52
|
81 | <view width="128" height="48" background="#0b0f19">
| -^^^^^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| help: missing `,`
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `">
<text color="`
--> crates/taffy-canvas-core/tests/core_flow.rs:81:58
|
81 | <view width="128" height="48" background="#0b0f19">
| ^
| |
| expected one of `)`, `,`, `.`, `?`, or an operator
| __________________________________________________________help: missing `,`
| |
82 | | <text color="#ffffff">Hello {{name}}</text>
| |_______________________^ unexpected token
error: expected one of `)`, `,`, `.`, `?`, or an operator, found `#`
--> crates/taffy-canvas-core/tests/core_flow.rs:82:24
|
82 | <text color="#ffffff">Hello {{name}}</text>
| ^ expected one of `)`, `,`, `.`, `?`, or an operator
warning: unused import: `Template`
--> crates/taffy-canvas-core/tests/core_flow.rs:5:34
|
5 | RenderOptions, RendererPool, Template, TemplateParams,
| ^^^^^^^^
|
= note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default
warning: `taffy-canvas-core` (test "core_flow") generated 1 warning
error: could not compile `taffy-canvas-core` (test "core_flow") due to 33 previous errors; 1 warning emitted
>cargo test -p taffy-canvas-coreExit code: 0
Wall time: 1.9 seconds
Output:
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
running 4 tests
test template_substitutes_text_and_document_size ... ok
test layout_computes_absolute_offsets ... ok
test render_outputs_expected_pixels_for_background_and_absolute_child ... ok
test renderer_pool_renders_multiple_param_sets ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
warning: use of deprecated associated function `skia_safe::surface::<impl skia_safe::RCHandle<skia_bindings::SkSurface>>::new_raster_n32_premul`: use surfaces::raster_n32_premul()
--> crates/taffy-canvas-core/src/render.rs:37:32
|
37 | let mut surface = Surface::new_raster_n32_premul((layout.width as i32, layout.height as i32))
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(deprecated)]` on by default
warning: use of deprecated method `skia_safe::image::<impl skia_safe::RCHandle<skia_bindings::SkImage>>::encode_to_data`: Support for encoding GPU backed images without a context was removed, use `encode_to_data_with_context` instead
--> crates/taffy-canvas-core/src/render.rs:46:10
|
46 | .encode_to_data(EncodedImageFormat::PNG)
| ^^^^^^^^^^^^^^
warning: field `source` is never read
--> crates/taffy-canvas-core/src/template.rs:19:16
|
18 | pub struct Template {
| -------- field in this struct
19 | pub(crate) source: String,
| ^^^^^^
|
= note: `Template` has derived impls for the traits `Debug` and `Clone`, but these are intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
warning: `taffy-canvas-core` (lib) generated 3 warnings
Compiling taffy-canvas-core v0.1.0 (/Users/dj/Developer/taffy-canvas/crates/taffy-canvas-core)
warning: `taffy-canvas-core` (lib test) generated 3 warnings (3 duplicates)
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.49s
Running unittests src/lib.rs (target/debug/deps/taffy_canvas_core-884af7166b0f7beb)
Running tests/core_flow.rs (target/debug/deps/core_flow-d305ca6008e689e4)
Doc-tests taffy_canvas_core
The first green slice is stable now: core tests pass end to end with compile, instantiate, layout, render, and pooled rendering. I’m going to commit this checkpoint, then I’ll extend the Node wrapper and add a usable benchmark run on top of it.
>git status --shortExit code: 0
Wall time: 0 seconds
Output:
?? .gitignore
?? Cargo.lock
?? Cargo.toml
?? crates/
>git add . && git commit -m "Scaffold core template renderer"Exit code: 128
Wall time: 0 seconds
Output:
error: 'crates/taffy-canvas-core/' does not have a commit checked out
fatal: adding files failed
cargo new created nested git repos inside each crate, which blocks staging from the workspace root. I’m removing those nested .git directories because they’re just scaffold artifacts I created, then I’ll retry the commit from the actual project root.
>rm -rf crates/taffy-canvas-core/.git crates/taffy-canvas-node/.gitExit code: 0
Wall time: 0 seconds
Output:
>find crates -maxdepth 2 -name .git -type dExit code: 0
Wall time: 0 seconds
Output:
crates/taffy-canvas-core/.git
crates/taffy-canvas-node/.git
>find crates -maxdepth 2 -name .git -type dExit code: 0
Wall time: 0 seconds
Output: