import { getBaseItem } from "@/core/components/util"; import { getPaperConfig, paperConfigs, PaperKey, } from "@/example/components/slide/actions"; import { tableCompassKey, tableCoverHeight, tableCoverKey, tableCoverScaleKey, tableCoverWidth, tableTableKey, tableTitleKey, } from "../../../constant"; import { matResponse } from "@/core/components/table"; import { Transform } from "konva/lib/Util"; import { getFixPosition } from "@/utils/bound"; import { getImage } from "@/utils/resource"; import { ImageData } from "@/core/components/image"; import { DrawData } from "@/core/components"; import { getEmptyStoreData, StoreData } from "@/core/store/store"; import { defaultLayer } from "@/constant"; import { getIconStyle, IconData } from "@/core/components/icon"; import { MathUtils } from "three"; import { getCurrentNdxRaw, getSerialFontW, joinKey, SerialData, defaultStyle as serialDefaultStyle, } from "@/core/components/serial"; import type { TabCover } from "../../store"; export const getRealPixel = (real: number, paperKey: PaperKey) => { const realPixelScale = paperConfigs[paperKey].scale; return real * realPixelScale; }; export const getPixelReal = (pixel: number, paperKey: PaperKey) => { const realPixelScale = paperConfigs[paperKey].scale; return pixel / realPixelScale; }; export const transformPaper = ( real: number, paperKey: PaperKey, toPaperKey: PaperKey, ) => { const scale = paperConfigs[paperKey].scale / paperConfigs[toPaperKey].scale; return real * scale; }; export const getCoverPaperScale = (cover: ImageData, paperKey: PaperKey) => { let pixelScale = (cover.widthRaw! / cover.width) * cover.proportion!.scale; const realPixelScale = paperConfigs[paperKey].scale; return realPixelScale * pixelScale; }; export const getCoverWidthRaw = ( cover: ImageData, paperKey: PaperKey, pp: number, ) => { const pixelScale = pp / paperConfigs[paperKey].scale; const widthRaw = (pixelScale / cover.proportion!.scale) * cover.width; return widthRaw; }; export const setCoverPaperScale = ( cover: ImageData, paperKey: PaperKey, scale: number, ) => { const realPixelScale = paperConfigs[paperKey].scale; cover.width = cover.widthRaw! / (scale / realPixelScale / cover.proportion!.scale); cover.height = (cover.heightRaw! / cover.widthRaw!) * cover.width; }; export const genTabulationData = async ( paperKey: PaperKey, compass?: number, cover?: TabCover | null, ) => { const temp: Record = await window.platform.getTableTemp(); const { margin, size } = getPaperConfig( paperConfigs[paperKey].size, paperConfigs[paperKey].scale, ); const getTable = async () => { const w1 = getRealPixel(25, paperKey); const w2 = getRealPixel(55, paperKey); const h = getRealPixel(8, paperKey); const nameColl = { width: w1, height: h, padding: getRealPixel(2, paperKey), content: "", align: "center", fontSize: getRealPixel(4, paperKey), fontColor: "#000000", }; const valueColl = { ...nameColl, width: w2 }; const tableTemp = temp.table; const rows = Object.entries(tableTemp); const data = { ...getBaseItem(), content: rows.map(([name, value]) => [ { ...nameColl, content: name }, { ...valueColl, content: value }, ]), fontSize: getRealPixel(4, paperKey), key: tableTableKey, width: nameColl.width + valueColl.width, height: nameColl.height * rows.length, titleHeight: h, title: temp.tableTitle, mat: [1, 0, 0, 1, 0, 0], fill: null, }; const pos = getFixPosition( { right: getRealPixel(15, paperKey) + margin[1], bottom: getRealPixel(15, paperKey) + margin[2], }, data, size, ); return matResponse({ data, mat: new Transform().translate(pos.x, pos.y) }); }; const getCover = async () => { if (!cover) return; const image = await getImage(window.platform.getResource(cover.url)); const rectScale = image.width / image.height; const tableCoverScale = tableCoverWidth / tableCoverHeight; let width: number, height: number; if (rectScale > tableCoverScale) { width = transformPaper(tableCoverWidth, paperKey, "a4"); height = width / rectScale; } else { height = transformPaper(tableCoverHeight, paperKey, "a4"); width = rectScale * height; } const coverData = { ...getBaseItem(), cornerRadius: 0, strokeWidth: 0, disableDelete: true, url: cover.url, key: tableCoverKey, proportion: cover.proportion, disableTransformer: true, widthRaw: cover.width, showScale: true, heightRaw: cover.height, zIndex: -1, width, height, mat: [1, 0, 0, 1, 0, 0], itemName: "比例", }; const pos = getFixPosition( { left: coverData.width / 2 + margin[3] + getRealPixel(15, paperKey), bottom: -coverData.height / 2 + margin[2] + getRealPixel(15, paperKey), }, coverData, size, ); coverData.mat[4] = pos.x; coverData.mat[5] = pos.y; const scale = getCoverPaperScale(coverData, paperKey); setCoverPaperScale(coverData, paperKey, Math.round(scale / 10) * 10 || 10); return coverData; }; const getCoverScale = (cover: ImageData) => { const scale = (cover.widthRaw! / cover.width) * cover.proportion!.scale; const text = { ...getBaseItem(), content: `1:${scale}`, width: getRealPixel(30, paperKey), heihgt: getRealPixel(4.8, paperKey), fontSize: getRealPixel(4, paperKey), disableEditText: true, key: tableCoverScaleKey, disableDelete: true, align: "center", mat: [1, 0, 0, 1, 0, 0], }; const x = cover.mat[4] - (text.width || 0) / 2; const y = cover.mat[5] + cover.height / 2 + getRealPixel(5, paperKey); text.mat[4] = x; text.mat[5] = y; return text; }; const getTitle = () => { const title = { ...getBaseItem(), content: temp.title, width: size.width - margin[1] - margin[3], heihgt: getRealPixel(14.4, paperKey), fontSize: getRealPixel(12, paperKey), key: tableTitleKey, align: "center", mat: [1, 0, 0, 1, 0, 0], }; const pos = { x: margin[3], y: getRealPixel(15, paperKey) + margin[0], }; title.mat[4] = pos.x; title.mat[5] = pos.y; return title; }; const getCompass = async () => { const mat = new Transform().rotate(MathUtils.degToRad(compass!)); const style = await getIconStyle( "./icons/compass.svg", getRealPixel(37.3366 / 2.3, paperKey), getRealPixel(60 / 2.3, paperKey), ); const data: IconData = { ...getBaseItem(), ...style, disableDelete: true, itemName: "指南针", coverOpcatiy: 0, strokeScaleEnabled: false, key: tableCompassKey, mat: mat.m, name: "指南针", }; console.error("指南针", data); const pos = getFixPosition( { right: getRealPixel(8, paperKey) + margin[1], top: getRealPixel(42, paperKey) + margin[2], }, data, size, ); data.mat[4] = pos.x; data.mat[5] = pos.y; return data; }; const getSerials = (refImage: ImageData, items: TabCover["syncItems"]) => { if (!items) return; const scale = refImage.width / refImage.widthRaw!; const offset = { x: refImage.widthRaw! / 2, y: refImage.heightRaw! / 2, }; const mat = new Transform() .multiply(new Transform(refImage.mat)) .scale(scale, scale) .translate(-offset.x, -offset.y); const serials: SerialData[] = []; let i = 0; for (const shape of items) { const start = { x: shape.rect.x, y: shape.rect.y, // x: refImage.widthRaw, // y: refImage.heightRaw }; const point = mat.point(start); const s = { ...serialDefaultStyle, ...getBaseItem(), padding: 3, key: "join-" + shape.id, content: (++i).toString(), strokeWidth: getRealPixel(0.5, paperKey), mat: [1, 0, 0, 1, point.x, point.y], radiusX: 1, desc: shape.desc || "", radiusY: 1, }; const radius = (getSerialFontW(s) * Math.sqrt(2)) / 2; s.radiusX = s.radiusY = radius; serials.push(s); } return serials; }; const data: DrawData = { table: [await getTable()], serial: [], }; if (temp.title) { data.text = [getTitle()]; } const image = await getCover(); if (image) { data.image = [image]; data.text!.push(getCoverScale(image)); const serials = getSerials(image, cover?.syncItems); if (serials) { data.serial = serials; } } if (compass !== undefined) { data.icon = [await getCompass()]; } return data; }; export const repTabulationStore = async ( paperKey: PaperKey, compass?: number, cover?: TabCover, store?: StoreData, ) => { const repData = await genTabulationData(paperKey, compass, cover); const layer = store?.layers && store?.layers[defaultLayer]; if (!layer || !store.config) { return { ...(store || {}), config: { ...getEmptyStoreData().config, ...(store?.config || {}), }, layers: { ...(store?.layers || {}), [defaultLayer]: repData, }, }; } if (repData.image?.length) { const imageData = repData.image[0]; const images = layer.image || []; const imageNdx = images.findIndex((item) => item.key === imageData.key); if (~imageNdx) { images[imageNdx] = imageData; images[imageNdx] = { ...imageData, mat: images[imageNdx].mat, }; } else { images.push(imageData); } layer.image = images; const scaleData = repData.text!.find( (item) => item.key === tableCoverScaleKey, )!; const texts = layer.text || []; const textNdx = texts.findIndex((item) => item.key === scaleData.key); if (~textNdx) { texts[textNdx].content = scaleData.content; } else { texts.push(scaleData); } layer.text = texts; } if (repData.icon) { const iconData = repData.icon[0]; const icons = layer.icon || []; const iconNdx = icons.findIndex((item) => item.key === iconData.key); if (~iconNdx) { icons[iconNdx] = iconData; } else { icons.push(iconData); } layer.icon = icons; } if (repData.serial) { if (layer.serial) { const oldSerials = [...layer.serial]; const notAutoSerials = oldSerials.filter( (item) => !item.key?.startsWith("join-"), ); const newSerials = [...repData.serial, ...notAutoSerials]; layer.serial = newSerials; const tableNdx = layer.table ? layer.table.findIndex((table) => table.key === joinKey) : -1; if (~tableNdx) { const table = layer.table![tableNdx]; layer.table!.splice(tableNdx, 1); for (const serial of notAutoSerials) { for (let r = 0; r < table.content.length; r++) { for (let c = 0; c < table.content[r].length; c += 2) { if (table.content[r][c].content === serial.content) { serial.desc = table.content[r][c + 1].content; } } } } } const updateSerials = [...repData.serial]; for (const serial of notAutoSerials) { serial.content = getCurrentNdxRaw(updateSerials); updateSerials.push(serial); } } else { layer.serial = repData.serial; } } // if (import.meta.env.DEV) { // layer.table = repData.table // layer.text = repData.text // } store.layers[defaultLayer] = layer; return store; };