* Resolve ` ` into a CSS background value using repeating gradients. * * OOXML defines 40+ pattern presets. We support the most common ones and * fall back to a simple foreground/background 50% mix for unknown patterns.
(pattFill: SafeXmlNode, ctx: RenderContext)
| 274 | * fall back to a simple foreground/background 50% mix for unknown patterns. |
| 275 | */ |
| 276 | function resolvePatternFill(pattFill: SafeXmlNode, ctx: RenderContext): string { |
| 277 | const preset = pattFill.attr('prst') ?? 'solid' |
| 278 | |
| 279 | // Foreground and background colors |
| 280 | let fg = '#000000' |
| 281 | let bg = '#ffffff' |
| 282 | |
| 283 | const fgClr = pattFill.child('fgClr') |
| 284 | if (fgClr.exists()) { |
| 285 | const { color, alpha } = resolveColor(fgClr, ctx) |
| 286 | fg = toCssColor(color, alpha) |
| 287 | } |
| 288 | |
| 289 | const bgClr = pattFill.child('bgClr') |
| 290 | if (bgClr.exists()) { |
| 291 | const { color, alpha } = resolveColor(bgClr, ctx) |
| 292 | bg = toCssColor(color, alpha) |
| 293 | } |
| 294 | |
| 295 | // Size of pattern tile in px |
| 296 | const s = 8 |
| 297 | |
| 298 | // Helper: returns CSS `background` shorthand with repeating pattern layer(s) over bg color. |
| 299 | // Format: "<gradient-layer> 0 0/<size>, <bg-color-layer>" |
| 300 | // This is a valid multi-layer CSS background shorthand. |
| 301 | const pat = (gradient: string): string => `${gradient} 0 0/${s}px ${s}px, ${bg}` |
| 302 | const pat2 = (g1: string, g2: string): string => |
| 303 | `${g1} 0 0/${s}px ${s}px, ${g2} 0 0/${s}px ${s}px, ${bg}` |
| 304 | |
| 305 | switch (preset) { |
| 306 | // Solid fills |
| 307 | case 'solid': |
| 308 | case 'solidDmnd': |
| 309 | return fg |
| 310 | |
| 311 | // Percentage fills (dots on background) |
| 312 | case 'pct5': |
| 313 | case 'pct10': |
| 314 | case 'pct20': |
| 315 | case 'pct25': |
| 316 | return pat(`radial-gradient(${fg} 1px, transparent 1px)`) |
| 317 | case 'pct30': |
| 318 | case 'pct40': |
| 319 | case 'pct50': |
| 320 | return pat(`radial-gradient(${fg} 1.5px, transparent 1.5px)`) |
| 321 | case 'pct60': |
| 322 | case 'pct70': |
| 323 | case 'pct75': |
| 324 | case 'pct80': |
| 325 | case 'pct90': |
| 326 | return pat(`radial-gradient(${fg} 2.5px, transparent 2.5px)`) |
| 327 | |
| 328 | // Horizontal lines |
| 329 | case 'horz': |
| 330 | case 'ltHorz': |
| 331 | case 'narHorz': |
| 332 | case 'dkHorz': |
| 333 | return pat( |
no test coverage detected