@meonode/canvas 1.2.0 → 1.3.0
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/README.md +320 -225
- package/dist/cjs/canvas/canvas.type.d.ts +38 -7
- package/dist/cjs/canvas/canvas.type.d.ts.map +1 -1
- package/dist/cjs/canvas/grid.canvas.util.d.ts +25 -18
- package/dist/cjs/canvas/grid.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/grid.canvas.util.js +298 -210
- package/dist/cjs/canvas/grid.canvas.util.js.map +1 -1
- package/dist/cjs/canvas/text.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/text.canvas.util.js +84 -51
- package/dist/cjs/canvas/text.canvas.util.js.map +1 -1
- package/dist/esm/canvas/canvas.type.d.ts +38 -7
- package/dist/esm/canvas/canvas.type.d.ts.map +1 -1
- package/dist/esm/canvas/grid.canvas.util.d.ts +25 -18
- package/dist/esm/canvas/grid.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/grid.canvas.util.js +298 -210
- package/dist/esm/canvas/text.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/text.canvas.util.js +84 -51
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.canvas.util.js","sources":["../../../../src/canvas/grid.canvas.util.ts"],"sourcesContent":["// TODO: Add comprehensive unit tests for this file.\n\nimport type { GridProps } from '@/canvas/canvas.type.js'\nimport { BoxNode, RowNode } from '@/canvas/layout.canvas.util.js'\nimport { Style, FlexDirection } from '@/constant/common.const.js'\n\n/**\n * Grid layout node that arranges children in a configurable number of columns or rows.\n * Uses Yoga's flexbox capabilities with wrapping and gap properties to simulate a grid.\n * @extends RowNode\n */\nexport class GridNode extends RowNode {\n private readonly columns: number\n private readonly columnGapValue: number | `${number}%`\n private readonly rowGapValue: number | `${number}%`\n private readonly isVertical: boolean // True if the main axis is vertical (flexDirection: column or column-reverse)\n\n /**\n * Creates a new grid layout node\n * @param props Grid configuration properties\n */\n constructor(props: GridProps) {\n const columns = Math.max(1, props.columns || 1)\n const direction = props.direction || 'row' // Default to horizontal row\n const isVertical = direction === 'column' || direction === 'column-reverse'\n\n // Map direction string to Yoga FlexDirection\n let flexDirection: FlexDirection\n switch (direction) {\n case 'row':\n flexDirection = Style.FlexDirection.Row\n break\n case 'column':\n flexDirection = Style.FlexDirection.Column\n break\n case 'row-reverse':\n flexDirection = Style.FlexDirection.RowReverse\n break\n case 'column-reverse':\n flexDirection = Style.FlexDirection.ColumnReverse\n break\n default:\n console.warn(`[GridNode] Invalid direction \"${direction}\". Defaulting to \"row\".`)\n flexDirection = Style.FlexDirection.Row\n }\n\n // Determine the column and row gap values from props\n let columnGap: number | `${number}%` = 0\n let rowGap: number | `${number}%` = 0\n\n if (typeof props.gap === 'number' || (typeof props.gap === 'string' && props.gap.trim() !== '')) {\n // Single value applies to both row and column gaps\n columnGap = props.gap\n rowGap = props.gap\n } else if (props.gap && typeof props.gap === 'object') {\n // Object format: prioritize a specific direction (Column/Row), then All\n columnGap = props.gap.Column ?? props.gap.All ?? 0\n rowGap = props.gap.Row ?? props.gap.All ?? 0\n }\n\n super({\n name: 'Grid',\n flexWrap: Style.Wrap.Wrap, // Essential for grid behavior\n flexDirection,\n ...props,\n // Explicitly remove the 'direction' prop passed to super, as it's handled by flexDirection\n direction: undefined,\n // Pass undefined for gap to prevent BoxNode from trying to parse it\n gap: undefined,\n })\n\n this.columns = columns\n this.columnGapValue = columnGap\n this.rowGapValue = rowGap\n this.isVertical = isVertical\n\n // Explicitly set gaps on this.node after super() call\n // These will be updated again in updateLayoutBasedOnComputedSize, but this ensures initial setup\n if (typeof columnGap === 'number') {\n this.node.setGap(Style.Gutter.Column, columnGap)\n } else if (typeof columnGap === 'string' && columnGap.endsWith('%')) {\n this.node.setGapPercent(Style.Gutter.Column, parseFloat(columnGap))\n }\n if (typeof rowGap === 'number') {\n this.node.setGap(Style.Gutter.Row, rowGap)\n } else if (typeof rowGap === 'string' && rowGap.endsWith('%')) {\n this.node.setGapPercent(Style.Gutter.Row, parseFloat(rowGap))\n }\n }\n\n /**\n * Appends a child node to this grid.\n * Overridden primarily for documentation/clarity, functionality is inherited.\n * @param child Child node to append\n * @param index Index at which to insert the child\n */\n protected override appendChild(child: BoxNode, index: number) {\n super.appendChild(child, index)\n }\n\n /**\n * Update layout calculations after the initial layout is computed.\n * This method calculates the appropriate flex-basis for children based on the\n * number of columns and gaps, respecting the container's padding,\n * and applies the gaps using Yoga's built-in properties.\n */\n protected override updateLayoutBasedOnComputedSize() {\n // Step 1: Early return if the grid is empty or invalid\n if (this.columns <= 0 || this.children.length === 0) {\n return\n }\n\n // Step 2: Get container dimensions and padding after the initial layout\n const width = this.node.getComputedWidth()\n const height = this.node.getComputedHeight()\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 // Calculate content box dimensions\n const contentWidth = Math.max(0, width - paddingLeft - paddingRight)\n const contentHeight = Math.max(0, height - paddingTop - paddingBottom)\n\n // Step 3: Validate dimensions needed for calculations\n if (!this.isVertical && contentWidth <= 0 && width > 0) {\n console.warn(\n `[GridNode ${this.props.key} - Finalize] Grid content width (${contentWidth}) is zero or negative after accounting for padding (${paddingLeft}+${paddingRight}) on total width ${width}. Cannot calculate basis.`,\n )\n if (this.columns > 1) return\n }\n if (this.isVertical && contentHeight <= 0 && height > 0) {\n console.warn(\n `[GridNode ${this.props.key} - Finalize] Grid content height (${contentHeight}) is zero or negative after accounting for padding (${paddingTop}+${paddingBottom}) on total height ${height}. Cannot calculate basis.`,\n )\n if (this.columns > 1) return\n }\n\n // Step 4: Calculate Gap Values in Pixels\n let columnGapPixels = 0\n if (typeof this.columnGapValue === 'number') {\n columnGapPixels = this.columnGapValue\n } else if (typeof this.columnGapValue === 'string' && this.columnGapValue.trim().endsWith('%')) {\n try {\n const percent = parseFloat(this.columnGapValue)\n if (!isNaN(percent) && contentWidth > 0) {\n columnGapPixels = (percent / 100) * contentWidth\n } else if (isNaN(percent)) {\n console.warn(`[GridNode ${this.props.key}] Invalid percentage column gap format: \"${this.columnGapValue}\". Using 0px.`)\n } else if (contentWidth <= 0) {\n console.warn(`[GridNode ${this.props.key}] Cannot calculate percentage column gap (${this.columnGapValue}) because content width is zero. Using 0px.`)\n }\n } catch (e) {\n console.warn(`[GridNode ${this.props.key}] Error parsing percentage column gap: \"${this.columnGapValue}\". Using 0px.`, e)\n }\n } else if (typeof this.columnGapValue === 'string' && this.columnGapValue.trim() !== '') {\n console.warn(\n `[GridNode ${this.props.key}] Unsupported string column gap format: \"${this.columnGapValue}\". Using 0px. Only numbers and percentages ('%') are supported.`,\n )\n }\n\n let rowGapPixels = 0\n if (typeof this.rowGapValue === 'number') {\n rowGapPixels = this.rowGapValue\n } else if (typeof this.rowGapValue === 'string' && this.rowGapValue.trim().endsWith('%')) {\n try {\n const percent = parseFloat(this.rowGapValue)\n if (!isNaN(percent) && contentHeight > 0) {\n rowGapPixels = (percent / 100) * contentHeight\n } else if (isNaN(percent)) {\n console.warn(`[GridNode ${this.props.key}] Invalid percentage row gap format: \"${this.rowGapValue}\". Using 0px.`)\n } else if (contentHeight <= 0) {\n console.warn(`[GridNode ${this.props.key}] Cannot calculate percentage row gap (${this.rowGapValue}) because content height is zero. Using 0px.`)\n }\n } catch (e) {\n console.warn(`[GridNode ${this.props.key}] Error parsing percentage row gap: \"${this.rowGapValue}\". Using 0px.`, e)\n }\n } else if (typeof this.rowGapValue === 'string' && this.rowGapValue.trim() !== '') {\n console.warn(\n `[GridNode ${this.props.key}] Unsupported string row gap format: \"${this.rowGapValue}\". Using 0px. Only numbers and percentages ('%') are supported.`,\n )\n }\n\n // Ensure gaps are not negative\n columnGapPixels = Math.max(0, columnGapPixels)\n rowGapPixels = Math.max(0, rowGapPixels)\n\n // Step 5: Calculate flex-basis percentage for children\n const mainAxisGapPixels = this.isVertical ? rowGapPixels : columnGapPixels\n const mainAxisContentSize = this.isVertical ? contentHeight : contentWidth\n let childWidth = 0\n\n if (mainAxisContentSize > 0 && this.columns > 0) {\n // Total space taken up by gaps on the main axis\n const totalGapSpaceOnMainAxis = this.columns > 1 ? mainAxisGapPixels * (this.columns - 1) : 0\n\n // Calculate the space available *only* for the items themselves\n const availableSpaceOnMainAxis = Math.max(0, mainAxisContentSize - totalGapSpaceOnMainAxis)\n\n // Calculate the exact pixel of the total content size that each item should occupy\n const exactItemWidth = availableSpaceOnMainAxis / this.columns\n\n // Ensure it's not negative (shouldn't happen, but safety)\n childWidth = Math.max(0, exactItemWidth - 0.5) // Slightly reduce to avoid rounding issues\n } else if (this.columns === 1) {\n // If only one column, it takes up the full basis (gaps don't apply)\n childWidth = mainAxisContentSize\n }\n\n // Clamp basis percentage between 0 and 100 (mostly redundant after floor/max(0) but safe)\n childWidth = Math.max(0, Math.min(mainAxisContentSize, childWidth))\n\n // Step 6: Apply layout properties to children\n let childrenNeedRecalculation = false\n for (const child of this.children) {\n let childChanged = false\n const currentLayoutWidth = child.node.getWidth()\n const currentWidthValue = currentLayoutWidth.value\n const currentWidthUnit = currentLayoutWidth.unit\n\n let widthNeedsUpdate = false\n if (currentWidthUnit === Style.Unit.Point) {\n // If current width is in points, check if the value is significantly different\n if (Math.abs(currentWidthValue - childWidth) > 0.01) {\n widthNeedsUpdate = true\n }\n } else {\n // If current width is not in points (e.g., Auto, Percent, Undefined), it needs to be set to points\n widthNeedsUpdate = true\n }\n\n if (widthNeedsUpdate) {\n child.node.setWidth(childWidth)\n childChanged = true\n }\n\n // Ensure grow/shrink are set correctly for grid items\n if (child.node.getFlexGrow() !== 0) {\n child.node.setFlexGrow(0)\n childChanged = true\n }\n if (child.node.getFlexShrink() !== 1) {\n child.node.setFlexShrink(1) // Allow shrinking\n childChanged = true\n }\n\n // Remove margins that might interfere with gap property\n if (child.node.getMargin(Style.Edge.Bottom).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Bottom, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Right).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Right, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Top).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Top, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Left).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Left, undefined)\n childChanged = true\n }\n\n if (childChanged && !child.node.isDirty()) {\n child.node.markDirty()\n childrenNeedRecalculation = true\n }\n }\n\n // Step 7: Apply gaps using Yoga's built-in gap properties\n const currentColumnGap = this.node.getGap(Style.Gutter.Column).value\n const currentRowGap = this.node.getGap(Style.Gutter.Row).value\n let gapsChanged = false\n\n // Use a small tolerance for comparing gap pixels\n if (Math.abs(currentColumnGap - columnGapPixels) > 0.001) {\n this.node.setGap(Style.Gutter.Column, columnGapPixels)\n gapsChanged = true\n }\n if (Math.abs(currentRowGap - rowGapPixels) > 0.001) {\n this.node.setGap(Style.Gutter.Row, rowGapPixels)\n gapsChanged = true\n }\n\n // Step 8: Mark the grid node itself as dirty if gaps changed or children changed\n if ((gapsChanged || childrenNeedRecalculation) && !this.node.isDirty()) {\n this.node.markDirty()\n }\n }\n}\n\n/**\n * Factory function to create a new GridNode instance.\n * @param props Grid configuration properties.\n * @returns A new GridNode instance.\n */\nexport const Grid = (props: GridProps) => new GridNode(props)\n"],"names":["RowNode","Style"],"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 // 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 const width = this.node.getComputedWidth()\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 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 let childrenChanged = false\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 childrenChanged = true\n }\n\n if (childNode.getPosition(Style.Edge.Left).value !== x) {\n childNode.setPosition(Style.Edge.Left, x)\n childrenChanged = true\n }\n if (childNode.getPosition(Style.Edge.Top).value !== y) {\n childNode.setPosition(Style.Edge.Top, y)\n childrenChanged = true\n }\n\n if (childNode.getWidth().unit !== Style.Unit.Point || Math.abs(childNode.getWidth().value - totalWidth) > 0.1) {\n childNode.setWidth(totalWidth)\n childrenChanged = true\n }\n if (childNode.getHeight().unit !== Style.Unit.Point || Math.abs(childNode.getHeight().value - totalHeight) > 0.1) {\n childNode.setHeight(totalHeight)\n childrenChanged = true\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 childrenChanged = true\n }\n\n if (childrenChanged && !this.node.isDirty()) {\n this.node.markDirty()\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/text.canvas.util.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAU,KAAK,wBAAwB,EAA2B,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAGxD;;;GAGG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAwC;IACzE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,kBAAkB,CAAe;IAEjC,KAAK,EAAE,SAAS,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;gBAElC,IAAI,GAAE,MAAM,GAAG,MAAW,EAAE,KAAK,GAAE,SAAc;IAuB7D;;;;;;;;OAQG;WACW,gBAAgB,CAC5B,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,GAAE;QACL,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC,CAAA;QACpC,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAA;QAClC,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,SAAS,CAAC,EAAE,wBAAwB,CAAC,WAAW,CAAC,CAAA;QACjD,YAAY,CAAC,EAAE,wBAAwB,CAAC,cAAc,CAAC,CAAA;KACnD;cAwBW,aAAa,IAAI,IAAI;IAoDxC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,sBAAsB;IA8B9B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,aAAa;IA+ErB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,gBAAgB;IAyBxB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IAiCrB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAQjC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,WAAW;IA8NnB;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY;IAuKpB;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAmErB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;;;;;;;;;;;;;;;OAgBG;cACgB,cAAc,CAAC,GAAG,EAAE,wBAAwB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"text.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/text.canvas.util.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,yBAAyB,CAAA;AACrE,OAAO,EAAU,KAAK,wBAAwB,EAA2B,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAGxD;;;GAGG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAwC;IACzE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,kBAAkB,CAAe;IAEjC,KAAK,EAAE,SAAS,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;gBAElC,IAAI,GAAE,MAAM,GAAG,MAAW,EAAE,KAAK,GAAE,SAAc;IAuB7D;;;;;;;;OAQG;WACW,gBAAgB,CAC5B,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,GAAE;QACL,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC,CAAA;QACpC,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAA;QAClC,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,SAAS,CAAC,EAAE,wBAAwB,CAAC,WAAW,CAAC,CAAA;QACjD,YAAY,CAAC,EAAE,wBAAwB,CAAC,cAAc,CAAC,CAAA;KACnD;cAwBW,aAAa,IAAI,IAAI;IAoDxC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,sBAAsB;IA8B9B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,aAAa;IA+ErB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,gBAAgB;IAyBxB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IAiCrB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAQjC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,WAAW;IA8NnB;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY;IAuKpB;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAmErB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;;;;;;;;;;;;;;;OAgBG;cACgB,cAAc,CAAC,GAAG,EAAE,wBAAwB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAiXrH;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,GAAG,MAAM,EAAE,QAAQ,SAAS,aAA8B,CAAA"}
|
|
@@ -809,16 +809,6 @@ class TextNode extends layout_canvas_util.BoxNode {
|
|
|
809
809
|
*/
|
|
810
810
|
_renderContent(ctx, x, y, width, height) {
|
|
811
811
|
super._renderContent(ctx, x, y, width, height);
|
|
812
|
-
const linesToRender = this.getLinesToMeasureOrRender();
|
|
813
|
-
const numLinesToRender = linesToRender.length;
|
|
814
|
-
// Validate required data is available
|
|
815
|
-
if (numLinesToRender === 0 ||
|
|
816
|
-
this.segments.length === 0 ||
|
|
817
|
-
this.lineHeights.length !== numLinesToRender ||
|
|
818
|
-
this.lineAscents.length !== numLinesToRender ||
|
|
819
|
-
this.lineContentHeights.length !== numLinesToRender) {
|
|
820
|
-
return;
|
|
821
|
-
}
|
|
822
812
|
ctx.save();
|
|
823
813
|
ctx.textBaseline = 'alphabetic';
|
|
824
814
|
ctx.letterSpacing = this.formatSpacing(this.props.letterSpacing);
|
|
@@ -838,9 +828,80 @@ class TextNode extends layout_canvas_util.BoxNode {
|
|
|
838
828
|
ctx.restore();
|
|
839
829
|
return;
|
|
840
830
|
}
|
|
831
|
+
// Re-calculate lines based on the actual render width to ensure consistency
|
|
832
|
+
// This fixes issues where Yoga Layout might use a cached measurement from a different
|
|
833
|
+
// width constraint (e.g., during a flex shrink pass) but final layout is wider.
|
|
834
|
+
const spaceWidth = this.measureSpaceWidth(ctx);
|
|
835
|
+
// Use a small epsilon for float precision issues
|
|
836
|
+
const epsilon = 0.01;
|
|
837
|
+
const allLines = this.wrapTextRich(ctx, this.segments, contentWidth + epsilon, parsedWordSpacingPx);
|
|
838
|
+
const needsEllipsis = this.props.ellipsis && this.props.maxLines !== undefined && allLines.length > this.props.maxLines;
|
|
839
|
+
// Apply maxLines constraint to get the visible lines
|
|
840
|
+
const visibleLines = this.props.maxLines !== undefined && this.props.maxLines > 0 ? allLines.slice(0, this.props.maxLines) : allLines;
|
|
841
|
+
const numLinesToRender = visibleLines.length;
|
|
842
|
+
// Recalculate line metrics for the rendered lines
|
|
843
|
+
// We cannot rely on this.lineHeights from measureText because it might correspond to different wrapping
|
|
844
|
+
const lineHeights = [];
|
|
845
|
+
const lineAscents = [];
|
|
846
|
+
const lineContentHeights = [];
|
|
847
|
+
const defaultLineHeightMultiplier = 1.2;
|
|
848
|
+
let totalTextHeight = 0;
|
|
849
|
+
for (const line of visibleLines) {
|
|
850
|
+
let maxAscent = 0;
|
|
851
|
+
let maxDescent = 0;
|
|
852
|
+
let maxFontSizeOnLine = 0;
|
|
853
|
+
if (line.length === 0) {
|
|
854
|
+
ctx.font = this.getFontString();
|
|
855
|
+
if (this.props.fontVariant)
|
|
856
|
+
ctx.fontVariant = typeof this.props.fontVariant === 'string' ? this.props.fontVariant : 'normal';
|
|
857
|
+
const metrics = ctx.measureText(this.metricsString);
|
|
858
|
+
maxAscent = metrics.actualBoundingBoxAscent ?? baseFontSize * 0.8;
|
|
859
|
+
maxDescent = metrics.actualBoundingBoxDescent ?? baseFontSize * 0.2;
|
|
860
|
+
maxFontSizeOnLine = baseFontSize;
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
for (const segment of line) {
|
|
864
|
+
if (/^\s+$/.test(segment.text))
|
|
865
|
+
continue;
|
|
866
|
+
const segmentSize = segment.size || baseFontSize;
|
|
867
|
+
maxFontSizeOnLine = Math.max(maxFontSizeOnLine, segmentSize);
|
|
868
|
+
// Style context for accurate metrics
|
|
869
|
+
ctx.font = this.getFontString(segment);
|
|
870
|
+
if (this.props.fontVariant)
|
|
871
|
+
ctx.fontVariant = typeof this.props.fontVariant === 'string' ? this.props.fontVariant : 'normal';
|
|
872
|
+
const metrics = ctx.measureText(this.metricsString);
|
|
873
|
+
const ascent = metrics.actualBoundingBoxAscent ?? segmentSize * 0.8;
|
|
874
|
+
const descent = metrics.actualBoundingBoxDescent ?? segmentSize * 0.2;
|
|
875
|
+
maxAscent = Math.max(maxAscent, ascent);
|
|
876
|
+
maxDescent = Math.max(maxDescent, descent);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
if (maxAscent === 0 && maxDescent === 0 && line.length > 0) {
|
|
880
|
+
// Fallback
|
|
881
|
+
ctx.font = this.getFontString();
|
|
882
|
+
if (this.props.fontVariant)
|
|
883
|
+
ctx.fontVariant = typeof this.props.fontVariant === 'string' ? this.props.fontVariant : 'normal';
|
|
884
|
+
const metrics = ctx.measureText(this.metricsString);
|
|
885
|
+
maxAscent = metrics.actualBoundingBoxAscent ?? baseFontSize * 0.8;
|
|
886
|
+
maxDescent = metrics.actualBoundingBoxDescent ?? baseFontSize * 0.2;
|
|
887
|
+
maxFontSizeOnLine = maxFontSizeOnLine || baseFontSize;
|
|
888
|
+
}
|
|
889
|
+
maxFontSizeOnLine = maxFontSizeOnLine || baseFontSize;
|
|
890
|
+
const actualContentHeight = maxAscent + maxDescent;
|
|
891
|
+
const targetLineBoxHeight = typeof this.props.lineHeight === 'number' && this.props.lineHeight > 0 ? this.props.lineHeight : maxFontSizeOnLine * defaultLineHeightMultiplier;
|
|
892
|
+
const finalLineHeight = Math.max(actualContentHeight, targetLineBoxHeight);
|
|
893
|
+
lineHeights.push(finalLineHeight);
|
|
894
|
+
lineAscents.push(maxAscent);
|
|
895
|
+
lineContentHeights.push(actualContentHeight);
|
|
896
|
+
totalTextHeight += finalLineHeight;
|
|
897
|
+
}
|
|
898
|
+
if (numLinesToRender === 0) {
|
|
899
|
+
ctx.restore();
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
841
902
|
// Calculate vertical alignment offset
|
|
842
903
|
const lineGapValue = this.props.lineGap;
|
|
843
|
-
const totalCalculatedTextHeight =
|
|
904
|
+
const totalCalculatedTextHeight = totalTextHeight + Math.max(0, numLinesToRender - 1) * lineGapValue;
|
|
844
905
|
let blockStartY;
|
|
845
906
|
switch (this.props.verticalAlign) {
|
|
846
907
|
case 'middle':
|
|
@@ -860,13 +921,12 @@ class TextNode extends layout_canvas_util.BoxNode {
|
|
|
860
921
|
ctx.clip();
|
|
861
922
|
// Configure ellipsis if needed
|
|
862
923
|
const ellipsisChar = typeof this.props.ellipsis === 'string' ? this.props.ellipsis : '...';
|
|
863
|
-
const needsEllipsis = this.props.ellipsis && this.lines.length > numLinesToRender;
|
|
864
924
|
let ellipsisWidth = 0;
|
|
865
925
|
let ellipsisStyle = undefined;
|
|
866
926
|
if (needsEllipsis) {
|
|
867
|
-
const lastRenderedLine =
|
|
927
|
+
const lastRenderedLine = visibleLines[visibleLines.length - 1];
|
|
928
|
+
// ... ellipsis calculation ...
|
|
868
929
|
const lastTextStyleSegment = [...lastRenderedLine].reverse().find(seg => !/^\s+$/.test(seg.text));
|
|
869
|
-
// Inherit styles from last non-whitespace segment
|
|
870
930
|
ellipsisStyle = lastTextStyleSegment
|
|
871
931
|
? {
|
|
872
932
|
color: lastTextStyleSegment.color,
|
|
@@ -876,38 +936,20 @@ class TextNode extends layout_canvas_util.BoxNode {
|
|
|
876
936
|
i: lastTextStyleSegment.i,
|
|
877
937
|
}
|
|
878
938
|
: undefined;
|
|
879
|
-
|
|
880
|
-
const originalVariant = ctx.fontVariant;
|
|
939
|
+
ctx.save();
|
|
881
940
|
ctx.font = this.getFontString(ellipsisStyle);
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
ctx.fontVariant = this.props.fontVariant;
|
|
885
|
-
}
|
|
886
|
-
else if (this.props.fontVariant !== undefined) {
|
|
887
|
-
console.warn(`[TextNode ${this.key || ''}] Invalid fontVariant prop type in _renderContent (ellipsis measure):`, this.props.fontVariant);
|
|
888
|
-
if (ctx.fontVariant !== 'normal')
|
|
889
|
-
ctx.fontVariant = 'normal';
|
|
890
|
-
}
|
|
891
|
-
else {
|
|
892
|
-
if (ctx.fontVariant !== 'normal')
|
|
893
|
-
ctx.fontVariant = 'normal';
|
|
941
|
+
if (this.props.fontVariant) {
|
|
942
|
+
ctx.fontVariant = typeof this.props.fontVariant === 'string' ? this.props.fontVariant : 'normal';
|
|
894
943
|
}
|
|
895
944
|
ellipsisWidth = ctx.measureText(ellipsisChar).width;
|
|
896
|
-
ctx.
|
|
897
|
-
if (originalVariant !== 'normal') {
|
|
898
|
-
ctx.fontVariant = originalVariant;
|
|
899
|
-
}
|
|
900
|
-
else if (ctx.fontVariant !== 'normal') {
|
|
901
|
-
ctx.fontVariant = 'normal';
|
|
902
|
-
}
|
|
945
|
+
ctx.restore();
|
|
903
946
|
}
|
|
904
|
-
const spaceWidth = this.measureSpaceWidth(ctx);
|
|
905
947
|
// Render text content line by line
|
|
906
948
|
for (let i = 0; i < numLinesToRender; i++) {
|
|
907
|
-
const lineSegments =
|
|
908
|
-
const currentLineFinalHeight =
|
|
909
|
-
const currentLineMaxAscent =
|
|
910
|
-
const currentLineContentHeight =
|
|
949
|
+
const lineSegments = visibleLines[i];
|
|
950
|
+
const currentLineFinalHeight = lineHeights[i];
|
|
951
|
+
const currentLineMaxAscent = lineAscents[i];
|
|
952
|
+
const currentLineContentHeight = lineContentHeights[i];
|
|
911
953
|
// Calculate line spacing metrics
|
|
912
954
|
const currentLineLeading = currentLineFinalHeight - currentLineContentHeight;
|
|
913
955
|
const currentLineSpaceAbove = Math.max(0, currentLineLeading / 2);
|
|
@@ -1065,9 +1107,7 @@ class TextNode extends layout_canvas_util.BoxNode {
|
|
|
1065
1107
|
if (applyEllipsisAfter) {
|
|
1066
1108
|
const ellipsisRemainingWidth = contentX + contentWidth - currentX;
|
|
1067
1109
|
if (ellipsisRemainingWidth >= ellipsisWidth) {
|
|
1068
|
-
|
|
1069
|
-
const originalVariant = ctx.fontVariant;
|
|
1070
|
-
const originalFill = ctx.fillStyle;
|
|
1110
|
+
ctx.save();
|
|
1071
1111
|
ctx.font = this.getFontString(ellipsisStyle);
|
|
1072
1112
|
if (typeof this.props.fontVariant === 'string') {
|
|
1073
1113
|
ctx.fontVariant = this.props.fontVariant;
|
|
@@ -1083,14 +1123,7 @@ class TextNode extends layout_canvas_util.BoxNode {
|
|
|
1083
1123
|
}
|
|
1084
1124
|
ctx.fillStyle = ellipsisStyle?.color || this.props.color || 'black';
|
|
1085
1125
|
ctx.fillText(ellipsisChar, currentX, lineY, Math.max(0, ellipsisRemainingWidth + 1));
|
|
1086
|
-
ctx.
|
|
1087
|
-
if (originalVariant !== 'normal') {
|
|
1088
|
-
ctx.fontVariant = originalVariant;
|
|
1089
|
-
}
|
|
1090
|
-
else if (ctx.fontVariant !== 'normal') {
|
|
1091
|
-
ctx.fontVariant = 'normal';
|
|
1092
|
-
}
|
|
1093
|
-
ctx.fillStyle = originalFill;
|
|
1126
|
+
ctx.restore();
|
|
1094
1127
|
}
|
|
1095
1128
|
break;
|
|
1096
1129
|
}
|