@meonode/canvas 1.5.4 → 1.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/canvas/grid.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/grid.canvas.util.js +13 -6
- package/dist/cjs/canvas/grid.canvas.util.js.map +1 -1
- package/dist/cjs/canvas/image.canvas.util.d.ts +2 -1
- package/dist/cjs/canvas/image.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/image.canvas.util.js +7 -3
- package/dist/cjs/canvas/image.canvas.util.js.map +1 -1
- package/dist/cjs/canvas/root.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/root.canvas.util.js +11 -4
- package/dist/cjs/canvas/root.canvas.util.js.map +1 -1
- package/dist/esm/canvas/grid.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/grid.canvas.util.js +13 -6
- package/dist/esm/canvas/image.canvas.util.d.ts +2 -1
- package/dist/esm/canvas/image.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/image.canvas.util.js +7 -3
- package/dist/esm/canvas/root.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/root.canvas.util.js +11 -4
- package/package.json +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/grid.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACtF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAIjE;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,OAAO;gBAC3B,KAAK,EAAE,aAAa;CAMjC;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,aAAa,iBAA4B,CAAA;AAEzE;;;GAGG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC;;;OAGG;gBACS,KAAK,EAAE,SAAS;IAQ5B;;OAEG;IACH,OAAO,CAAC,UAAU;IAwBlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAmBpB;;OAEG;cACgB,+BAA+B;
|
|
1
|
+
{"version":3,"file":"grid.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/grid.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACtF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAIjE;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,OAAO;gBAC3B,KAAK,EAAE,aAAa;CAMjC;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,aAAa,iBAA4B,CAAA;AAEzE;;;GAGG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC;;;OAGG;gBACS,KAAK,EAAE,SAAS;IAQ5B;;OAEG;IACH,OAAO,CAAC,UAAU;IAwBlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAmBpB;;OAEG;cACgB,+BAA+B;IAoTlD;;OAEG;IACH,OAAO,CAAC,aAAa;CAkCtB;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,SAAS,aAAwB,CAAA"}
|
|
@@ -77,15 +77,22 @@ class GridNode extends layout_canvas_util.RowNode {
|
|
|
77
77
|
const parent = this.node.getParent();
|
|
78
78
|
if (parent) {
|
|
79
79
|
const parentWidth = parent.getWidth();
|
|
80
|
+
const parentMinWidth = parent.getMinWidth();
|
|
80
81
|
const parentMaxWidth = parent.getMaxWidth();
|
|
81
|
-
//
|
|
82
|
-
|
|
82
|
+
// Parent has % minWidth but no hard width/maxWidth constraint
|
|
83
|
+
const hasPercentMinWidth = parentMinWidth.unit === common_const.Style.Unit.Percent;
|
|
84
|
+
const hasExplicitWidth = parentWidth.unit !== common_const.Style.Unit.Undefined && parentWidth.unit !== common_const.Style.Unit.Auto;
|
|
85
|
+
const hasMaxWidth = parentMaxWidth.unit !== common_const.Style.Unit.Undefined && parentMaxWidth.unit !== common_const.Style.Unit.Auto;
|
|
86
|
+
if (hasPercentMinWidth && !hasExplicitWidth && !hasMaxWidth) {
|
|
83
87
|
const grandparent = parent.getParent();
|
|
84
88
|
if (grandparent) {
|
|
85
|
-
const
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
const intendedWidth = (parentMinWidth.value / 100) * grandparent.getComputedWidth();
|
|
90
|
+
// Check if parent has flexGrow - if so, don't constrain
|
|
91
|
+
const parentFlexGrow = parent.getFlexGrow();
|
|
92
|
+
if (parentFlexGrow > 0) ;
|
|
93
|
+
else {
|
|
94
|
+
// No flexGrow - constrain to minWidth
|
|
95
|
+
width = Math.min(width, intendedWidth);
|
|
89
96
|
}
|
|
90
97
|
}
|
|
91
98
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.canvas.util.js","sources":["../../../../src/canvas/grid.canvas.util.ts"],"sourcesContent":["import type { GridProps, GridTrackSize, GridItemProps } from '@/canvas/canvas.type.js'\nimport { BoxNode, RowNode } from '@/canvas/layout.canvas.util.js'\nimport { Style } from '@/constant/common.const.js'\nimport { parsePercentage } from '@/canvas/canvas.helper.js'\n\n/**\n * GridItem Node. Theoretically just a BoxNode but typed differently in factory.\n * In runtime, it behaves almost like a BoxNode, but we can detect it if needed,\n * or simply rely on the props being present in the instance.\n */\nexport class GridItemNode extends BoxNode {\n constructor(props: GridItemProps) {\n super({\n ...props,\n name: 'GridItem',\n })\n }\n}\n\n/**\n * Factory for GridItem.\n */\nexport const GridItem = (props: GridItemProps) => new GridItemNode(props)\n\n/**\n * Grid layout node that arranges children in a 2D grid.\n * Implements a simplified version of the CSS Grid Layout algorithm.\n */\nexport class GridNode extends RowNode {\n /**\n * Creates a new grid layout node\n * @param props Grid configuration properties\n */\n constructor(props: GridProps) {\n super({\n ...props,\n name: props.name || 'Grid',\n flexWrap: Style.Wrap.Wrap,\n })\n }\n\n /**\n * Helper to parse a track size definition.\n */\n private parseTrack(track: GridTrackSize, availableSpace: number): { type: 'px' | '%' | 'fr' | 'auto'; value: number } {\n if (typeof track === 'number') {\n return { type: 'px', value: track }\n }\n if (track === 'auto') {\n return { type: 'auto', value: 0 }\n }\n if (typeof track === 'string') {\n if (track.endsWith('fr')) {\n return { type: 'fr', value: parseFloat(track) }\n }\n if (track.endsWith('%')) {\n return { type: '%', value: parsePercentage(track, availableSpace) }\n }\n if (track.endsWith('px')) {\n return { type: 'px', value: parseFloat(track) }\n }\n // Try parsing as number (px) if just string \"100\"\n const num = parseFloat(track)\n if (!isNaN(num)) return { type: 'px', value: num }\n }\n return { type: 'auto', value: 0 }\n }\n\n /**\n * Parses the gap property into pixels.\n */\n private getGapPixels(gap: GridProps['gap'], width: number, height: number) {\n let rowGap = 0\n let colGap = 0\n\n if (typeof gap === 'number') {\n rowGap = colGap = gap\n } else if (typeof gap === 'string') {\n const val = parsePercentage(gap, width) // Use width as base for simplicity if %\n rowGap = colGap = val\n } else if (gap && typeof gap === 'object') {\n const colVal = gap.Column ?? gap.All ?? 0\n const rowVal = gap.Row ?? gap.All ?? 0\n colGap = parsePercentage(colVal as string | number, width)\n rowGap = parsePercentage(rowVal as string | number, height)\n }\n\n return { rowGap, colGap }\n }\n\n /**\n * Update layout calculations after the initial layout is computed.\n */\n protected override updateLayoutBasedOnComputedSize() {\n // 1. Get Container Dimensions\n let width = this.node.getComputedWidth()\n const parent = this.node.getParent()\n\n if (parent) {\n const parentWidth = parent.getWidth()\n const parentMaxWidth = parent.getMaxWidth()\n\n // Case: Parent has % width but no maxWidth - we're likely expanding it\n if (parentWidth.unit === Style.Unit.Percent && (parentMaxWidth.unit === Style.Unit.Undefined || parentMaxWidth.unit === Style.Unit.Auto)) {\n const grandparent = parent.getParent()\n if (grandparent) {\n const intended = (parentWidth.value / 100) * grandparent.getComputedWidth()\n // Only constrain if we expanded beyond intended (don't shrink if already smaller)\n if (width > intended) {\n width = intended\n }\n }\n }\n }\n\n const paddingLeft = this.node.getComputedPadding(Style.Edge.Left)\n const paddingRight = this.node.getComputedPadding(Style.Edge.Right)\n const paddingTop = this.node.getComputedPadding(Style.Edge.Top)\n const paddingBottom = this.node.getComputedPadding(Style.Edge.Bottom)\n\n const contentWidth = Math.max(0, width - paddingLeft - paddingRight)\n const computedHeight = this.node.getComputedHeight()\n const contentHeight = Math.max(0, computedHeight - paddingTop - paddingBottom)\n\n const { templateColumns, templateRows, autoRows = 'auto', gap, columns } = this.props as GridProps\n\n // 2. Resolve Gaps\n const { rowGap, colGap } = this.getGapPixels(gap, contentWidth, contentHeight)\n\n // 3. Resolve Columns (Tracks)\n let explicitColTracks: GridTrackSize[] = templateColumns || []\n if (explicitColTracks.length === 0 && columns) {\n explicitColTracks = Array(columns).fill('1fr')\n }\n if (explicitColTracks.length === 0) explicitColTracks = ['1fr']\n\n const resolvedColTracks = this.resolveTracks(explicitColTracks, contentWidth, colGap)\n\n // Pre-calculate Col Offsets needed for placement/width\n const colOffsetsValues = [0]\n for (let i = 0; i < resolvedColTracks.length; i++) {\n colOffsetsValues.push(colOffsetsValues[i] + resolvedColTracks[i] + colGap)\n }\n\n // 4. Place Items & Resolve Explicit Row Tracks\n const explicitRowTracks = templateRows || []\n const resolvedExplicitRowTracks = this.resolveTracks(explicitRowTracks, contentHeight, rowGap)\n\n const cells: boolean[][] = [] // true if occupied\n const items: { node: BoxNode; rowStart: number; rowEnd: number; colStart: number; colEnd: number }[] = []\n\n const isOccupied = (r: number, c: number) => {\n if (!cells[r]) return false\n return cells[r][c] === true\n }\n const setOccupied = (r: number, c: number) => {\n if (!cells[r]) cells[r] = []\n cells[r][c] = true\n }\n\n let cursorRow = 0\n let cursorCol = 0\n\n for (const child of this.children) {\n const childProps = child.props as GridItemProps\n const { gridColumn, gridRow } = childProps\n\n let colStart: number | undefined\n let colEnd: number | undefined\n let colSpan = 1\n let rowStart: number | undefined\n let rowEnd: number | undefined\n let rowSpan = 1\n\n // ... Grid Placement Logic ...\n if (gridColumn) {\n const parts = gridColumn.split('/').map(s => s.trim())\n if (parts[0]) {\n if (parts[0].startsWith('span')) {\n colSpan = parseInt(parts[0].replace('span', '')) || 1\n } else {\n colStart = parseInt(parts[0]) - 1\n }\n }\n if (parts[1]) {\n if (parts[1].startsWith('span')) {\n const span = parseInt(parts[1].replace('span', '')) || 1\n if (colStart !== undefined) {\n colEnd = colStart + span\n colSpan = span\n } else {\n // If start is undefined but end is span? Unusual. Treat as span.\n colSpan = span\n }\n } else {\n colEnd = parseInt(parts[1]) - 1\n if (colStart !== undefined) {\n colSpan = colEnd - colStart\n }\n }\n }\n }\n\n if (gridRow) {\n const parts = gridRow.split('/').map(s => s.trim())\n if (parts[0]) {\n if (parts[0].startsWith('span')) {\n rowSpan = parseInt(parts[0].replace('span', '')) || 1\n } else {\n rowStart = parseInt(parts[0]) - 1\n }\n }\n if (parts[1]) {\n if (parts[1].startsWith('span')) {\n const span = parseInt(parts[1].replace('span', '')) || 1\n if (rowStart !== undefined) {\n rowEnd = rowStart + span\n rowSpan = span\n } else {\n rowSpan = span\n }\n } else {\n rowEnd = parseInt(parts[1]) - 1\n if (rowStart !== undefined) {\n rowSpan = rowEnd - rowStart\n }\n }\n }\n }\n\n if (colStart !== undefined && rowStart !== undefined) {\n // Fixed position: Check overlap in simpler V1? Or just place?\n // Just place.\n } else {\n // Auto placement\n let placed = false\n while (!placed) {\n if (!cells[cursorRow]) cells[cursorRow] = []\n\n if (colStart !== undefined) cursorCol = colStart\n\n let fits = true\n for (let r = 0; r < rowSpan; r++) {\n for (let c = 0; c < colSpan; c++) {\n if (isOccupied(cursorRow + r, cursorCol + c)) {\n fits = false\n break\n }\n }\n if (!fits) break\n }\n\n if (fits) {\n rowStart = cursorRow\n colStart = cursorCol\n placed = true\n } else {\n cursorCol++\n if (cursorCol + colSpan > resolvedColTracks.length) {\n cursorCol = 0\n cursorRow++\n }\n }\n }\n cursorCol += colSpan\n if (cursorCol >= resolvedColTracks.length) {\n cursorCol = 0\n cursorRow++\n }\n }\n\n rowEnd = (rowStart ?? 0) + rowSpan\n colEnd = (colStart ?? 0) + colSpan\n\n for (let r = rowStart!; r < rowEnd!; r++) {\n for (let c = colStart!; c < colEnd!; c++) {\n setOccupied(r, c)\n }\n }\n\n // CRITICAL FIX: Pre-set width on item to ensure height calculation is accurate later\n const itemColStart = colStart!\n const itemColEnd = colEnd!\n\n // Extend local offsets if needed for spanned columns beyond track count (rare but safe)\n while (colOffsetsValues.length <= itemColEnd) {\n colOffsetsValues.push(colOffsetsValues[colOffsetsValues.length - 1] + 0 + colGap)\n }\n\n const cs = Math.min(itemColStart, colOffsetsValues.length - 1)\n const ce = Math.min(itemColEnd, colOffsetsValues.length - 1)\n const targetWidth = Math.max(0, colOffsetsValues[ce] - colOffsetsValues[cs] - colGap)\n\n child.node.setWidth(targetWidth)\n child.node.calculateLayout(targetWidth, Number.NaN, Style.Direction.LTR)\n\n // Recursively finalize nested children (e.g. inner Grids) so their\n // computed heights are accurate before we measure row sizes.\n child.finalizeLayout()\n if (child.node.isDirty()) {\n child.node.calculateLayout(targetWidth, Number.NaN, Style.Direction.LTR)\n }\n\n items.push({ node: child, rowStart: rowStart!, rowEnd: rowEnd!, colStart: itemColStart, colEnd: itemColEnd })\n }\n\n // 6. Finalize Rows (Implicit)\n const totalRowsNeeded = Math.max(resolvedExplicitRowTracks.length, ...items.map(i => i.rowEnd))\n const resolvedRowTracks = [...resolvedExplicitRowTracks]\n\n // Fill implicit rows\n for (let r = resolvedExplicitRowTracks.length; r < totalRowsNeeded; r++) {\n let rowSize = 0\n\n // Better 'auto' handling:\n if (autoRows === 'auto') {\n const rowItems = items.filter(i => i.rowStart === r && i.rowEnd - i.rowStart === 1)\n for (const item of rowItems) {\n rowSize = Math.max(rowSize, item.node.node.getComputedHeight())\n }\n } else {\n const parsed = this.parseTrack(autoRows, contentHeight)\n rowSize = parsed.value\n }\n resolvedRowTracks.push(rowSize)\n }\n\n // 6. Calculate Offsets (Rows) & Final Layout Application\n const colOffsets = colOffsetsValues // Re-use\n const rowOffsets = [0]\n for (let i = 0; i < resolvedRowTracks.length; i++) {\n let size = resolvedRowTracks[i]\n // Re-check auto-sized explicit rows (value 0)\n if (size === 0) {\n const rowItems = items.filter(it => it.rowStart === i && it.rowEnd - it.rowStart === 1)\n for (const item of rowItems) {\n size = Math.max(size, item.node.node.getComputedHeight())\n }\n resolvedRowTracks[i] = size\n }\n rowOffsets.push(rowOffsets[i] + size + rowGap)\n }\n\n // 7. Apply Positions\n for (const item of items) {\n const x = colOffsets[item.colStart] + paddingLeft\n\n while (colOffsets.length <= item.colEnd) {\n colOffsets.push(colOffsets[colOffsets.length - 1] + 0 + colGap)\n }\n\n const widthStart = colOffsets[item.colStart]\n const widthEnd = colOffsets[item.colEnd]\n const totalWidth = Math.max(0, widthEnd - widthStart - colGap)\n\n const y = rowOffsets[item.rowStart] + paddingTop\n\n const heightStart = rowOffsets[item.rowStart]\n const heightEnd = rowOffsets[item.rowEnd]\n const totalHeight = Math.max(0, heightEnd - heightStart - rowGap)\n\n const childNode = item.node.node\n\n if (childNode.getPositionType() !== Style.PositionType.Absolute) {\n childNode.setPositionType(Style.PositionType.Absolute)\n }\n\n if (childNode.getPosition(Style.Edge.Left).value !== x) {\n childNode.setPosition(Style.Edge.Left, x)\n }\n if (childNode.getPosition(Style.Edge.Top).value !== y) {\n childNode.setPosition(Style.Edge.Top, y)\n }\n\n if (childNode.getWidth().unit !== Style.Unit.Point || Math.abs(childNode.getWidth().value - totalWidth) > 0.1) {\n childNode.setWidth(totalWidth)\n }\n if (childNode.getHeight().unit !== Style.Unit.Point || Math.abs(childNode.getHeight().value - totalHeight) > 0.1) {\n childNode.setHeight(totalHeight)\n }\n }\n\n // 9. Update Grid Height\n const totalGridHeight = Math.max(0, rowOffsets[rowOffsets.length - 1] - rowGap)\n const currentHeightStyle = this.node.getHeight()\n if (currentHeightStyle.unit === Style.Unit.Auto || currentHeightStyle.unit === Style.Unit.Undefined) {\n const targetTotalHeight = totalGridHeight + paddingTop + paddingBottom\n this.node.setHeight(targetTotalHeight)\n }\n }\n\n /**\n * Resolves track sizes to pixels.\n */\n private resolveTracks(tracks: GridTrackSize[], availableSpace: number, gap: number): number[] {\n const resolved: number[] = []\n let usedSpace = 0\n let totalFr = 0\n const frIndices: number[] = []\n\n tracks.forEach((t, i) => {\n const parsed = this.parseTrack(t, availableSpace)\n if (parsed.type === 'px' || parsed.type === '%') {\n resolved[i] = parsed.value\n usedSpace += parsed.value\n } else if (parsed.type === 'fr') {\n totalFr += parsed.value\n resolved[i] = 0\n frIndices.push(i)\n } else {\n resolved[i] = 0\n }\n })\n\n const totalGaps = Math.max(0, tracks.length - 1) * gap\n usedSpace += totalGaps\n\n const remainingSpace = Math.max(0, availableSpace - usedSpace)\n if (totalFr > 0) {\n frIndices.forEach(i => {\n const parsed = this.parseTrack(tracks[i], availableSpace)\n const share = (parsed.value / totalFr) * remainingSpace\n resolved[i] = share\n })\n }\n\n return resolved\n }\n}\n\n/**\n * Factory function to create a new GridNode instance.\n */\nexport const Grid = (props: GridProps) => new GridNode(props)\n"],"names":["RowNode","Style","parsePercentage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"grid.canvas.util.js","sources":["../../../../src/canvas/grid.canvas.util.ts"],"sourcesContent":["import type { GridProps, GridTrackSize, GridItemProps } from '@/canvas/canvas.type.js'\nimport { BoxNode, RowNode } from '@/canvas/layout.canvas.util.js'\nimport { Style } from '@/constant/common.const.js'\nimport { parsePercentage } from '@/canvas/canvas.helper.js'\n\n/**\n * GridItem Node. Theoretically just a BoxNode but typed differently in factory.\n * In runtime, it behaves almost like a BoxNode, but we can detect it if needed,\n * or simply rely on the props being present in the instance.\n */\nexport class GridItemNode extends BoxNode {\n constructor(props: GridItemProps) {\n super({\n ...props,\n name: 'GridItem',\n })\n }\n}\n\n/**\n * Factory for GridItem.\n */\nexport const GridItem = (props: GridItemProps) => new GridItemNode(props)\n\n/**\n * Grid layout node that arranges children in a 2D grid.\n * Implements a simplified version of the CSS Grid Layout algorithm.\n */\nexport class GridNode extends RowNode {\n /**\n * Creates a new grid layout node\n * @param props Grid configuration properties\n */\n constructor(props: GridProps) {\n super({\n ...props,\n name: props.name || 'Grid',\n flexWrap: Style.Wrap.Wrap,\n })\n }\n\n /**\n * Helper to parse a track size definition.\n */\n private parseTrack(track: GridTrackSize, availableSpace: number): { type: 'px' | '%' | 'fr' | 'auto'; value: number } {\n if (typeof track === 'number') {\n return { type: 'px', value: track }\n }\n if (track === 'auto') {\n return { type: 'auto', value: 0 }\n }\n if (typeof track === 'string') {\n if (track.endsWith('fr')) {\n return { type: 'fr', value: parseFloat(track) }\n }\n if (track.endsWith('%')) {\n return { type: '%', value: parsePercentage(track, availableSpace) }\n }\n if (track.endsWith('px')) {\n return { type: 'px', value: parseFloat(track) }\n }\n // Try parsing as number (px) if just string \"100\"\n const num = parseFloat(track)\n if (!isNaN(num)) return { type: 'px', value: num }\n }\n return { type: 'auto', value: 0 }\n }\n\n /**\n * Parses the gap property into pixels.\n */\n private getGapPixels(gap: GridProps['gap'], width: number, height: number) {\n let rowGap = 0\n let colGap = 0\n\n if (typeof gap === 'number') {\n rowGap = colGap = gap\n } else if (typeof gap === 'string') {\n const val = parsePercentage(gap, width) // Use width as base for simplicity if %\n rowGap = colGap = val\n } else if (gap && typeof gap === 'object') {\n const colVal = gap.Column ?? gap.All ?? 0\n const rowVal = gap.Row ?? gap.All ?? 0\n colGap = parsePercentage(colVal as string | number, width)\n rowGap = parsePercentage(rowVal as string | number, height)\n }\n\n return { rowGap, colGap }\n }\n\n /**\n * Update layout calculations after the initial layout is computed.\n */\n protected override updateLayoutBasedOnComputedSize() {\n // 1. Get Container Dimensions\n let width = this.node.getComputedWidth()\n const parent = this.node.getParent()\n\n if (parent) {\n const parentWidth = parent.getWidth()\n const parentMinWidth = parent.getMinWidth()\n const parentMaxWidth = parent.getMaxWidth()\n\n // Parent has % minWidth but no hard width/maxWidth constraint\n const hasPercentMinWidth = parentMinWidth.unit === Style.Unit.Percent\n const hasExplicitWidth = parentWidth.unit !== Style.Unit.Undefined && parentWidth.unit !== Style.Unit.Auto\n const hasMaxWidth = parentMaxWidth.unit !== Style.Unit.Undefined && parentMaxWidth.unit !== Style.Unit.Auto\n\n if (hasPercentMinWidth && !hasExplicitWidth && !hasMaxWidth) {\n const grandparent = parent.getParent()\n if (grandparent) {\n const intendedWidth = (parentMinWidth.value / 100) * grandparent.getComputedWidth()\n\n // Check if parent has flexGrow - if so, don't constrain\n const parentFlexGrow = parent.getFlexGrow()\n if (parentFlexGrow > 0) {\n // Allow expansion - use computed width\n } else {\n // No flexGrow - constrain to minWidth\n width = Math.min(width, intendedWidth)\n }\n }\n }\n }\n\n const paddingLeft = this.node.getComputedPadding(Style.Edge.Left)\n const paddingRight = this.node.getComputedPadding(Style.Edge.Right)\n const paddingTop = this.node.getComputedPadding(Style.Edge.Top)\n const paddingBottom = this.node.getComputedPadding(Style.Edge.Bottom)\n\n const contentWidth = Math.max(0, width - paddingLeft - paddingRight)\n const computedHeight = this.node.getComputedHeight()\n const contentHeight = Math.max(0, computedHeight - paddingTop - paddingBottom)\n\n const { templateColumns, templateRows, autoRows = 'auto', gap, columns } = this.props as GridProps\n\n // 2. Resolve Gaps\n const { rowGap, colGap } = this.getGapPixels(gap, contentWidth, contentHeight)\n\n // 3. Resolve Columns (Tracks)\n let explicitColTracks: GridTrackSize[] = templateColumns || []\n if (explicitColTracks.length === 0 && columns) {\n explicitColTracks = Array(columns).fill('1fr')\n }\n if (explicitColTracks.length === 0) explicitColTracks = ['1fr']\n\n const resolvedColTracks = this.resolveTracks(explicitColTracks, contentWidth, colGap)\n\n // Pre-calculate Col Offsets needed for placement/width\n const colOffsetsValues = [0]\n for (let i = 0; i < resolvedColTracks.length; i++) {\n colOffsetsValues.push(colOffsetsValues[i] + resolvedColTracks[i] + colGap)\n }\n\n // 4. Place Items & Resolve Explicit Row Tracks\n const explicitRowTracks = templateRows || []\n const resolvedExplicitRowTracks = this.resolveTracks(explicitRowTracks, contentHeight, rowGap)\n\n const cells: boolean[][] = [] // true if occupied\n const items: { node: BoxNode; rowStart: number; rowEnd: number; colStart: number; colEnd: number }[] = []\n\n const isOccupied = (r: number, c: number) => {\n if (!cells[r]) return false\n return cells[r][c] === true\n }\n const setOccupied = (r: number, c: number) => {\n if (!cells[r]) cells[r] = []\n cells[r][c] = true\n }\n\n let cursorRow = 0\n let cursorCol = 0\n\n for (const child of this.children) {\n const childProps = child.props as GridItemProps\n const { gridColumn, gridRow } = childProps\n\n let colStart: number | undefined\n let colEnd: number | undefined\n let colSpan = 1\n let rowStart: number | undefined\n let rowEnd: number | undefined\n let rowSpan = 1\n\n // ... Grid Placement Logic ...\n if (gridColumn) {\n const parts = gridColumn.split('/').map(s => s.trim())\n if (parts[0]) {\n if (parts[0].startsWith('span')) {\n colSpan = parseInt(parts[0].replace('span', '')) || 1\n } else {\n colStart = parseInt(parts[0]) - 1\n }\n }\n if (parts[1]) {\n if (parts[1].startsWith('span')) {\n const span = parseInt(parts[1].replace('span', '')) || 1\n if (colStart !== undefined) {\n colEnd = colStart + span\n colSpan = span\n } else {\n // If start is undefined but end is span? Unusual. Treat as span.\n colSpan = span\n }\n } else {\n colEnd = parseInt(parts[1]) - 1\n if (colStart !== undefined) {\n colSpan = colEnd - colStart\n }\n }\n }\n }\n\n if (gridRow) {\n const parts = gridRow.split('/').map(s => s.trim())\n if (parts[0]) {\n if (parts[0].startsWith('span')) {\n rowSpan = parseInt(parts[0].replace('span', '')) || 1\n } else {\n rowStart = parseInt(parts[0]) - 1\n }\n }\n if (parts[1]) {\n if (parts[1].startsWith('span')) {\n const span = parseInt(parts[1].replace('span', '')) || 1\n if (rowStart !== undefined) {\n rowEnd = rowStart + span\n rowSpan = span\n } else {\n rowSpan = span\n }\n } else {\n rowEnd = parseInt(parts[1]) - 1\n if (rowStart !== undefined) {\n rowSpan = rowEnd - rowStart\n }\n }\n }\n }\n\n if (colStart !== undefined && rowStart !== undefined) {\n // Fixed position: Check overlap in simpler V1? Or just place?\n // Just place.\n } else {\n // Auto placement\n let placed = false\n while (!placed) {\n if (!cells[cursorRow]) cells[cursorRow] = []\n\n if (colStart !== undefined) cursorCol = colStart\n\n let fits = true\n for (let r = 0; r < rowSpan; r++) {\n for (let c = 0; c < colSpan; c++) {\n if (isOccupied(cursorRow + r, cursorCol + c)) {\n fits = false\n break\n }\n }\n if (!fits) break\n }\n\n if (fits) {\n rowStart = cursorRow\n colStart = cursorCol\n placed = true\n } else {\n cursorCol++\n if (cursorCol + colSpan > resolvedColTracks.length) {\n cursorCol = 0\n cursorRow++\n }\n }\n }\n cursorCol += colSpan\n if (cursorCol >= resolvedColTracks.length) {\n cursorCol = 0\n cursorRow++\n }\n }\n\n rowEnd = (rowStart ?? 0) + rowSpan\n colEnd = (colStart ?? 0) + colSpan\n\n for (let r = rowStart!; r < rowEnd!; r++) {\n for (let c = colStart!; c < colEnd!; c++) {\n setOccupied(r, c)\n }\n }\n\n // CRITICAL FIX: Pre-set width on item to ensure height calculation is accurate later\n const itemColStart = colStart!\n const itemColEnd = colEnd!\n\n // Extend local offsets if needed for spanned columns beyond track count (rare but safe)\n while (colOffsetsValues.length <= itemColEnd) {\n colOffsetsValues.push(colOffsetsValues[colOffsetsValues.length - 1] + 0 + colGap)\n }\n\n const cs = Math.min(itemColStart, colOffsetsValues.length - 1)\n const ce = Math.min(itemColEnd, colOffsetsValues.length - 1)\n const targetWidth = Math.max(0, colOffsetsValues[ce] - colOffsetsValues[cs] - colGap)\n\n child.node.setWidth(targetWidth)\n child.node.calculateLayout(targetWidth, Number.NaN, Style.Direction.LTR)\n\n // Recursively finalize nested children (e.g. inner Grids) so their\n // computed heights are accurate before we measure row sizes.\n child.finalizeLayout()\n if (child.node.isDirty()) {\n child.node.calculateLayout(targetWidth, Number.NaN, Style.Direction.LTR)\n }\n\n items.push({ node: child, rowStart: rowStart!, rowEnd: rowEnd!, colStart: itemColStart, colEnd: itemColEnd })\n }\n\n // 6. Finalize Rows (Implicit)\n const totalRowsNeeded = Math.max(resolvedExplicitRowTracks.length, ...items.map(i => i.rowEnd))\n const resolvedRowTracks = [...resolvedExplicitRowTracks]\n\n // Fill implicit rows\n for (let r = resolvedExplicitRowTracks.length; r < totalRowsNeeded; r++) {\n let rowSize = 0\n\n // Better 'auto' handling:\n if (autoRows === 'auto') {\n const rowItems = items.filter(i => i.rowStart === r && i.rowEnd - i.rowStart === 1)\n for (const item of rowItems) {\n rowSize = Math.max(rowSize, item.node.node.getComputedHeight())\n }\n } else {\n const parsed = this.parseTrack(autoRows, contentHeight)\n rowSize = parsed.value\n }\n resolvedRowTracks.push(rowSize)\n }\n\n // 6. Calculate Offsets (Rows) & Final Layout Application\n const colOffsets = colOffsetsValues // Re-use\n const rowOffsets = [0]\n for (let i = 0; i < resolvedRowTracks.length; i++) {\n let size = resolvedRowTracks[i]\n // Re-check auto-sized explicit rows (value 0)\n if (size === 0) {\n const rowItems = items.filter(it => it.rowStart === i && it.rowEnd - it.rowStart === 1)\n for (const item of rowItems) {\n size = Math.max(size, item.node.node.getComputedHeight())\n }\n resolvedRowTracks[i] = size\n }\n rowOffsets.push(rowOffsets[i] + size + rowGap)\n }\n\n // 7. Apply Positions\n for (const item of items) {\n const x = colOffsets[item.colStart] + paddingLeft\n\n while (colOffsets.length <= item.colEnd) {\n colOffsets.push(colOffsets[colOffsets.length - 1] + 0 + colGap)\n }\n\n const widthStart = colOffsets[item.colStart]\n const widthEnd = colOffsets[item.colEnd]\n const totalWidth = Math.max(0, widthEnd - widthStart - colGap)\n\n const y = rowOffsets[item.rowStart] + paddingTop\n\n const heightStart = rowOffsets[item.rowStart]\n const heightEnd = rowOffsets[item.rowEnd]\n const totalHeight = Math.max(0, heightEnd - heightStart - rowGap)\n\n const childNode = item.node.node\n\n if (childNode.getPositionType() !== Style.PositionType.Absolute) {\n childNode.setPositionType(Style.PositionType.Absolute)\n }\n\n if (childNode.getPosition(Style.Edge.Left).value !== x) {\n childNode.setPosition(Style.Edge.Left, x)\n }\n if (childNode.getPosition(Style.Edge.Top).value !== y) {\n childNode.setPosition(Style.Edge.Top, y)\n }\n\n if (childNode.getWidth().unit !== Style.Unit.Point || Math.abs(childNode.getWidth().value - totalWidth) > 0.1) {\n childNode.setWidth(totalWidth)\n }\n if (childNode.getHeight().unit !== Style.Unit.Point || Math.abs(childNode.getHeight().value - totalHeight) > 0.1) {\n childNode.setHeight(totalHeight)\n }\n }\n\n // 9. Update Grid Height\n const totalGridHeight = Math.max(0, rowOffsets[rowOffsets.length - 1] - rowGap)\n const currentHeightStyle = this.node.getHeight()\n if (currentHeightStyle.unit === Style.Unit.Auto || currentHeightStyle.unit === Style.Unit.Undefined) {\n const targetTotalHeight = totalGridHeight + paddingTop + paddingBottom\n this.node.setHeight(targetTotalHeight)\n }\n }\n\n /**\n * Resolves track sizes to pixels.\n */\n private resolveTracks(tracks: GridTrackSize[], availableSpace: number, gap: number): number[] {\n const resolved: number[] = []\n let usedSpace = 0\n let totalFr = 0\n const frIndices: number[] = []\n\n tracks.forEach((t, i) => {\n const parsed = this.parseTrack(t, availableSpace)\n if (parsed.type === 'px' || parsed.type === '%') {\n resolved[i] = parsed.value\n usedSpace += parsed.value\n } else if (parsed.type === 'fr') {\n totalFr += parsed.value\n resolved[i] = 0\n frIndices.push(i)\n } else {\n resolved[i] = 0\n }\n })\n\n const totalGaps = Math.max(0, tracks.length - 1) * gap\n usedSpace += totalGaps\n\n const remainingSpace = Math.max(0, availableSpace - usedSpace)\n if (totalFr > 0) {\n frIndices.forEach(i => {\n const parsed = this.parseTrack(tracks[i], availableSpace)\n const share = (parsed.value / totalFr) * remainingSpace\n resolved[i] = share\n })\n }\n\n return resolved\n }\n}\n\n/**\n * Factory function to create a new GridNode instance.\n */\nexport const Grid = (props: GridProps) => new GridNode(props)\n"],"names":["RowNode","Style","parsePercentage"],"mappings":"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"}
|
|
@@ -10,8 +10,9 @@ export declare class ImageNode extends BoxNode {
|
|
|
10
10
|
private loadedImage;
|
|
11
11
|
private naturalWidth;
|
|
12
12
|
private naturalHeight;
|
|
13
|
-
private
|
|
13
|
+
private loadingPromise;
|
|
14
14
|
constructor(props: ImageProps);
|
|
15
|
+
load(): Promise<void>;
|
|
15
16
|
/**
|
|
16
17
|
* Loads and processes an image from various sources (URL, file path, or Buffer).
|
|
17
18
|
* Handles SVG color modifications and sets natural dimensions with an aspect ratio.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/image.canvas.util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"image.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/image.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,KAAK,wBAAwB,EAAmC,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAsBxD;;;GAGG;AACH,qBAAa,SAAU,SAAQ,OAAO;IAC5B,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;IACrC,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,cAAc,CAA6B;gBAEvC,KAAK,EAAE,UAAU;IAYtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IA8GX,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzC;;;OAGG;cACgB,cAAc,CAAC,GAAG,EAAE,wBAAwB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAoJrH;AAED;;GAEG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,UAAU,cAAyB,CAAA"}
|
|
@@ -6,7 +6,6 @@ var canvas_helper = require('./canvas.helper.js');
|
|
|
6
6
|
var fs = require('fs');
|
|
7
7
|
var common_const = require('../constant/common.const.js');
|
|
8
8
|
|
|
9
|
-
// TODO: Add comprehensive unit tests for this file.
|
|
10
9
|
/**
|
|
11
10
|
* Calculates pixel offset for image positioning based on percentage or pixel values.
|
|
12
11
|
* This handles centering, edge alignment, and percentage-based positioning.
|
|
@@ -41,7 +40,12 @@ class ImageNode extends layout_canvas_util.BoxNode {
|
|
|
41
40
|
objectPosition: { Left: '50%', Top: '50%' },
|
|
42
41
|
...props,
|
|
43
42
|
};
|
|
44
|
-
|
|
43
|
+
}
|
|
44
|
+
load() {
|
|
45
|
+
if (!this.loadingPromise) {
|
|
46
|
+
this.loadingPromise = this._loadImage();
|
|
47
|
+
}
|
|
48
|
+
return this.loadingPromise;
|
|
45
49
|
}
|
|
46
50
|
/**
|
|
47
51
|
* Loads and processes an image from various sources (URL, file path, or Buffer).
|
|
@@ -150,7 +154,7 @@ class ImageNode extends layout_canvas_util.BoxNode {
|
|
|
150
154
|
});
|
|
151
155
|
}
|
|
152
156
|
getLoadingPromise() {
|
|
153
|
-
return this.loadingPromise ??
|
|
157
|
+
return this.loadingPromise ?? this.load();
|
|
154
158
|
}
|
|
155
159
|
/**
|
|
156
160
|
* Renders the image with correct sizing, clipping, and positioning.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.canvas.util.js","sources":["../../../../src/canvas/image.canvas.util.ts"],"sourcesContent":["// TODO: Add comprehensive unit tests for this file.\n\nimport type { BaseProps, ImageProps } from '@/canvas/canvas.type.js'\nimport { type CanvasRenderingContext2D, Image as CanvasImage, loadImage } from 'skia-canvas'\nimport { BoxNode } from '@/canvas/layout.canvas.util.js'\nimport { drawRoundedRectPath, parseBorderRadius } from '@/canvas/canvas.helper.js'\nimport { promises as fs } from 'fs'\nimport { Style } from '@/constant/common.const.js'\n\n/**\n * Calculates pixel offset for image positioning based on percentage or pixel values.\n * This handles centering, edge alignment, and percentage-based positioning.\n */\nfunction calculateOffsetFromValue(positionValue: number | `${number}%` | undefined, availableSpace: number): number {\n const value = positionValue ?? '50%'\n if (typeof value === 'number') {\n return value\n }\n if (typeof value === 'string' && value.endsWith('%')) {\n const percentage = parseFloat(value) / 100\n return availableSpace * percentage\n }\n console.warn(`[ImageNode] Invalid objectPosition value format: ${value}. Defaulting to 50%.`)\n return availableSpace * 0.5\n}\n\n/**\n * Renders images with configurable sizing, positioning, and effects.\n * Supports object-fit modes, positioning, border radius, and saturation filters.\n */\nexport class ImageNode extends BoxNode {\n declare props: ImageProps & BaseProps\n private loadedImage: CanvasImage | null = null\n private naturalWidth = 0\n private naturalHeight = 0\n private readonly loadingPromise: Promise<void> | null = null\n\n constructor(props: ImageProps) {\n super({ name: 'Image', ...props, children: undefined })\n\n this.props = {\n objectFit: 'fill',\n overflow: Style.Overflow.Hidden,\n saturate: 1,\n objectPosition: { Left: '50%', Top: '50%' },\n ...props,\n }\n\n this.loadingPromise = this._loadImage()\n }\n\n /**\n * Loads and processes an image from various sources (URL, file path, or Buffer).\n * Handles SVG color modifications and sets natural dimensions with an aspect ratio.\n * @returns Promise that resolves when image loading completes\n * @throws Error if image loading fails\n */\n private _loadImage(): Promise<void> {\n if (this.loadingPromise) return this.loadingPromise\n if (this.loadedImage) return Promise.resolve()\n\n if (!this.props.src) {\n const aspectRatioFromProps = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined\n this.node.setAspectRatio(aspectRatioFromProps)\n this.naturalWidth = 0\n this.naturalHeight = 0\n\n return Promise.resolve()\n }\n\n return new Promise(resolve => {\n const load = async () => {\n const { fileTypeFromBuffer, fileTypeFromFile } = await import('file-type')\n let finalSource: string | Buffer = this.props.src\n let isSvg = false\n let contentBuffer: Buffer | null = null\n let detectedMime: string | undefined\n\n try {\n if (typeof this.props.src === 'string') {\n if (this.props.src.startsWith('http')) {\n const response = await fetch(this.props.src)\n if (!response.ok) {\n throw new Error(`HTTP error ${response.status} fetching image: ${this.props.src}`)\n }\n const imageArrayBuffer = await response.arrayBuffer()\n contentBuffer = Buffer.from(imageArrayBuffer)\n finalSource = contentBuffer\n\n const fileTypeResult = await fileTypeFromBuffer(contentBuffer)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n\n if ((!detectedMime || detectedMime === 'application/xml') && contentBuffer.toString('utf-8').includes('<svg')) {\n isSvg = true\n }\n } else {\n finalSource = this.props.src\n const filePath = this.props.src\n\n try {\n const fileTypeResult = await fileTypeFromFile(filePath)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n\n if ((!detectedMime || detectedMime === 'application/xml') && filePath.toLowerCase().endsWith('.svg')) {\n isSvg = true\n }\n } catch {\n isSvg = filePath.toLowerCase().endsWith('.svg')\n }\n\n if (isSvg && this.props.color) {\n try {\n contentBuffer = await fs.readFile(filePath)\n } catch {\n isSvg = false\n contentBuffer = null\n }\n }\n }\n } else {\n contentBuffer = this.props.src\n finalSource = contentBuffer\n\n const fileTypeResult = await fileTypeFromBuffer(contentBuffer)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n }\n\n if (isSvg && this.props.color && contentBuffer) {\n const svgString = contentBuffer.toString('utf-8')\n const modifiedSvgString = svgString.replace(/fill=\"[^\"]*\"/g, `fill=\"${this.props.color}\"`)\n\n if (modifiedSvgString !== svgString) {\n finalSource = Buffer.from(modifiedSvgString)\n } else {\n finalSource = contentBuffer\n }\n }\n\n const img = await loadImage(finalSource as never)\n this.loadedImage = img\n this.naturalWidth = img.width\n this.naturalHeight = img.height\n\n const calculatedAspectRatio = this.naturalWidth > 0 && this.naturalHeight > 0 ? this.naturalWidth / this.naturalHeight : undefined\n\n const finalAspectRatio = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : calculatedAspectRatio\n\n this.node.setAspectRatio(finalAspectRatio)\n\n this.props.onLoad?.()\n resolve()\n } catch (error: any) {\n this.naturalWidth = 0\n this.naturalHeight = 0\n const finalAspectRatioOnError = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined\n this.node.setAspectRatio(finalAspectRatioOnError)\n this.props.onError?.(error)\n resolve()\n }\n }\n load()\n })\n }\n\n public getLoadingPromise(): Promise<void> {\n return this.loadingPromise ?? Promise.resolve()\n }\n\n /**\n * Renders the image with correct sizing, clipping, and positioning.\n * Handles object-fit, object-position, and visual effects like saturation.\n */\n protected override _renderContent(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {\n super._renderContent(ctx, x, y, width, height)\n\n if (!this.loadedImage || width <= 0 || height <= 0) return\n const img = this.loadedImage\n const imgW = this.naturalWidth\n const imgH = this.naturalHeight\n if (imgW <= 0 || imgH <= 0) return\n\n // Calculate content box accounting for padding and borders\n const paddingLeft = this.node.getComputedPadding(Style.Edge.Left)\n const paddingTop = this.node.getComputedPadding(Style.Edge.Top)\n const paddingRight = this.node.getComputedPadding(Style.Edge.Right)\n const paddingBottom = this.node.getComputedPadding(Style.Edge.Bottom)\n const borderLeft = this.node.getComputedBorder(Style.Edge.Left)\n const borderTop = this.node.getComputedBorder(Style.Edge.Top)\n const borderRight = this.node.getComputedBorder(Style.Edge.Right)\n const borderBottom = this.node.getComputedBorder(Style.Edge.Bottom)\n const contentX = x + borderLeft + paddingLeft\n const contentY = y + borderTop + paddingTop\n const contentWidth = Math.max(0, width - borderLeft - paddingLeft - borderRight - paddingRight)\n const contentHeight = Math.max(0, height - borderTop - paddingTop - borderBottom - paddingBottom)\n\n if (contentWidth <= 0 || contentHeight <= 0) return\n\n // Apply clipping for border radius\n ctx.save()\n const outerRadii = parseBorderRadius(this.props.borderRadius)\n const innerBorderRadii = {\n TopLeft: Math.max(0, outerRadii.TopLeft - borderTop),\n TopRight: Math.max(0, outerRadii.TopRight - borderTop),\n BottomRight: Math.max(0, outerRadii.BottomRight - borderBottom),\n BottomLeft: Math.max(0, outerRadii.BottomLeft - borderBottom),\n }\n const contentRadii = {\n TopLeft: Math.max(0, innerBorderRadii.TopLeft - Math.max(paddingLeft, paddingTop)),\n TopRight: Math.max(0, innerBorderRadii.TopRight - Math.max(paddingRight, paddingTop)),\n BottomRight: Math.max(0, innerBorderRadii.BottomRight - Math.max(paddingRight, paddingBottom)),\n BottomLeft: Math.max(0, innerBorderRadii.BottomLeft - Math.max(paddingLeft, paddingBottom)),\n }\n drawRoundedRectPath(ctx, contentX, contentY, contentWidth, contentHeight, contentRadii)\n ctx.clip()\n\n // Calculate image dimensions based on object-fit\n const nodeRatio = contentWidth / contentHeight\n const imgRatio = imgW / imgH\n const objectFit = this.props.objectFit\n let dw = contentWidth\n let dh = contentHeight\n\n if (objectFit === 'contain') {\n if (imgRatio > nodeRatio) {\n dw = contentWidth\n dh = contentWidth / imgRatio\n } else {\n dh = contentHeight\n dw = contentHeight * imgRatio\n }\n } else if (objectFit === 'cover') {\n if (imgRatio > nodeRatio) {\n dh = contentHeight\n dw = contentHeight * imgRatio\n } else {\n dw = contentWidth\n dh = contentWidth / imgRatio\n }\n } else if (objectFit === 'none') {\n dw = imgW\n dh = imgH\n } else if (objectFit === 'scale-down') {\n if (imgW <= contentWidth && imgH <= contentHeight) {\n dw = imgW\n dh = imgH\n } else {\n if (imgRatio > nodeRatio) {\n dw = contentWidth\n dh = contentWidth / imgRatio\n } else {\n dh = contentHeight\n dw = contentHeight * imgRatio\n }\n }\n }\n\n // Calculate image position based on object-position\n const sx = 0\n const sy = 0\n const sw = imgW\n const sh = imgH\n\n const availableWidth = contentWidth - dw\n const availableHeight = contentHeight - dh\n const posProps = this.props.objectPosition || {}\n const horizontalValue = posProps.Left !== undefined ? posProps.Left : posProps.Right !== undefined ? posProps.Right : '50%'\n const verticalValue = posProps.Top !== undefined ? posProps.Top : posProps.Bottom !== undefined ? posProps.Bottom : '50%'\n\n let offsetX = calculateOffsetFromValue(horizontalValue, availableWidth)\n let offsetY = calculateOffsetFromValue(verticalValue, availableHeight)\n\n if (posProps.Left === undefined && posProps.Right !== undefined) {\n offsetX = availableWidth - offsetX\n }\n if (posProps.Top === undefined && posProps.Bottom !== undefined) {\n offsetY = availableHeight - offsetY\n }\n\n const dx = contentX + offsetX\n const dy = contentY + offsetY\n\n // Draw image with filters\n ctx.save()\n try {\n if (this.props.dropShadow) {\n const shadow = this.props.dropShadow\n const shadowBlur = Math.max(shadow.offsetX ?? 0, shadow.offsetY ?? 0)\n ctx.shadowOffsetX = shadow.offsetX ?? 0\n ctx.shadowOffsetY = shadow.offsetY ?? 0\n ctx.shadowBlur = Math.max(0, shadow.blur ?? shadowBlur)\n ctx.shadowColor = shadow.color ?? 'black'\n }\n\n const saturateValue = this.props.saturate ?? 1\n let filterString = ''\n if (saturateValue !== 1) {\n filterString += `saturate(${saturateValue * 100}%) `\n }\n\n if (filterString) {\n const currentFilter = ctx.filter && ctx.filter !== 'none' ? ctx.filter + ' ' : ''\n ctx.filter = currentFilter + filterString.trim()\n }\n\n const finalDX = Math.floor(dx)\n const finalDY = Math.floor(dy)\n const finalDW = Math.ceil(dw + (dx - finalDX))\n const finalDH = Math.ceil(dh + (dy - finalDY))\n\n if (finalDW > 0 && finalDH > 0) {\n ctx.drawImage(img, sx, sy, sw, sh, finalDX, finalDY, finalDW, finalDH)\n }\n } catch (drawError) {\n console.error('[ImageNode] Error drawing image:', drawError)\n } finally {\n ctx.restore()\n }\n\n ctx.restore()\n }\n}\n\n/**\n * Factory function to create ImageNode instances\n */\nexport const Image = (props: ImageProps) => new ImageNode(props)\n"],"names":["BoxNode","Style","fs","loadImage","parseBorderRadius","drawRoundedRectPath"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"image.canvas.util.js","sources":["../../../../src/canvas/image.canvas.util.ts"],"sourcesContent":["import type { BaseProps, ImageProps } from '@/canvas/canvas.type.js'\nimport { type CanvasRenderingContext2D, Image as CanvasImage, loadImage } from 'skia-canvas'\nimport { BoxNode } from '@/canvas/layout.canvas.util.js'\nimport { drawRoundedRectPath, parseBorderRadius } from '@/canvas/canvas.helper.js'\nimport { promises as fs } from 'fs'\nimport { Style } from '@/constant/common.const.js'\n\n/**\n * Calculates pixel offset for image positioning based on percentage or pixel values.\n * This handles centering, edge alignment, and percentage-based positioning.\n */\nfunction calculateOffsetFromValue(positionValue: number | `${number}%` | undefined, availableSpace: number): number {\n const value = positionValue ?? '50%'\n if (typeof value === 'number') {\n return value\n }\n if (typeof value === 'string' && value.endsWith('%')) {\n const percentage = parseFloat(value) / 100\n return availableSpace * percentage\n }\n console.warn(`[ImageNode] Invalid objectPosition value format: ${value}. Defaulting to 50%.`)\n return availableSpace * 0.5\n}\n\n/**\n * Renders images with configurable sizing, positioning, and effects.\n * Supports object-fit modes, positioning, border radius, and saturation filters.\n */\nexport class ImageNode extends BoxNode {\n declare props: ImageProps & BaseProps\n private loadedImage: CanvasImage | null = null\n private naturalWidth = 0\n private naturalHeight = 0\n private loadingPromise: Promise<void> | null = null\n\n constructor(props: ImageProps) {\n super({ name: 'Image', ...props, children: undefined })\n\n this.props = {\n objectFit: 'fill',\n overflow: Style.Overflow.Hidden,\n saturate: 1,\n objectPosition: { Left: '50%', Top: '50%' },\n ...props,\n }\n }\n\n public load(): Promise<void> {\n if (!this.loadingPromise) {\n this.loadingPromise = this._loadImage()\n }\n return this.loadingPromise\n }\n\n /**\n * Loads and processes an image from various sources (URL, file path, or Buffer).\n * Handles SVG color modifications and sets natural dimensions with an aspect ratio.\n * @returns Promise that resolves when image loading completes\n * @throws Error if image loading fails\n */\n private _loadImage(): Promise<void> {\n if (this.loadingPromise) return this.loadingPromise\n if (this.loadedImage) return Promise.resolve()\n\n if (!this.props.src) {\n const aspectRatioFromProps = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined\n this.node.setAspectRatio(aspectRatioFromProps)\n this.naturalWidth = 0\n this.naturalHeight = 0\n\n return Promise.resolve()\n }\n\n return new Promise(resolve => {\n const load = async () => {\n const { fileTypeFromBuffer, fileTypeFromFile } = await import('file-type')\n let finalSource: string | Buffer = this.props.src\n let isSvg = false\n let contentBuffer: Buffer | null = null\n let detectedMime: string | undefined\n\n try {\n if (typeof this.props.src === 'string') {\n if (this.props.src.startsWith('http')) {\n const response = await fetch(this.props.src)\n if (!response.ok) {\n throw new Error(`HTTP error ${response.status} fetching image: ${this.props.src}`)\n }\n const imageArrayBuffer = await response.arrayBuffer()\n contentBuffer = Buffer.from(imageArrayBuffer)\n finalSource = contentBuffer\n\n const fileTypeResult = await fileTypeFromBuffer(contentBuffer)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n\n if ((!detectedMime || detectedMime === 'application/xml') && contentBuffer.toString('utf-8').includes('<svg')) {\n isSvg = true\n }\n } else {\n finalSource = this.props.src\n const filePath = this.props.src\n\n try {\n const fileTypeResult = await fileTypeFromFile(filePath)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n\n if ((!detectedMime || detectedMime === 'application/xml') && filePath.toLowerCase().endsWith('.svg')) {\n isSvg = true\n }\n } catch {\n isSvg = filePath.toLowerCase().endsWith('.svg')\n }\n\n if (isSvg && this.props.color) {\n try {\n contentBuffer = await fs.readFile(filePath)\n } catch {\n isSvg = false\n contentBuffer = null\n }\n }\n }\n } else {\n contentBuffer = this.props.src\n finalSource = contentBuffer\n\n const fileTypeResult = await fileTypeFromBuffer(contentBuffer)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n }\n\n if (isSvg && this.props.color && contentBuffer) {\n const svgString = contentBuffer.toString('utf-8')\n const modifiedSvgString = svgString.replace(/fill=\"[^\"]*\"/g, `fill=\"${this.props.color}\"`)\n\n if (modifiedSvgString !== svgString) {\n finalSource = Buffer.from(modifiedSvgString)\n } else {\n finalSource = contentBuffer\n }\n }\n\n const img = await loadImage(finalSource as never)\n this.loadedImage = img\n this.naturalWidth = img.width\n this.naturalHeight = img.height\n\n const calculatedAspectRatio = this.naturalWidth > 0 && this.naturalHeight > 0 ? this.naturalWidth / this.naturalHeight : undefined\n\n const finalAspectRatio = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : calculatedAspectRatio\n\n this.node.setAspectRatio(finalAspectRatio)\n\n this.props.onLoad?.()\n resolve()\n } catch (error: any) {\n this.naturalWidth = 0\n this.naturalHeight = 0\n const finalAspectRatioOnError = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined\n this.node.setAspectRatio(finalAspectRatioOnError)\n this.props.onError?.(error)\n resolve()\n }\n }\n load()\n })\n }\n\n public getLoadingPromise(): Promise<void> {\n return this.loadingPromise ?? this.load()\n }\n\n /**\n * Renders the image with correct sizing, clipping, and positioning.\n * Handles object-fit, object-position, and visual effects like saturation.\n */\n protected override _renderContent(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {\n super._renderContent(ctx, x, y, width, height)\n\n if (!this.loadedImage || width <= 0 || height <= 0) return\n const img = this.loadedImage\n const imgW = this.naturalWidth\n const imgH = this.naturalHeight\n if (imgW <= 0 || imgH <= 0) return\n\n // Calculate content box accounting for padding and borders\n const paddingLeft = this.node.getComputedPadding(Style.Edge.Left)\n const paddingTop = this.node.getComputedPadding(Style.Edge.Top)\n const paddingRight = this.node.getComputedPadding(Style.Edge.Right)\n const paddingBottom = this.node.getComputedPadding(Style.Edge.Bottom)\n const borderLeft = this.node.getComputedBorder(Style.Edge.Left)\n const borderTop = this.node.getComputedBorder(Style.Edge.Top)\n const borderRight = this.node.getComputedBorder(Style.Edge.Right)\n const borderBottom = this.node.getComputedBorder(Style.Edge.Bottom)\n const contentX = x + borderLeft + paddingLeft\n const contentY = y + borderTop + paddingTop\n const contentWidth = Math.max(0, width - borderLeft - paddingLeft - borderRight - paddingRight)\n const contentHeight = Math.max(0, height - borderTop - paddingTop - borderBottom - paddingBottom)\n\n if (contentWidth <= 0 || contentHeight <= 0) return\n\n // Apply clipping for border radius\n ctx.save()\n const outerRadii = parseBorderRadius(this.props.borderRadius)\n const innerBorderRadii = {\n TopLeft: Math.max(0, outerRadii.TopLeft - borderTop),\n TopRight: Math.max(0, outerRadii.TopRight - borderTop),\n BottomRight: Math.max(0, outerRadii.BottomRight - borderBottom),\n BottomLeft: Math.max(0, outerRadii.BottomLeft - borderBottom),\n }\n const contentRadii = {\n TopLeft: Math.max(0, innerBorderRadii.TopLeft - Math.max(paddingLeft, paddingTop)),\n TopRight: Math.max(0, innerBorderRadii.TopRight - Math.max(paddingRight, paddingTop)),\n BottomRight: Math.max(0, innerBorderRadii.BottomRight - Math.max(paddingRight, paddingBottom)),\n BottomLeft: Math.max(0, innerBorderRadii.BottomLeft - Math.max(paddingLeft, paddingBottom)),\n }\n drawRoundedRectPath(ctx, contentX, contentY, contentWidth, contentHeight, contentRadii)\n ctx.clip()\n\n // Calculate image dimensions based on object-fit\n const nodeRatio = contentWidth / contentHeight\n const imgRatio = imgW / imgH\n const objectFit = this.props.objectFit\n let dw = contentWidth\n let dh = contentHeight\n\n if (objectFit === 'contain') {\n if (imgRatio > nodeRatio) {\n dw = contentWidth\n dh = contentWidth / imgRatio\n } else {\n dh = contentHeight\n dw = contentHeight * imgRatio\n }\n } else if (objectFit === 'cover') {\n if (imgRatio > nodeRatio) {\n dh = contentHeight\n dw = contentHeight * imgRatio\n } else {\n dw = contentWidth\n dh = contentWidth / imgRatio\n }\n } else if (objectFit === 'none') {\n dw = imgW\n dh = imgH\n } else if (objectFit === 'scale-down') {\n if (imgW <= contentWidth && imgH <= contentHeight) {\n dw = imgW\n dh = imgH\n } else {\n if (imgRatio > nodeRatio) {\n dw = contentWidth\n dh = contentWidth / imgRatio\n } else {\n dh = contentHeight\n dw = contentHeight * imgRatio\n }\n }\n }\n\n // Calculate image position based on object-position\n const sx = 0\n const sy = 0\n const sw = imgW\n const sh = imgH\n\n const availableWidth = contentWidth - dw\n const availableHeight = contentHeight - dh\n const posProps = this.props.objectPosition || {}\n const horizontalValue = posProps.Left !== undefined ? posProps.Left : posProps.Right !== undefined ? posProps.Right : '50%'\n const verticalValue = posProps.Top !== undefined ? posProps.Top : posProps.Bottom !== undefined ? posProps.Bottom : '50%'\n\n let offsetX = calculateOffsetFromValue(horizontalValue, availableWidth)\n let offsetY = calculateOffsetFromValue(verticalValue, availableHeight)\n\n if (posProps.Left === undefined && posProps.Right !== undefined) {\n offsetX = availableWidth - offsetX\n }\n if (posProps.Top === undefined && posProps.Bottom !== undefined) {\n offsetY = availableHeight - offsetY\n }\n\n const dx = contentX + offsetX\n const dy = contentY + offsetY\n\n // Draw image with filters\n ctx.save()\n try {\n if (this.props.dropShadow) {\n const shadow = this.props.dropShadow\n const shadowBlur = Math.max(shadow.offsetX ?? 0, shadow.offsetY ?? 0)\n ctx.shadowOffsetX = shadow.offsetX ?? 0\n ctx.shadowOffsetY = shadow.offsetY ?? 0\n ctx.shadowBlur = Math.max(0, shadow.blur ?? shadowBlur)\n ctx.shadowColor = shadow.color ?? 'black'\n }\n\n const saturateValue = this.props.saturate ?? 1\n let filterString = ''\n if (saturateValue !== 1) {\n filterString += `saturate(${saturateValue * 100}%) `\n }\n\n if (filterString) {\n const currentFilter = ctx.filter && ctx.filter !== 'none' ? ctx.filter + ' ' : ''\n ctx.filter = currentFilter + filterString.trim()\n }\n\n const finalDX = Math.floor(dx)\n const finalDY = Math.floor(dy)\n const finalDW = Math.ceil(dw + (dx - finalDX))\n const finalDH = Math.ceil(dh + (dy - finalDY))\n\n if (finalDW > 0 && finalDH > 0) {\n ctx.drawImage(img, sx, sy, sw, sh, finalDX, finalDY, finalDW, finalDH)\n }\n } catch (drawError) {\n console.error('[ImageNode] Error drawing image:', drawError)\n } finally {\n ctx.restore()\n }\n\n ctx.restore()\n }\n}\n\n/**\n * Factory function to create ImageNode instances\n */\nexport const Image = (props: ImageProps) => new ImageNode(props)\n"],"names":["BoxNode","Style","fs","loadImage","parseBorderRadius","drawRoundedRectPath"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/root.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA8C,MAAM,aAAa,CAAA;AAChF,OAAO,EAAE,UAAU,EAAW,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAUnE,eAAO,MAAM,qBAAqB,YAEjC,CAAA;AAED;;;GAGG;AACH,qBAAa,QAAS,SAAQ,UAAU;IACtC,6CAA6C;IAC7C,OAAO,CAAC,MAAM,CAAoB;IAClC,8CAA8C;IAC9C,OAAO,CAAC,GAAG,CAAwC;IACnD,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAE9B;;;;OAIG;gBACS,KAAK,EAAE,SAAS,GAAG,SAAS;IAyCxC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"root.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/root.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA8C,MAAM,aAAa,CAAA;AAChF,OAAO,EAAE,UAAU,EAAW,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAUnE,eAAO,MAAM,qBAAqB,YAEjC,CAAA;AAED;;;GAGG;AACH,qBAAa,QAAS,SAAQ,UAAU;IACtC,6CAA6C;IAC7C,OAAO,CAAC,MAAM,CAAoB;IAClC,8CAA8C;IAC9C,OAAO,CAAC,GAAG,CAAwC;IACnD,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAE9B;;;;OAIG;gBACS,KAAK,EAAE,SAAS,GAAG,SAAS;IAyCxC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;CA2ChC;AAED;;;;GAIG;AACH,eAAO,MAAM,IAAI,GAAU,OAAO,SAAS,oBAAuC,CAAA"}
|
|
@@ -103,11 +103,18 @@ class RootNode extends layout_canvas_util.ColumnNode {
|
|
|
103
103
|
* @returns Promise resolving to the rendered Canvas instance
|
|
104
104
|
*/
|
|
105
105
|
async render() {
|
|
106
|
-
// Step 1: Load all images
|
|
106
|
+
// Step 1: Load all images with a concurrency limit to avoid overwhelming remote sources
|
|
107
107
|
const imageNodes = this.findAllImageNodes();
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
if (imageNodes.length > 0) {
|
|
109
|
+
const CONCURRENCY = 5;
|
|
110
|
+
const queue = [...imageNodes];
|
|
111
|
+
const workers = Array.from({ length: Math.min(CONCURRENCY, queue.length) }, async () => {
|
|
112
|
+
while (queue.length > 0) {
|
|
113
|
+
const node = queue.shift();
|
|
114
|
+
await node.load();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
await Promise.allSettled(workers);
|
|
111
118
|
}
|
|
112
119
|
// Step 2: Calculate initial layout
|
|
113
120
|
this.node.calculateLayout(this.targetWidth, undefined, common_const.Style.Direction.LTR);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.canvas.util.js","sources":["../../../../src/canvas/root.canvas.util.ts"],"sourcesContent":["import { Canvas, FontLibrary, type CanvasRenderingContext2D } from 'skia-canvas'\nimport { ColumnNode, BoxNode } from '@/canvas/layout.canvas.util.js'\nimport type { BaseProps, RootProps } from '@/canvas/canvas.type.js'\nimport { ImageNode } from '@/canvas/image.canvas.util.js'\nimport { Style } from '@/constant/common.const.js'\nimport * as path from 'node:path'\nimport * as fs from 'node:fs'\n\n/** Registry to track fonts that have already been loaded */\nconst registeredFonts = new Map<string, Set<string>>()\n\n// Exported for testing purposes only\nexport const _clearRegisteredFonts = () => {\n registeredFonts.clear()\n}\n\n/**\n * Root node that manages the canvas rendering context and coordinates overall layout and drawing.\n * Inherits from ColumnNode to provide vertical layout capabilities.\n */\nexport class RootNode extends ColumnNode {\n /** The canvas instance used for rendering */\n private canvas: Canvas | undefined\n /** The 2D rendering context for the canvas */\n private ctx: CanvasRenderingContext2D | null = null\n /** Target width for the canvas in pixels */\n private readonly targetWidth: number\n /** Target height for the canvas in pixels */\n private readonly targetHeight: number\n /** Scale factor for rendering (e.g. 2 for 2x resolution) */\n private readonly scale: number\n\n /**\n * Creates a new root node for canvas rendering\n * @param props Configuration properties for the root node\n * @throws Error if width property is not provided\n */\n constructor(props: RootProps & BaseProps) {\n // Call the parent constructor with root name and props\n super({ name: 'Root', ...props })\n\n this.props = props\n\n // Validate the required width property\n if (!props.width) {\n throw new Error('Width and height are required for Root')\n }\n\n // Register provided fonts with caching\n if (props.fonts?.length) {\n for (const font of props.fonts) {\n const family = font.family\n const paths = font.paths.map(p => path.resolve(p))\n\n if (!registeredFonts.has(family)) {\n registeredFonts.set(family, new Set())\n }\n\n const cachedPaths = registeredFonts.get(family)!\n const newPaths = paths.filter(p => !cachedPaths.has(p) && fs.existsSync(p))\n\n if (newPaths.length > 0) {\n FontLibrary.use({ [family]: newPaths })\n newPaths.forEach(p => cachedPaths.add(p))\n }\n }\n }\n\n // Set up scale and width\n this.scale = props.scale || 1\n this.targetWidth = props.width\n this.targetHeight = props.height\n this.node.setWidth(this.targetWidth)\n\n // Initialize children nodes\n this.processInitialChildren()\n }\n\n /**\n * Traverses the node tree to find all ImageNode instances using breadth-first search\n * @returns Array of all ImageNode instances found in the tree\n */\n private findAllImageNodes(): ImageNode[] {\n const imageNodes: ImageNode[] = []\n const queue: BoxNode[] = [this]\n while (queue.length > 0) {\n const node = queue.shift()!\n if (node instanceof ImageNode) {\n imageNodes.push(node)\n }\n queue.push(...node.children)\n }\n return imageNodes\n }\n\n /**\n * Renders the entire node tree to a canvas, handling image loading, layout calculation,\n * and final drawing\n * @returns Promise resolving to the rendered Canvas instance\n */\n async render(): Promise<Canvas> {\n // Step 1: Load all images\n const imageNodes = this.findAllImageNodes()\n const
|
|
1
|
+
{"version":3,"file":"root.canvas.util.js","sources":["../../../../src/canvas/root.canvas.util.ts"],"sourcesContent":["import { Canvas, FontLibrary, type CanvasRenderingContext2D } from 'skia-canvas'\nimport { ColumnNode, BoxNode } from '@/canvas/layout.canvas.util.js'\nimport type { BaseProps, RootProps } from '@/canvas/canvas.type.js'\nimport { ImageNode } from '@/canvas/image.canvas.util.js'\nimport { Style } from '@/constant/common.const.js'\nimport * as path from 'node:path'\nimport * as fs from 'node:fs'\n\n/** Registry to track fonts that have already been loaded */\nconst registeredFonts = new Map<string, Set<string>>()\n\n// Exported for testing purposes only\nexport const _clearRegisteredFonts = () => {\n registeredFonts.clear()\n}\n\n/**\n * Root node that manages the canvas rendering context and coordinates overall layout and drawing.\n * Inherits from ColumnNode to provide vertical layout capabilities.\n */\nexport class RootNode extends ColumnNode {\n /** The canvas instance used for rendering */\n private canvas: Canvas | undefined\n /** The 2D rendering context for the canvas */\n private ctx: CanvasRenderingContext2D | null = null\n /** Target width for the canvas in pixels */\n private readonly targetWidth: number\n /** Target height for the canvas in pixels */\n private readonly targetHeight: number\n /** Scale factor for rendering (e.g. 2 for 2x resolution) */\n private readonly scale: number\n\n /**\n * Creates a new root node for canvas rendering\n * @param props Configuration properties for the root node\n * @throws Error if width property is not provided\n */\n constructor(props: RootProps & BaseProps) {\n // Call the parent constructor with root name and props\n super({ name: 'Root', ...props })\n\n this.props = props\n\n // Validate the required width property\n if (!props.width) {\n throw new Error('Width and height are required for Root')\n }\n\n // Register provided fonts with caching\n if (props.fonts?.length) {\n for (const font of props.fonts) {\n const family = font.family\n const paths = font.paths.map(p => path.resolve(p))\n\n if (!registeredFonts.has(family)) {\n registeredFonts.set(family, new Set())\n }\n\n const cachedPaths = registeredFonts.get(family)!\n const newPaths = paths.filter(p => !cachedPaths.has(p) && fs.existsSync(p))\n\n if (newPaths.length > 0) {\n FontLibrary.use({ [family]: newPaths })\n newPaths.forEach(p => cachedPaths.add(p))\n }\n }\n }\n\n // Set up scale and width\n this.scale = props.scale || 1\n this.targetWidth = props.width\n this.targetHeight = props.height\n this.node.setWidth(this.targetWidth)\n\n // Initialize children nodes\n this.processInitialChildren()\n }\n\n /**\n * Traverses the node tree to find all ImageNode instances using breadth-first search\n * @returns Array of all ImageNode instances found in the tree\n */\n private findAllImageNodes(): ImageNode[] {\n const imageNodes: ImageNode[] = []\n const queue: BoxNode[] = [this]\n while (queue.length > 0) {\n const node = queue.shift()!\n if (node instanceof ImageNode) {\n imageNodes.push(node)\n }\n queue.push(...node.children)\n }\n return imageNodes\n }\n\n /**\n * Renders the entire node tree to a canvas, handling image loading, layout calculation,\n * and final drawing\n * @returns Promise resolving to the rendered Canvas instance\n */\n async render(): Promise<Canvas> {\n // Step 1: Load all images with a concurrency limit to avoid overwhelming remote sources\n const imageNodes = this.findAllImageNodes()\n if (imageNodes.length > 0) {\n const CONCURRENCY = 5\n const queue = [...imageNodes]\n const workers = Array.from({ length: Math.min(CONCURRENCY, queue.length) }, async () => {\n while (queue.length > 0) {\n const node = queue.shift()!\n await node.load()\n }\n })\n await Promise.allSettled(workers)\n }\n\n // Step 2: Calculate initial layout\n this.node.calculateLayout(this.targetWidth, undefined, Style.Direction.LTR)\n\n // Step 3: Allow nodes to finalize their layout\n const needRecalculate = this.finalizeLayout()\n if (needRecalculate) {\n this.node.calculateLayout(this.targetWidth, undefined, Style.Direction.LTR)\n }\n\n // Step 4: Create a canvas with calculated dimensions\n const calculatedContentHeight = this.node.getComputedHeight()\n const finalCanvasWidth = Math.ceil(this.targetWidth * this.scale)\n const finalCanvasHeight = this.targetHeight ? Math.ceil(this.targetHeight * this.scale) : Math.max(1, Math.ceil(calculatedContentHeight * this.scale))\n\n // Step 5: Set up canvas context\n this.canvas = new Canvas(finalCanvasWidth, finalCanvasHeight)\n this.ctx = this.canvas.getContext('2d')\n this.ctx.scale(this.scale, this.scale)\n\n // Step 6: Render content\n super.render(this.ctx, 0, 0)\n\n if (!this.canvas) {\n throw new Error('Canvas not initialized')\n }\n\n return this.canvas\n }\n}\n\n/**\n * Creates and renders a new root node with the given properties\n * @param props Configuration properties for the root node\n * @returns Promise resolving to the rendered Canvas instance\n */\nexport const Root = async (props: RootProps) => await new RootNode(props).render()\n"],"names":["ColumnNode","path","fs","FontLibrary","ImageNode","Style","Canvas"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/grid.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACtF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAIjE;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,OAAO;gBAC3B,KAAK,EAAE,aAAa;CAMjC;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,aAAa,iBAA4B,CAAA;AAEzE;;;GAGG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC;;;OAGG;gBACS,KAAK,EAAE,SAAS;IAQ5B;;OAEG;IACH,OAAO,CAAC,UAAU;IAwBlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAmBpB;;OAEG;cACgB,+BAA+B;
|
|
1
|
+
{"version":3,"file":"grid.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/grid.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAiB,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACtF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAIjE;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,OAAO;gBAC3B,KAAK,EAAE,aAAa;CAMjC;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,aAAa,iBAA4B,CAAA;AAEzE;;;GAGG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC;;;OAGG;gBACS,KAAK,EAAE,SAAS;IAQ5B;;OAEG;IACH,OAAO,CAAC,UAAU;IAwBlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAmBpB;;OAEG;cACgB,+BAA+B;IAoTlD;;OAEG;IACH,OAAO,CAAC,aAAa;CAkCtB;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,SAAS,aAAwB,CAAA"}
|
|
@@ -75,15 +75,22 @@ class GridNode extends RowNode {
|
|
|
75
75
|
const parent = this.node.getParent();
|
|
76
76
|
if (parent) {
|
|
77
77
|
const parentWidth = parent.getWidth();
|
|
78
|
+
const parentMinWidth = parent.getMinWidth();
|
|
78
79
|
const parentMaxWidth = parent.getMaxWidth();
|
|
79
|
-
//
|
|
80
|
-
|
|
80
|
+
// Parent has % minWidth but no hard width/maxWidth constraint
|
|
81
|
+
const hasPercentMinWidth = parentMinWidth.unit === Style.Unit.Percent;
|
|
82
|
+
const hasExplicitWidth = parentWidth.unit !== Style.Unit.Undefined && parentWidth.unit !== Style.Unit.Auto;
|
|
83
|
+
const hasMaxWidth = parentMaxWidth.unit !== Style.Unit.Undefined && parentMaxWidth.unit !== Style.Unit.Auto;
|
|
84
|
+
if (hasPercentMinWidth && !hasExplicitWidth && !hasMaxWidth) {
|
|
81
85
|
const grandparent = parent.getParent();
|
|
82
86
|
if (grandparent) {
|
|
83
|
-
const
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
const intendedWidth = (parentMinWidth.value / 100) * grandparent.getComputedWidth();
|
|
88
|
+
// Check if parent has flexGrow - if so, don't constrain
|
|
89
|
+
const parentFlexGrow = parent.getFlexGrow();
|
|
90
|
+
if (parentFlexGrow > 0) ;
|
|
91
|
+
else {
|
|
92
|
+
// No flexGrow - constrain to minWidth
|
|
93
|
+
width = Math.min(width, intendedWidth);
|
|
87
94
|
}
|
|
88
95
|
}
|
|
89
96
|
}
|
|
@@ -10,8 +10,9 @@ export declare class ImageNode extends BoxNode {
|
|
|
10
10
|
private loadedImage;
|
|
11
11
|
private naturalWidth;
|
|
12
12
|
private naturalHeight;
|
|
13
|
-
private
|
|
13
|
+
private loadingPromise;
|
|
14
14
|
constructor(props: ImageProps);
|
|
15
|
+
load(): Promise<void>;
|
|
15
16
|
/**
|
|
16
17
|
* Loads and processes an image from various sources (URL, file path, or Buffer).
|
|
17
18
|
* Handles SVG color modifications and sets natural dimensions with an aspect ratio.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/image.canvas.util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"image.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/image.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,KAAK,wBAAwB,EAAmC,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAsBxD;;;GAGG;AACH,qBAAa,SAAU,SAAQ,OAAO;IAC5B,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;IACrC,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,cAAc,CAA6B;gBAEvC,KAAK,EAAE,UAAU;IAYtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IA8GX,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzC;;;OAGG;cACgB,cAAc,CAAC,GAAG,EAAE,wBAAwB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAoJrH;AAED;;GAEG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,UAAU,cAAyB,CAAA"}
|
|
@@ -4,7 +4,6 @@ import { parseBorderRadius, drawRoundedRectPath } from './canvas.helper.js';
|
|
|
4
4
|
import { promises } from 'fs';
|
|
5
5
|
import { Style } from '../constant/common.const.js';
|
|
6
6
|
|
|
7
|
-
// TODO: Add comprehensive unit tests for this file.
|
|
8
7
|
/**
|
|
9
8
|
* Calculates pixel offset for image positioning based on percentage or pixel values.
|
|
10
9
|
* This handles centering, edge alignment, and percentage-based positioning.
|
|
@@ -39,7 +38,12 @@ class ImageNode extends BoxNode {
|
|
|
39
38
|
objectPosition: { Left: '50%', Top: '50%' },
|
|
40
39
|
...props,
|
|
41
40
|
};
|
|
42
|
-
|
|
41
|
+
}
|
|
42
|
+
load() {
|
|
43
|
+
if (!this.loadingPromise) {
|
|
44
|
+
this.loadingPromise = this._loadImage();
|
|
45
|
+
}
|
|
46
|
+
return this.loadingPromise;
|
|
43
47
|
}
|
|
44
48
|
/**
|
|
45
49
|
* Loads and processes an image from various sources (URL, file path, or Buffer).
|
|
@@ -148,7 +152,7 @@ class ImageNode extends BoxNode {
|
|
|
148
152
|
});
|
|
149
153
|
}
|
|
150
154
|
getLoadingPromise() {
|
|
151
|
-
return this.loadingPromise ??
|
|
155
|
+
return this.loadingPromise ?? this.load();
|
|
152
156
|
}
|
|
153
157
|
/**
|
|
154
158
|
* Renders the image with correct sizing, clipping, and positioning.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/root.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA8C,MAAM,aAAa,CAAA;AAChF,OAAO,EAAE,UAAU,EAAW,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAUnE,eAAO,MAAM,qBAAqB,YAEjC,CAAA;AAED;;;GAGG;AACH,qBAAa,QAAS,SAAQ,UAAU;IACtC,6CAA6C;IAC7C,OAAO,CAAC,MAAM,CAAoB;IAClC,8CAA8C;IAC9C,OAAO,CAAC,GAAG,CAAwC;IACnD,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAE9B;;;;OAIG;gBACS,KAAK,EAAE,SAAS,GAAG,SAAS;IAyCxC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"root.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/root.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA8C,MAAM,aAAa,CAAA;AAChF,OAAO,EAAE,UAAU,EAAW,MAAM,gCAAgC,CAAA;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAUnE,eAAO,MAAM,qBAAqB,YAEjC,CAAA;AAED;;;GAGG;AACH,qBAAa,QAAS,SAAQ,UAAU;IACtC,6CAA6C;IAC7C,OAAO,CAAC,MAAM,CAAoB;IAClC,8CAA8C;IAC9C,OAAO,CAAC,GAAG,CAAwC;IACnD,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAE9B;;;;OAIG;gBACS,KAAK,EAAE,SAAS,GAAG,SAAS;IAyCxC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;CA2ChC;AAED;;;;GAIG;AACH,eAAO,MAAM,IAAI,GAAU,OAAO,SAAS,oBAAuC,CAAA"}
|
|
@@ -81,11 +81,18 @@ class RootNode extends ColumnNode {
|
|
|
81
81
|
* @returns Promise resolving to the rendered Canvas instance
|
|
82
82
|
*/
|
|
83
83
|
async render() {
|
|
84
|
-
// Step 1: Load all images
|
|
84
|
+
// Step 1: Load all images with a concurrency limit to avoid overwhelming remote sources
|
|
85
85
|
const imageNodes = this.findAllImageNodes();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
if (imageNodes.length > 0) {
|
|
87
|
+
const CONCURRENCY = 5;
|
|
88
|
+
const queue = [...imageNodes];
|
|
89
|
+
const workers = Array.from({ length: Math.min(CONCURRENCY, queue.length) }, async () => {
|
|
90
|
+
while (queue.length > 0) {
|
|
91
|
+
const node = queue.shift();
|
|
92
|
+
await node.load();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
await Promise.allSettled(workers);
|
|
89
96
|
}
|
|
90
97
|
// Step 2: Calculate initial layout
|
|
91
98
|
this.node.calculateLayout(this.targetWidth, undefined, Style.Direction.LTR);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meonode/canvas",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.6",
|
|
4
4
|
"description": "A declarative, component-based library for server-side canvas image generation. Write complex visuals with simple functions, similar to the composition style of @meonode/ui.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"canvas",
|
|
@@ -56,7 +56,9 @@
|
|
|
56
56
|
"@semantic-release/npm": "^13.1.5",
|
|
57
57
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
58
58
|
"@types/jest": "^30.0.0",
|
|
59
|
+
"@types/lodash-es": "^4.17.12",
|
|
59
60
|
"@types/sharp": "^0.32.0",
|
|
61
|
+
"@types/tinycolor2": "^1.4.6",
|
|
60
62
|
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
|
61
63
|
"@typescript-eslint/parser": "^8.57.0",
|
|
62
64
|
"eslint": "^9.39.4",
|