62 lines
2.3 KiB
TypeScript
62 lines
2.3 KiB
TypeScript
/**
|
|
* 样式与坐标转换的共享工具(HTML / SVG 共用)。
|
|
*
|
|
* 布局结果内部统一使用 mm;SVG/HTML 输出按需换算为 px。
|
|
* 样式统一转成 CSS 声明,保证各 Renderer 视觉一致(§15)。
|
|
*/
|
|
import type { ResolvedStyle } from "@report/core"
|
|
import { mmToPx } from "@report/layout"
|
|
import type { RenderOptions } from "./types.js"
|
|
|
|
/** 把 mm 值按目标单位换算为数值(SVG/HTML 里直接写数字)。 */
|
|
export function toUnit(value: number, options: RenderOptions): number {
|
|
return options.unit === "px" ? mmToPx(value) : value
|
|
}
|
|
|
|
/** 单位后缀。 */
|
|
export function unitSuffix(options: RenderOptions): string {
|
|
return options.unit === "px" ? "px" : "mm"
|
|
}
|
|
|
|
/**
|
|
* 把已解析样式转成 CSS 声明字符串。
|
|
*
|
|
* 字号在文档中是 pt,HTML/SVG 里也以 pt 表达,保证与布局测量一致。
|
|
* 边框只输出四边统一值;逐边覆盖的边框由 Renderer 按需处理。
|
|
*/
|
|
export function styleToCss(style: ResolvedStyle): string {
|
|
const parts: string[] = []
|
|
parts.push(`font-family:${style.fontFamily}`)
|
|
parts.push(`font-size:${style.fontSize}pt`)
|
|
parts.push(`font-weight:${style.fontWeight}`)
|
|
parts.push(`font-style:${style.fontStyle}`)
|
|
parts.push(`line-height:${style.lineHeight}`)
|
|
parts.push(`color:${style.color}`)
|
|
if (style.background && style.background !== "transparent") {
|
|
parts.push(`background:${style.background}`)
|
|
}
|
|
parts.push(`text-align:${style.align}`)
|
|
parts.push(`text-decoration:${style.textDecoration}`)
|
|
if (style.border) {
|
|
const width = style.border.width ?? 0.1
|
|
const color = style.border.color ?? "#000000"
|
|
const lineStyle = style.border.style ?? "solid"
|
|
parts.push(`border:${width}mm ${lineStyle} ${color}`)
|
|
}
|
|
return parts.join(";")
|
|
}
|
|
|
|
/** 把已解析样式转成 SVG 文本属性(fill / font-size 等)。 */
|
|
export function styleToSvgTextAttrs(style: ResolvedStyle): Record<string, string> {
|
|
const attrs: Record<string, string> = {
|
|
fill: style.color,
|
|
"font-family": style.fontFamily,
|
|
"font-size": `${style.fontSize}pt`,
|
|
"font-weight": String(style.fontWeight),
|
|
"font-style": style.fontStyle,
|
|
}
|
|
if (style.textDecoration === "underline") attrs["text-decoration"] = "underline"
|
|
if (style.textDecoration === "line-through") attrs["text-decoration"] = "line-through"
|
|
return attrs
|
|
}
|