This commit is contained in:
iqudoo
2026-06-12 20:58:51 +08:00
parent c9a187bf9b
commit 239e2eeebd
9 changed files with 499 additions and 340 deletions

View File

@@ -15,6 +15,86 @@ export interface BorderSides {
left: boolean;
}
export interface PaddingMm {
top: number;
right: number;
bottom: number;
left: number;
}
export interface BorderSideStyle {
width: number;
color: string;
}
export type BorderConfig = Record<ElementSide, BorderSideStyle>;
export function resolvePaddingMm(elem: TemplateElement): PaddingMm {
const base = elem.padding ?? 0;
const val = (specific?: number) =>
specific !== undefined && specific !== null ? specific : base;
return {
top: val(elem.paddingTop),
right: val(elem.paddingRight),
bottom: val(elem.paddingBottom),
left: val(elem.paddingLeft),
};
}
export function getPaddedRectPx(
x: number,
y: number,
w: number,
h: number,
elem: TemplateElement,
scale: number
) {
const pad = resolvePaddingMm(elem);
const top = Math.round(pad.top * scale);
const right = Math.round(pad.right * scale);
const bottom = Math.round(pad.bottom * scale);
const left = Math.round(pad.left * scale);
return {
x: x + left,
y: y + top,
w: Math.max(1, w - left - right),
h: Math.max(1, h - top - bottom),
paddingPx: { top, right, bottom, left },
};
}
export function resolveBorderConfig(elem: TemplateElement): BorderConfig {
const baseWidth = elem.borderWidth ?? 0;
const baseColor = elem.borderColor || '#111827';
const legacy = elem.borderSides ?? {};
const resolveSide = (
side: ElementSide,
widthOverride: number | undefined,
colorOverride: string | undefined
): BorderSideStyle => {
let width: number;
if (widthOverride !== undefined && widthOverride !== null) {
width = widthOverride;
} else if (baseWidth <= 0 || legacy[side] === false) {
width = 0;
} else {
width = baseWidth;
}
return {
width,
color: colorOverride?.trim() ? colorOverride : baseColor,
};
};
return {
top: resolveSide('top', elem.borderWidthTop, elem.borderColorTop),
right: resolveSide('right', elem.borderWidthRight, elem.borderColorRight),
bottom: resolveSide('bottom', elem.borderWidthBottom, elem.borderColorBottom),
left: resolveSide('left', elem.borderWidthLeft, elem.borderColorLeft),
};
}
export function resolveCornerRadiiPx(
elem: TemplateElement,
scale: number,
@@ -39,16 +119,12 @@ export function resolveCornerRadiiPx(
}
export function resolveBorderSides(elem: TemplateElement): BorderSides {
const width = elem.borderWidth ?? 0;
if (width <= 0) {
return { top: false, right: false, bottom: false, left: false };
}
const sides = elem.borderSides ?? {};
const cfg = resolveBorderConfig(elem);
return {
top: sides.top !== false,
right: sides.right !== false,
bottom: sides.bottom !== false,
left: sides.left !== false,
top: cfg.top.width > 0,
right: cfg.right.width > 0,
bottom: cfg.bottom.width > 0,
left: cfg.left.width > 0,
};
}
@@ -106,20 +182,17 @@ export function drawElementBorders(
elem: TemplateElement,
scale: number
) {
const widthMm = elem.borderWidth ?? 0;
if (widthMm <= 0) return;
const color = elem.borderColor || '#111827';
const lw = Math.max(1, widthMm * scale);
const border = resolveBorderConfig(elem);
const { tl, tr, br, bl } = radii;
const inset = lw / 2;
ctx.strokeStyle = color;
ctx.lineWidth = lw;
ctx.lineCap = 'butt';
ctx.lineJoin = 'round';
if (sides.top) {
const lw = Math.max(1, border.top.width * scale);
const inset = lw / 2;
ctx.strokeStyle = border.top.color;
ctx.lineWidth = lw;
ctx.beginPath();
if (sides.left && tl > 0) {
ctx.arc(x + tl, y + tl, Math.max(0, tl - inset), Math.PI, 1.5 * Math.PI);
@@ -136,6 +209,10 @@ export function drawElementBorders(
}
if (sides.right) {
const lw = Math.max(1, border.right.width * scale);
const inset = lw / 2;
ctx.strokeStyle = border.right.color;
ctx.lineWidth = lw;
ctx.beginPath();
const topStart = sides.top && tr > 0;
if (topStart) {
@@ -153,6 +230,10 @@ export function drawElementBorders(
}
if (sides.bottom) {
const lw = Math.max(1, border.bottom.width * scale);
const inset = lw / 2;
ctx.strokeStyle = border.bottom.color;
ctx.lineWidth = lw;
ctx.beginPath();
if (sides.right && br > 0) {
ctx.moveTo(x + w - inset, y + h - br);
@@ -170,6 +251,10 @@ export function drawElementBorders(
}
if (sides.left) {
const lw = Math.max(1, border.left.width * scale);
const inset = lw / 2;
ctx.strokeStyle = border.left.color;
ctx.lineWidth = lw;
ctx.beginPath();
const bottomStart = sides.bottom && bl > 0;
if (bottomStart) {
@@ -202,20 +287,3 @@ export function drawElementChrome(
drawElementBorders(ctx, x, y, w, h, radii, sides, elem, scale);
return { radii, sides };
}
export function toggleSide(
current: Partial<Record<ElementSide, boolean>> | undefined,
side: ElementSide
): Partial<Record<ElementSide, boolean>> {
const next = { ...current };
const enabled = current?.[side] !== false;
next[side] = !enabled;
return next;
}
export function isSideEnabled(
sides: Partial<Record<ElementSide, boolean>> | undefined,
side: ElementSide
): boolean {
return sides?.[side] !== false;
}