diff --git a/demos/stefan/untitled-board-game/ubg-cards-exporter.js b/demos/stefan/untitled-board-game/ubg-cards-exporter.js
new file mode 100644
index 000000000..835d91bbc
--- /dev/null
+++ b/demos/stefan/untitled-board-game/ubg-cards-exporter.js
@@ -0,0 +1,168 @@
+/* global globalThis */
+"disable deepeval"
+
+import moment from "src/external/moment.js";
+
+// #TODO: remove duplication
+const POKER_CARD_SIZE_INCHES = lively.pt(2.5, 3.5);
+const POKER_CARD_SIZE_MM = POKER_CARD_SIZE_INCHES.scaleBy(25.4);
+
+export default class CardExporter {
+
+ /*MD ## Helper MD*/
+ static async printWithSavedWorld(fn) {
+ const oldBody = window.oldBody = Array.from(document.body.childNodes)
+ const bodyCSS = document.body.style.cssText
+ const title = document.title
+
+ try {
+ await Promise.race([fn(), lively.sleep(10000)])
+
+ document.querySelectorAll('lively-notification-list').forEach(list => list.remove())
+ const mutationIndicator = document.querySelector('#mutationIndicator')
+ if (mutationIndicator) {
+ mutationIndicator.remove()
+ }
+ document.title = `cards-${moment().format('YYYY-MM-DD-HH-mm-ss')}`
+
+ return window.print()
+ } finally {
+ document.body.innerHTML = ""
+ document.body.style = bodyCSS
+ document.body.append(...oldBody)
+ document.title = title
+ }
+ }
+
+ /*MD ## Layout & Rendering MD*/
+ static async execute(cards, ubgCards) {
+ const cardsToPrint = cards.slice(0, 14)
+
+ this.printWithSavedWorld(async () => {
+ const body = document.body
+ body.innerHTML = ''
+ // body.style = ""
+
+ await this.buildCards(undefined, cardsToPrint, false, ubgCards)
+ })
+ }
+
+ static addGridPage() {
+ const grid =
;
+ document.body.append();
+ return grid;
+ }
+
+ static placeHolder() {
+ return placeholder
+ }
+
+ static cardBack(card) {
+ return {card.getName()}
+ }
+
+ static async renderCard(card, ubgCards) {
+ const ubg = ubgCards;
+
+ const cardPreview = document.createElement('ubg-card')
+ cardPreview.setCard(card)
+ cardPreview.src = ubg.src
+ await cardPreview.render()
+ return cardPreview
+ }
+
+ static async buildCards(doc, cardsToPrint, skipCardBack, ubgCards) {
+ const GAP = lively.pt(.2, .2);
+ const A4_WIDTH = 210
+ const A4_HEIGHT = 297
+
+ const rowsPerPage = Math.max(((A4_HEIGHT + GAP.y) / (POKER_CARD_SIZE_MM.y + GAP.y)).floor(), 1);
+ const cardsPerRow = Math.max(((A4_WIDTH + GAP.x) / (POKER_CARD_SIZE_MM.x + GAP.x)).floor(), 1);
+ const cardsPerPage = rowsPerPage * cardsPerRow;
+
+ this.prepareGridSizes(cardsPerRow)
+
+ let currentPage = 0;
+ while (cardsToPrint.length > cardsPerPage * currentPage) {
+ const frontGrid = this.addGridPage()
+ const backGrid = this.addGridPage()
+
+ for(let rowIndex = 0; rowIndex < rowsPerPage; rowIndex++) {
+ for(let cIndex = 0; cIndex < cardsPerRow; cIndex++) {
+ const card = cardsToPrint[cIndex + rowIndex * cardsPerRow + currentPage * cardsPerPage];
+ if (card) {
+ frontGrid.append(await this.renderCard(card, ubgCards))
+ } else {
+ frontGrid.append(this.placeHolder())
+ }
+
+ const cardBack = cardsToPrint[cardsPerRow - cIndex - 1 + rowIndex * cardsPerRow + currentPage * cardsPerPage];
+ if (cardBack) {
+ // #TODO: cardBacks
+ backGrid.append(await this.cardBack(cardBack))
+ } else {
+ backGrid.append(this.placeHolder())
+ }
+ }
+ }
+
+ currentPage++;
+ }
+ }
+
+ static prepareGridSizes(cardsPerRow) {
+ const style = ;
+ style.textContent = `
+@page {
+size: A4 portrait;
+margin: 0;
+}
+
+.page {
+page-break-before: always;
+
+
+
+width: 100vw;
+height: 100vh;
+}
+
+.grid-wrapper {
+display: grid;
+place-items: center;
+height: 100vh;
+}
+
+.grid {
+
+z-index: 100;
+display: grid;
+gap: .2mm;
+grid-template-columns: repeat(${cardsPerRow}, ${POKER_CARD_SIZE_INCHES.x}in);
+width: min-content;
+}
+`;
+ document.body.append(style);
+ }
+
+}
+
+globalThis.__ubg_html_to_pdf_exporter__ = CardExporter
diff --git a/src/components/widgets/ubg-card.js b/src/components/widgets/ubg-card.js
index 712e2be82..45cc26ef1 100644
--- a/src/components/widgets/ubg-card.js
+++ b/src/components/widgets/ubg-card.js
@@ -110,18 +110,6 @@ if (globalThis.__ubg_font_cache__) {
globalThis.__ubg_font_cache__ = new FontCache();
}
-// const BASE64_FONT_AWESOME_THIN = await globalThis.__ubg_font_cache__.BASE64_FONT_AWESOME_THIN()
-// const BASE64_FONT_AWESOME_LIGHT = await globalThis.__ubg_font_cache__.BASE64_FONT_AWESOME_LIGHT()
-// const BASE64_FONT_AWESOME_REGULAR = await globalThis.__ubg_font_cache__.BASE64_FONT_AWESOME_REGULAR()
-// const BASE64_FONT_AWESOME_SOLID = await globalThis.__ubg_font_cache__.BASE64_FONT_AWESOME_SOLID()
-// const BASE64_FONT_AWESOME_BRANDS = await globalThis.__ubg_font_cache__.BASE64_FONT_AWESOME_BRANDS()
-// const BASE64_FONT_AWESOME_DUOTONE = await globalThis.__ubg_font_cache__.BASE64_FONT_AWESOME_DUOTONE()
-
-// const BASE64_BeaufortforLOLJaBold = await globalThis.__ubg_font_cache__.BASE64_BeaufortforLOLJaBold()
-// const BASE64_BeaufortforLOLJaRegular = await globalThis.__ubg_font_cache__.BASE64_BeaufortforLOLJaRegular()
-// const BASE64_Univers_55 = await globalThis.__ubg_font_cache__.BASE64_Univers_55()
-// const BASE64_Univers45LightItalic = await globalThis.__ubg_font_cache__.BASE64_Univers45LightItalic()
-
const FONT_NAME_FA_THIN_100 = 'fa-thin-100'
const FONT_NAME_FA_LIGHT_300 = 'fa-light-300'
const FONT_NAME_FA_REGULAR_400 = 'fa-regular-400'
@@ -137,11 +125,6 @@ const FONT_NAME_UNIVERS_45_LIGHT_ITALIC = 'Univers 45 Light Italic'
// Card group name (ELITE, SPIDER, YETI, etc.) -- Univers 59 // #BROKEN?? #TODO
const FONT_NAME_CARD_TYPE = FONT_NAME_UNIVERS_55
-// Card name, card cost, card stats -- Beaufort for LOL Bold
-const FONT_NAME_CARD_NAME = FONT_NAME_BEAUFORT_FOR_LOL_BOLD
-const FONT_NAME_CARD_COST = FONT_NAME_BEAUFORT_FOR_LOL_BOLD
-const FONT_NAME_CARD_VP = FONT_NAME_BEAUFORT_FOR_LOL_BOLD
-
// Card description -- Univers 55
const FONT_NAME_CARD_TEXT = FONT_NAME_UNIVERS_55
@@ -158,6 +141,7 @@ const CSS_FONT_FAMILY_BEAUFORT_FOR_LOL_REGULAR = "Beaufort for LOL Regular"
const CSS_FONT_FAMILY_UNIVERS_55 = "Univers 55"
const CSS_FONT_FAMILY_UNIVERS_45_LIGHT_ITALIC = "Univers 45 Light Italic"
+// Card name, card cost, card stats -- Beaufort for LOL Bold
const CSS_FONT_FAMILY_CARD_NAME = CSS_FONT_FAMILY_BEAUFORT_FOR_LOL_BOLD
const CSS_FONT_FAMILY_CARD_COST = CSS_FONT_FAMILY_BEAUFORT_FOR_LOL_BOLD
const CSS_FONT_FAMILY_CARD_VP = CSS_FONT_FAMILY_BEAUFORT_FOR_LOL_BOLD
@@ -830,10 +814,7 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1
/*MD ## --- MD*/
// #important
- static async renderRuleText(cardEditor, cardDesc, doc, outsideBorder, ruleBox, {
- insetTextBy = 2,
- beforeRenderRules = () => {}
- } = { }) {
+ static async renderRuleText(cardEditor, cardDesc, outsideBorder, ruleBox, options) {
let printedRules = cardDesc.getText() || '';
// old big cast icon with small tap
@@ -904,7 +885,7 @@ ${SVG.elementSymbol(others[2], lively.pt(12.5, 8.5), 1.5)}`, lively.rect(0, 0, 1
printedRules = this.renderHedronIcon(printedRules)
printedRules = this.renderTapIcon(printedRules)
- return this.renderToDoc(cardEditor, outsideBorder, ruleBox, insetTextBy, printedRules, beforeRenderRules, doc)
+ this.renderToDoc(cardEditor, outsideBorder, ruleBox, printedRules, options)
}
static renderReminderText(printedRules, cardEditor, cardDesc) {
@@ -1389,7 +1370,19 @@ ${textToPrint}`, undefined, undefined, 'transform:scale(1);');
});
}
- static async renderToDoc(cardEditor, outsideBorder, ruleBox, insetTextBy, printedRules, beforeRenderRules, doc) {
+ static async renderToDoc(cardEditor, outsideBorder, ruleBox, printedRules, options) {
+ const {
+ insetBoxBy = 1,
+ insetTextBy = 1,
+ innerStrokeWidth = .2,
+ innerStrokeColor = 'black',
+ innerFillColor = 'white',
+ innerFillOpacity = .5,
+ outerStrokeColor= 'gray',
+ outerFillColor = 'white',
+ outerFillOpacity = .5,
+ } = options
+
const textShadow = `text-shadow:
-1px -1px 0 #fff,
1px -1px 0 #fff,
@@ -1399,103 +1392,37 @@ ${textToPrint}`, undefined, undefined, 'transform:scale(1);');
1px 0 0 #fff,
0 1px 0 #fff,
0 -1px 0 #fff;`
-
- const ruleTextBox = ruleBox.insetBy(insetTextBy);
- // doc.rect(ruleBox.x, ruleBox.y, ruleBox.width, ruleBox.height, 'FD')
- cardEditor.debugRect(ruleTextBox)
- const elementHTML = ;
- elementHTML.innerHTML = printedRules;
- cardEditor.content.append(elementHTML)
- beforeRenderRules(undefined, elementHTML)
- return;
- document.body.append(elementHTML);
-
- const canvas = await html2canvas(elementHTML, {
- backgroundColor: null,
- ignoreElements: element => {
- try {
- if (!element) {
- return true;
- }
-
- return !(element === document.head || element.id === RUNETERRA_FONT_ID || element === document.body || element === elementHTML || elementHTML.contains(element));
- } catch (e) {}
- }
- });
- // elementHTML.remove();
-
- const EXISTING_CANVAS_ID = 'exist-canvas';
- const EXISTING_ELEMENT_ID = 'exist-element';
- const existCanvas = document.getElementById(EXISTING_CANVAS_ID);
- existCanvas && existCanvas.remove();
- document.body.appendChild(canvas);
- canvas.id = EXISTING_CANVAS_ID;
-
- const existElement = document.getElementById(EXISTING_ELEMENT_ID);
- existElement && existElement.remove();
- document.body.appendChild(elementHTML);
- elementHTML.style.overflow = 'visible';
- elementHTML.id = EXISTING_ELEMENT_ID;
-
- const imgData = canvas.toDataURL('image/png');
- const imgRect = lively.rect(0, 0, canvas.width, canvas.height);
- const scaledRect = imgRect.fitToBounds(ruleTextBox, true);
- scaledRect.y = ruleTextBox.y + ruleTextBox.height - scaledRect.height;
-
-
- doc.addImage(imgData, "PNG", ...scaledRect::xYWidthHeight());
-
- return scaledRect
- }
-}
+ cardEditor.content.append(outerBox)
-function justify(pdfGen, text, xStart, yStart, textWidth) {
- text = text.replace(/(?:\r\n|\r|\n)/g, ' ');
- text = text.replace(/ +(?= )/g, '');
- const lineHeight = pdfGen.getTextDimensions('a').h * 1.15;
- const words = text.split(' ');
- let lineNumber = 0;
- let wordsInfo = [];
- let lineLength = 0;
- for (const word of words) {
- const wordLength = pdfGen.getTextWidth(word + ' ');
- if (wordLength + lineLength > textWidth) {
- writeLine(pdfGen, wordsInfo, lineLength, lineNumber++, xStart, yStart, lineHeight, textWidth);
- wordsInfo = [];
- lineLength = 0;
- }
- wordsInfo.push({ text, wordLength });
- lineLength += wordLength;
- }
- if (wordsInfo.length > 0) {
- writeLastLine(wordsInfo, pdfGen, xStart, yStart, lineNumber, lineHeight);
- }
-}
-function writeLastLine(wordsInfo, pdfGen, xStart, yStart, lineNumber, lineHeight) {
- const line = wordsInfo.map(x => x.text).join(' ');
- pdfGen.text(line, xStart, yStart + lineNumber * lineHeight);
-}
-
-function writeLine(pdfGen, wordsInfo, lineLength, lineNumber, xStart, yStart, lineHeight, textWidth) {
+ const ruleTextBox = ruleBox.insetBy(insetTextBy);
+ // cardEditor.debugRect(ruleTextBox)
+ const marginCalc = `${insetBoxBy}mm - ${innerStrokeWidth}mm / 2`;
+ const paddingCalc = `${insetTextBy}mm - ${innerStrokeWidth}mm / 2`;
+ const ruleTextElement = ;
- const wordSpacing = (textWidth - lineLength) / (wordsInfo.length - 1);
- let x = xStart;
- const y = yStart + lineNumber * lineHeight;
- for (const wordInfo of wordsInfo) {
- pdfGen.text(wordInfo.text, x, y);
- x += wordInfo.wordLength + wordSpacing;
+ ruleTextElement.innerHTML = printedRules;
+ outerBox.append(ruleTextElement)
}
}
@@ -1965,86 +1892,6 @@ export class Cards extends Morph {
return (await this.assetsFolder.fetchStats()).contents;
}
- /*MD #### Fonts MD*/
- addFont(doc, vfsName, fontName, fontDataBase64) {
- // "data:font/ttf;base64," +
- const fontBase64 = fontDataBase64;
- doc.addFileToVFS(vfsName, fontBase64);
- doc.addFont(vfsName, fontName, 'normal');
- }
-
- async ensureFont(doc, fontName) {
- throw new Error('Attempted Font Loading ' + fontName)
- if (!doc.__ubg_fonts__) {
- doc.__ubg_fonts__ = {}
- }
-
- if (doc.__ubg_fonts__[fontName]) {
- lively.notify(fontName, 'existing font')
- return
- }
-
- doc.__ubg_fonts__[fontName] = true
-
- // convert fonts to jspdf-compatible format at https://peckconsulting.s3.amazonaws.com/fontconverter/fontconverter.html
- const allFontData = {
- [FONT_NAME_FA_THIN_100]: {
- vfsName: 'fa-thin-100.ttf',
- fontDataBase64: BASE64_FONT_AWESOME_THIN
- },
- [FONT_NAME_FA_LIGHT_300]: {
- vfsName: 'fa-light-300.ttf',
- fontDataBase64: BASE64_FONT_AWESOME_LIGHT
- },
- [FONT_NAME_FA_REGULAR_400]: {
- vfsName: 'fa-regular-400.ttf',
- fontDataBase64: BASE64_FONT_AWESOME_REGULAR
- },
- [FONT_NAME_FA_SOLID_900]: {
- vfsName: 'fa-solid-900.ttf',
- fontDataBase64: BASE64_FONT_AWESOME_SOLID
- },
- [FONT_NAME_FA_BRANDS_400]: {
- vfsName: 'fa-brands-400.ttf',
- fontDataBase64: BASE64_FONT_AWESOME_BRANDS
- },
- [FONT_NAME_FA_DUOTONE_900]: {
- vfsName: 'fa-duotone-900.ttf',
- fontDataBase64: BASE64_FONT_AWESOME_DUOTONE
- },
-
- [FONT_NAME_BEAUFORT_FOR_LOL_BOLD]: {
- vfsName: 'BeaufortforLOLJa-Bold-normal.ttf',
- fontDataBase64: BASE64_BeaufortforLOLJaBold
- },
- [FONT_NAME_BEAUFORT_FOR_LOL_REGULAR]: {
- vfsName: 'BeaufortforLOLJa-Regular-normal.ttf',
- fontDataBase64: BASE64_BeaufortforLOLJaRegular
- },
- [FONT_NAME_UNIVERS_55]: {
- vfsName: 'univers_55-normal.ttf',
- fontDataBase64: BASE64_Univers_55
- },
- [FONT_NAME_UNIVERS_45_LIGHT_ITALIC]: {
- vfsName: 'univers-45-light-italic.ttf',
- fontDataBase64: BASE64_Univers45LightItalic
- },
- }
-
- const fontData = allFontData[fontName]
- if (!fontData) {
- throw new Error('Unknown font: ' + fontName)
- }
- const { vfsName, fontDataBase64 } = fontData
- this.addFont(doc, vfsName, fontName, fontDataBase64);
- }
-
- async setAndEnsureFont(doc, fontName, fontStyle) {
- // return;
- await this.ensureFont(doc, fontName)
- doc.setFont(fontName, fontStyle)
- }
-
/*MD ### BUILD MD*/
async buildCards(doc, cardsToPrint, skipCardBack) {
const GAP = lively.pt(.2, .2);
@@ -2207,130 +2054,93 @@ export class Cards extends Morph {
}
async renderMagicStyle(doc, cardDesc, outsideBorder, assetsInfo) {
- const currentVersion = cardDesc.versions.last;
-
const [BOX_FILL_COLOR, BOX_STROKE_COLOR, BOX_FILL_OPACITY] = this.colorsForCard(cardDesc);
-// // black border
-// doc::withGraphicsState(() => {
-// doc.setFillColor(0.0);
-// doc.roundedRect(...outsideBorder::xYWidthHeight(), 3, 3, 'F');
-// });
-
-// // innerBorder
-// const innerBorder = outsideBorder.insetBy(3);
-// // doc.setFillColor(120, 120, 120);
-// // doc.roundedRect(...innerBorder::xYWidthHeight(), 3, 3, 'FD');
-
-// // id
-// doc::withGraphicsState(() => {
-// doc.setFontSize(7);
-// doc.setTextColor(255, 255, 255);
-// doc.text(`${cardDesc.id || '???'}/1`, innerBorder.right(), (innerBorder.bottom() + outsideBorder.bottom()) / 2, { align: 'right', baseline: 'middle' });
-// });
-
-// // card image
-// const { img, scaledRect } = await this.getBackgroundImage(doc, cardDesc, innerBorder, assetsInfo);
-
-// doc::withGraphicsState(() => {
-// doc.rect(...innerBorder::xYWidthHeight(), null); // set clipping area
-// doc.internal.write('W n');
-// doc.addImage(img, "JPEG", ...scaledRect::xYWidthHeight());
-// });
-
-// // title bar
-// const TITLE_BAR_HEIGHT = 7;
-// const titleBar = innerBorder.insetBy(1);
-// titleBar.height = TITLE_BAR_HEIGHT;
-// doc::withGraphicsState(() => {
-// doc.setGState(new doc.GState({ opacity: 0.5 }));
-// doc.setFillColor(BOX_FILL_COLOR);
-// doc.setDrawColor(BOX_STROKE_COLOR);
-// doc.roundedRect(...titleBar::xYWidthHeight(), 1, 1, 'DF');
-// });
-
-// // card name
-// const cardName = this.getNameFromCard(cardDesc);
-// doc::withGraphicsState(() => {
-// doc.setFontSize(.6 * TITLE_BAR_HEIGHT::mmToPoint());
-// doc.setTextColor('#000000');
-// doc.text(cardName, ...titleBar.leftCenter().addX(2).toPair(), { align: 'left', baseline: 'middle' });
-// });
-// // doc.text(['hello world', 'this is a card'], ...titleBar.leftCenter().addX(2).toPair(), { align: 'left', baseline: 'middle' });
-
-// // cost
-// const cost = cardDesc.getCost();
-// const costs = Array.isArray(cost) ? cost : [cost];
-// let top = titleBar.bottom() + 1;
-// let right = titleBar.right();
-// const COIN_RADIUS = 4;
-// costs.forEach((cost, i) => {
-// const coinCenter = lively.pt(right - COIN_RADIUS, top + COIN_RADIUS + COIN_RADIUS * 2 * 0.9 * i);
-
-// doc::withGraphicsState(() => {
-// doc.setGState(new doc.GState({ opacity: 0.9 }));
-// doc.setFillColor('#b8942d');
-// doc.setDrawColor('#b8942d');
-// doc.ellipse(...coinCenter.toPair(), COIN_RADIUS, COIN_RADIUS, 'DF');
-// });
-
-// if (cost !== undefined) {
-// doc::withGraphicsState(() => {
-// doc.setFontSize(12);
-// doc.setTextColor('#000000');
-// doc.text('' + cost, ...coinCenter.toPair(), { align: 'center', baseline: 'middle' });
-// });
-// }
-// });
-
-// // rule box
-// const ruleBox = innerBorder.insetBy(1);
-// const height = innerBorder.height * .4;
-// ruleBox.y = ruleBox.bottom() - height;
-// ruleBox.height = height;
-// doc::withGraphicsState(() => {
-// doc.setGState(new doc.GState({ opacity: BOX_FILL_OPACITY }));
-// doc.setFillColor(BOX_FILL_COLOR);
-// doc.setDrawColor(BOX_STROKE_COLOR);
-// doc.roundedRect(...ruleBox::xYWidthHeight(), 1, 1, 'DF');
-// });
-
-// // rule text
-// const ubgTest = document.querySelector('#ubg-test');
-// if (ubgTest && false) {
-// lively.notify(244);
-// await new Promise((resolve, reject) => {
-// doc.html(ubgTest, {
-// callback: resolve,
-// x: ruleBox.x,
-// y: ruleBox.y
-// });
-// });
-// } else {}
-// // const ruleTextBox = ruleBox.insetBy(2);
-// // doc.setFontSize(9);
-// // doc.setTextColor('#000000');
-// // doc.text(currentVersion.text, ...ruleTextBox.topLeft().toPair(), { align: 'left', baseline: 'top', maxWidth: ruleTextBox.width });
-
-
-// // type & elements
-// doc::withGraphicsState(() => {
-// doc.setFontSize(7);
-// doc.setTextColor(255, 255, 255);
-// doc.text(`${currentVersion.type || ''} - ${currentVersion.elements || currentVersion.element || ''}`, ruleBox.left(), ruleBox.top() - .5, { align: 'justify', baseline: 'bottom' });
-// });
-
-// await this.renderRuleText(doc, cardDesc, outsideBorder, ruleBox, {
-// insetTextBy: 2
-// });
-
-// // tags
-// const tagsAnchor = ruleBox.topRight().subY(1);
-// await this.renderTags(doc, cardDesc, tagsAnchor, outsideBorder)
+ // black border
+ this.roundedRect(outsideBorder, 'black', 'transparent', '0', '0')
+
+ // innerBorder
+ const INNER_INSET = 3;
+ const innerBorder = outsideBorder.insetBy(INNER_INSET);
+
+ // id
+ this.renderId(cardDesc)
+ this.get('#id-version').style.color = 'white'
+
+ // card image
+ const filePath = this.filePathForBackgroundImage(cardDesc, assetsInfo);
+ const newBG = ;
+ this.content.append(newBG)
+
+ // title bar
+ const TITLE_BAR_HEIGHT = 7;
+ const titleBar = innerBorder.insetBy(1);
+ titleBar.height = TITLE_BAR_HEIGHT;
+ const TITLE_BAR_BORDER_WIDTH = 0.200025;
+ this.roundedRect(titleBar, this.colorWithOpacity(BOX_FILL_COLOR, .5), BOX_STROKE_COLOR, TITLE_BAR_BORDER_WIDTH, 1)
+
+ // card name
+ {
+ const pos = titleBar.leftCenter().addX(2);
+ const fontSize = .6 * titleBar.height::mmToPoint();
+
+ const cardName = this.getNameFromCard(cardDesc);
+ this.content.append({cardName})
+ }
+
+ // cost
+ const COIN_RADIUS = 4;
+ const coinPos = titleBar.bottomLeft().addY(1).addXY(COIN_RADIUS, COIN_RADIUS);
+ this.renderCost(doc, cardDesc, coinPos, COIN_RADIUS)
+
+ // type & elements
+ const typePos = coinPos.addY(COIN_RADIUS * 1.5)
+ await this.renderType(cardDesc, typePos, BOX_FILL_COLOR, BOX_FILL_OPACITY)
+
+ // rule box
+ const ruleBox = outsideBorder.copy()
+ const height = outsideBorder.height * .4;
+ ruleBox.y = ruleBox.bottom() - height;
+ ruleBox.height = height;
+ this.debugRect(ruleBox)
+ const ruleBoxInset = 1 + INNER_INSET;
+ const ruleTextInset = 2;
+ await this.renderRuleText(cardDesc, outsideBorder, ruleBox, {
+ insetBoxBy: ruleBoxInset,
+ insetTextBy: ruleTextInset,
+ innerStrokeColor: BOX_STROKE_COLOR,
+ innerFillColor: BOX_FILL_COLOR,
+ innerFillOpacity: BOX_FILL_OPACITY,
+ outerStrokeColor: 'transparent',
+ outerFillColor: 'transparent',
+ outerFillOpacity: 0,
+ });
+
+ // tags
+ const tagsAnchor = titleBar.bottomRight().addY(1);
+ await this.renderTags(cardDesc, tagsAnchor, outsideBorder)
}
async renderFullBleedStyle(doc, cardDesc, outsideBorder, assetsInfo) {
- // #CONTINUE
const type = cardDesc.getType();
const typeString = type && type.toLowerCase && type.toLowerCase() || '';
@@ -2344,8 +2154,8 @@ export class Cards extends Morph {
await this.renderMagicStyle(doc, cardDesc, outsideBorder, assetsInfo)
}
- this.renderIsBad(doc, cardDesc, outsideBorder)
- this.renderVersionIndicator(doc, cardDesc, outsideBorder)
+ this.renderIsBad(cardDesc, outsideBorder)
+ this.renderVersionIndicator(cardDesc, outsideBorder)
}
/*MD ### Rendering Card Types MD*/
@@ -2354,90 +2164,67 @@ export class Cards extends Morph {
const [BOX_FILL_COLOR, BOX_STROKE_COLOR, BOX_FILL_OPACITY] = this.colorsForCard(cardDesc);
// background card image
-// const { img, scaledRect } = await this.getBackgroundImage(doc, cardDesc, outsideBorder, assetsInfo);
-// this.withinCardBorder(doc, outsideBorder, () => {
-// doc.addImage(img, "JPEG", ...scaledRect::xYWidthHeight());
-// });
-
-// this.withinCardBorder(doc, outsideBorder, () => {
-// doc::withGraphicsState(() => {
-// doc.setGState(new doc.GState({ opacity: BOX_FILL_OPACITY }));
-// doc.setFillColor(BOX_FILL_COLOR);
-// doc.rect(...outsideBorder::xYWidthHeight(), 'F');
-// });
-// })
-
-// // spell circle
-// {
-// const CIRCLE_BORDER = -3;
-// const RADIUS = (outsideBorder.width - CIRCLE_BORDER) / 2;
-// const middle = outsideBorder.center().withY(outsideBorder.top() + CIRCLE_BORDER + RADIUS)
-
-// // console.log(doc.getLineWidth())
-// this.withinCardBorder(doc, outsideBorder, () => {
-// doc::withGraphicsState(() => {
-// doc.circle(...middle.toPair(), RADIUS, null);
-// doc.internal.write('W n');
-
-// doc.addImage(img, "JPEG", ...scaledRect::xYWidthHeight());
-
-// doc.setDrawColor(BOX_STROKE_COLOR);
-// doc.setLineWidth(2)
-// doc.circle(...middle.toPair(), RADIUS, 'D');
-// })
-// })
-// }
+ this.setBackgroundImage(cardDesc, assetsInfo)
-// // innerBorder
+ // spell circle
+ {
+ const CIRCLE_BORDER = -3;
+ const RADIUS = (outsideBorder.width - CIRCLE_BORDER) / 2;
+ const middle = outsideBorder.center().withY(outsideBorder.top() + CIRCLE_BORDER + RADIUS)
+ const strokeWidth = 2;
+ const svg = ;
+
+ this.content.insertAdjacentHTML('beforeend', svg.outerHTML)
+ }
+
+ // innerBorder
const innerBorder = outsideBorder.insetBy(3);
- // doc.setFillColor(120, 120, 120);
- // doc.roundedRect(...innerBorder::xYWidthHeight(), 3, 3, 'FD');
-// // title
-// const TITLE_BAR_HEIGHT = 7;
-// const COST_COIN_RADIUS = 4;
-// const COST_COIN_MARGIN = 2;
+ // title
+ const TITLE_BAR_HEIGHT = 7;
+ const COST_COIN_RADIUS = 4;
+ const COST_COIN_MARGIN = 2;
-// const titleBorder = innerBorder.insetBy(1);
-// titleBorder.height = TITLE_BAR_HEIGHT;
-
-// await this.renderTitleBarAndCost(doc, cardDesc, titleBorder, COST_COIN_RADIUS, COST_COIN_MARGIN)
-
-// // rule box
-// const ruleBox = outsideBorder.copy()
-// const height = outsideBorder.height * .3;
-// ruleBox.y = ruleBox.bottom() - height;
-// ruleBox.height = height;
-// // const ruleBox = innerBorder.insetBy(1);
-// // const height = innerBorder.height * .4;
-// // ruleBox.y = ruleBox.bottom() - height;
-// // ruleBox.height = height;
-// this.withinCardBorder(doc, outsideBorder, () => {
-// doc::withGraphicsState(() => {
-// doc.setGState(new doc.GState({ opacity: BOX_FILL_OPACITY }));
-// doc.setFillColor(BOX_FILL_COLOR);
-// // doc.rect(...ruleBox::xYWidthHeight(), 'F');
-// })
-// })
-
-// doc::withGraphicsState(() => {
-// doc.setLineWidth(1);
-// doc.setDrawColor(BOX_STROKE_COLOR);
-// doc.setLineDashPattern([2,1], 0);
-// // doc.line(ruleBox.left(), ruleBox.top(), ruleBox.right(), ruleBox.top());
-// });
-
-// // rule text
-// const ruleTextBox = await this.renderRuleText(doc, cardDesc, outsideBorder, ruleBox, {
-// insetTextBy: 2
-// });
-
-// // tags
-// const tagsAnchor = ruleTextBox.topRight();
-// await this.renderTags(doc, cardDesc, tagsAnchor, outsideBorder)
+ const titleBorder = innerBorder.insetBy(1);
+ titleBorder.height = TITLE_BAR_HEIGHT;
+
+ await this.renderTitleBarAndCost(doc, cardDesc, titleBorder, COST_COIN_RADIUS, COST_COIN_MARGIN)
+
+ // rule box
+ const ruleBox = outsideBorder.copy()
+ const height = outsideBorder.height * .4;
+ ruleBox.y = ruleBox.bottom() - height;
+ ruleBox.height = height;
+ this.debugRect(ruleBox)
+ // rule text
+ const RULE_BOX_INSET = 1;
+ const RULE_TEXT_INSET = 1;
+ await this.renderRuleText(cardDesc, outsideBorder, ruleBox, {
+ insetBoxBy: RULE_BOX_INSET,
+ insetTextBy: RULE_TEXT_INSET,
+ outerStrokeColor: 'transparent',
+ outerFillColor: 'transparent',
+ outerFillOpacity: 0,
+ });
+
+ // tags
+ const tagsAnchor = lively.pt(titleBorder.right(), titleBorder.bottom()).addXY(-RULE_TEXT_INSET, 1);
+ await this.renderTags(cardDesc, tagsAnchor, outsideBorder)
+
// id
- this.renderId(doc, cardDesc, outsideBorder, innerBorder)
+ this.renderId(cardDesc)
}
line(start, end, color, width) {
@@ -2484,15 +2271,17 @@ export class Cards extends Morph {
return `color-mix(in srgb, ${color} ${opacity * 100}%, transparent)`
}
+ setBackgroundImage(cardDesc, assetsInfo) {
+ const filePath = this.filePathForBackgroundImage(cardDesc, assetsInfo);
+ this.get('#bg').style.backgroundImage = `url(${filePath})`
+ }
+
// #important
async renderGadget(doc, cardDesc, outsideBorder, assetsInfo) {
const [BOX_FILL_COLOR, BOX_STROKE_COLOR, BOX_FILL_OPACITY] = this.colorsForCard(cardDesc);
// background card image
- {
- const filePath = this.filePathForBackgroundImage(cardDesc, assetsInfo);
- this.get('#bg').style.backgroundImage = `url(${filePath})`
- }
+ this.setBackgroundImage(cardDesc, assetsInfo)
// innerBorder
const innerBorder = outsideBorder.insetBy(3);
@@ -2507,15 +2296,17 @@ export class Cards extends Morph {
this.line(topBox.bottomLeft(), topBox.bottomRight(), BOX_STROKE_COLOR, 1)
}
-// // title
- const TITLE_BAR_HEIGHT = 7;
- const COST_COIN_RADIUS = 4;
- const COST_COIN_MARGIN = 2;
-
- const titleBorder = innerBorder.insetBy(1);
- titleBorder.height = TITLE_BAR_HEIGHT;
-
- await this.renderTitleBarAndCost(doc, cardDesc, titleBorder, COST_COIN_RADIUS, COST_COIN_MARGIN)
+ // title
+ {
+ const TITLE_BAR_HEIGHT = 7;
+ const COST_COIN_RADIUS = 4;
+ const COST_COIN_MARGIN = 2;
+
+ const titleBorder = innerBorder.insetBy(1);
+ titleBorder.height = TITLE_BAR_HEIGHT;
+
+ await this.renderTitleBarAndCost(doc, cardDesc, titleBorder, COST_COIN_RADIUS, COST_COIN_MARGIN)
+ }
// rule box border calc
const ruleBox = outsideBorder.copy()
@@ -2525,44 +2316,22 @@ export class Cards extends Morph {
this.debugRect(ruleBox)
// rule text
- const RULE_TEXT_INSET = 2;
- let effectiveRuleBox
- const ruleTextBox = await this.renderRuleText(doc, cardDesc, outsideBorder, ruleBox, {
+ const RULE_BOX_INSET = 1;
+ const RULE_TEXT_INSET = 1;
+ await this.renderRuleText(cardDesc, outsideBorder, ruleBox, {
+ insetBoxBy: RULE_BOX_INSET,
insetTextBy: RULE_TEXT_INSET,
- beforeRenderRules: (ruleTextBox, rulesElement) => {
- // rule box render
- const rulesHeight = window.getComputedStyle(rulesElement).getPropertyValue("height")
- const div =
- rulesElement.insertAdjacentElement('beforebegin', div);
-
- const line =
- rulesElement.insertAdjacentElement('beforebegin', line);
- }
+ outerStrokeColor: BOX_STROKE_COLOR,
+ outerFillColor: BOX_FILL_COLOR,
+ outerFillOpacity: BOX_FILL_OPACITY,
});
// tags
const tagsAnchor = lively.pt(topBox.right(), topBox.bottom()).addXY(-RULE_TEXT_INSET, 1);
- await this.renderTags(doc, cardDesc, tagsAnchor, outsideBorder)
+ await this.renderTags(cardDesc, tagsAnchor, outsideBorder)
// id
- this.renderId(doc, cardDesc, outsideBorder, innerBorder)
+ this.renderId(cardDesc)
}
// #important
@@ -2570,77 +2339,69 @@ background: ${BOX_STROKE_COLOR};
const [BOX_FILL_COLOR, BOX_STROKE_COLOR, BOX_FILL_OPACITY] = this.colorsForCard(cardDesc);
// background card image
-// const { img, scaledRect } = await this.getBackgroundImage(doc, cardDesc, outsideBorder, assetsInfo);
-// this.withinCardBorder(doc, outsideBorder, () => {
-// doc.addImage(img, "JPEG", ...scaledRect::xYWidthHeight());
-// });
-
-// // Zohar design
-// const ZOHAR_DESIGN_BORDER_WIDTH = .5;
-// [[outsideBorder.topLeft(), lively.pt(1, 0)], [outsideBorder.topRight(), lively.pt(-1, 0)]].forEach(([startingPt, direction]) => {
-// const dirX = direction.x;
-// this.withinCardBorder(doc, outsideBorder, () => {
-// doc::withGraphicsState(() => {
-// doc.setGState(new doc.GState({ opacity: 0.5 }));
-// doc.setFillColor(BOX_FILL_COLOR);
-// doc.setDrawColor(BOX_STROKE_COLOR);
-// doc.setLineWidth(ZOHAR_DESIGN_BORDER_WIDTH);
-// doc.lines([[dirX*8,0],[0,15],[-dirX*15,15],[dirX*15,15],[0,100], [-dirX*10,0]], ...startingPt.toPair(), [1,1], 'DF', true)
-// });
-// });
-// })
+ this.setBackgroundImage(cardDesc, assetsInfo)
+
+ // Zohar design
+ {
+ const ZOHAR_DESIGN_BORDER_WIDTH = .5;
+ [[outsideBorder.topLeft(), lively.pt(1, 0)], [outsideBorder.topRight(), lively.pt(-1, 0)]].forEach(([startingPt, direction]) => {
+ const dirX = direction.x;
+ startingPt = startingPt.subY(5)
+ const topMost = startingPt.addXY(dirX*8, 0);
+ const triangleTop = topMost.addXY(0, 15 + 5);
+ const triangleOuter = triangleTop.addXY(-dirX*15, 15);
+ const triangleBottom = triangleOuter.addXY(dirX*15, 15);
+ const bottom = triangleBottom.addXY(0, 100);
+ const bottomOuter = bottom.addXY(-dirX*10, 0);
+ const diamondPoints = `${startingPt.x} ${startingPt.y}, ${topMost.x} ${topMost.y}, ${triangleTop.x} ${triangleTop.y}, ${triangleOuter.x} ${triangleOuter.y}, ${triangleBottom.x} ${triangleBottom.y}, ${bottom.x} ${bottom.y}, ${bottomOuter.x} ${bottomOuter.y}`;
+
+ const svg = ;
+
+ this.content.insertAdjacentHTML('beforeend', svg.outerHTML)
+ })
+ }
// innerBorder
const innerBorder = outsideBorder.insetBy(3);
- // doc.setFillColor(120, 120, 120);
- // doc.roundedRect(...innerBorder::xYWidthHeight(), 3, 3, 'FD');
+ // this.roundedRect(innerBorder, 'steelblue', 'red', 3, 0)
-// // title
-// const TITLE_BAR_HEIGHT = 7;
-// const COST_COIN_RADIUS = 4;
-// const COST_COIN_MARGIN = 2;
+ // title
+ const TITLE_BAR_HEIGHT = 7;
+ const COST_COIN_RADIUS = 4;
+ const COST_COIN_MARGIN = 2;
-// const titleBorder = innerBorder.insetBy(1);
-// titleBorder.height = TITLE_BAR_HEIGHT;
-
-// await this.renderTitleBarAndCost(doc, cardDesc, titleBorder, COST_COIN_RADIUS, COST_COIN_MARGIN)
-
-// // rule box border calc
-// const ruleBox = outsideBorder.copy()
-// const height = outsideBorder.height * .4;
-// ruleBox.y = ruleBox.bottom() - height;
-// ruleBox.height = height;
+ const titleBorder = innerBorder.insetBy(1);
+ titleBorder.height = TITLE_BAR_HEIGHT;
-// // rule text
-// const RULE_TEXT_INSET = 2;
-// let effectiveRuleBox
-// const ruleTextBox = await this.renderRuleText(doc, cardDesc, outsideBorder, ruleBox, {
-// insetTextBy: RULE_TEXT_INSET,
-// beforeRenderRules: ruleTextBox => {
-// // rule box render
-// effectiveRuleBox = ruleTextBox.insetBy(-RULE_TEXT_INSET)
-// this.withinCardBorder(doc, outsideBorder, () => {
-// doc::withGraphicsState(() => {
-// doc.setGState(new doc.GState({ opacity: BOX_FILL_OPACITY }));
-// doc.setFillColor(BOX_FILL_COLOR);
-// doc.rect(...effectiveRuleBox::xYWidthHeight(), 'F');
-// })
-// })
-
-// doc::withGraphicsState(() => {
-// doc.setLineWidth(1);
-// doc.setDrawColor(BOX_STROKE_COLOR);
-// doc.line(effectiveRuleBox.left(), effectiveRuleBox.top(), effectiveRuleBox.right(), effectiveRuleBox.top());
-// });
-// }
-// });
+ await this.renderTitleBarAndCost(doc, cardDesc, titleBorder, COST_COIN_RADIUS, COST_COIN_MARGIN)
-// // tags
-// const tagsAnchor = lively.pt(ruleTextBox.right(), effectiveRuleBox.top()).subY(1);
-// await this.renderTags(doc, cardDesc, tagsAnchor, outsideBorder)
+ // rule box border calc
+ const ruleBox = outsideBorder.copy()
+ const height = outsideBorder.height * .4;
+ ruleBox.y = ruleBox.bottom() - height;
+ ruleBox.height = height;
+
+ // rule text
+ const RULE_BOX_INSET = 1;
+ const RULE_TEXT_INSET = 1;
+ await this.renderRuleText(cardDesc, outsideBorder, ruleBox, {
+ insetBoxBy: RULE_BOX_INSET,
+ insetTextBy: RULE_TEXT_INSET,
+ outerStrokeColor: BOX_STROKE_COLOR,
+ outerFillColor: BOX_FILL_COLOR,
+ outerFillOpacity: BOX_FILL_OPACITY,
+ });
+
+ // tags
+ const tagsAnchor = lively.pt(titleBorder.right(), titleBorder.bottom()).addXY(-RULE_TEXT_INSET, 1);
+ await this.renderTags(cardDesc, tagsAnchor, outsideBorder)
// id
- this.renderId(doc, cardDesc, outsideBorder, innerBorder)
+ this.renderId(cardDesc)
}
/*MD ### Rendering Card Components MD*/
@@ -2722,7 +2483,7 @@ font-family: "${CSS_FONT_FAMILY_CARD_NAME}";
// type
currentCenter = currentCenter.addY(costCoinRadius * .75)
const [BOX_FILL_COLOR, BOX_STROKE_COLOR, BOX_FILL_OPACITY] = this.colorsForCard(cardDesc);
- await this.renderType(doc, cardDesc, currentCenter, BOX_FILL_COLOR, BOX_FILL_OPACITY)
+ await this.renderType(cardDesc, currentCenter, BOX_FILL_COLOR, BOX_FILL_OPACITY)
}
async renderElementList(doc, cardDesc, pos, radius, direction) {
@@ -2811,8 +2572,8 @@ font-family: "${font}";
}
// #important
- async renderRuleText(doc, cardDesc, outsideBorder, ruleBox, options = { }) {
- return RuleTextRenderer.renderRuleText(this, cardDesc, doc, outsideBorder, ruleBox, options)
+ async renderRuleText(cardDesc, outsideBorder, ruleBox, options) {
+ return RuleTextRenderer.renderRuleText(this, cardDesc, outsideBorder, ruleBox, options)
}
debugPoint(pt, color = 'red') {
@@ -2833,7 +2594,7 @@ background: ${color};
}
// type
- async renderType(doc, cardDesc, anchorPt, color, opacity) {
+ async renderType(cardDesc, anchorPt, color, opacity) {
// function curate() {
// return this.toLower().upperFirst();
// }
@@ -2867,7 +2628,7 @@ background: ${color};
`}>{fullText});
}
- renderTags(doc, cardDesc, tagsAnchor, outsideBorder) {
+ renderTags(cardDesc, tagsAnchor, outsideBorder) {
const tags = cardDesc.getTags().sortBy(i => i, true).map(tag => #{tag}
);
const FONT_SIZE = 7;
@@ -2893,10 +2654,7 @@ font-family: ${CSS_FONT_FAMILY_UNIVERS_55};
this.content.insertAdjacentHTML('beforeend', yourSvgString)
}
- renderId(doc, cardDesc, outsideBorder, innerBorder, color = '000') {
- // doc.setFontSize(7);
- // doc.setTextColor(color);
- // doc.text(`${cardDesc.id || '???'}/${cardDesc.getHighestVersion()}`, innerBorder.right() - 2, (innerBorder.bottom() + outsideBorder.bottom()) / 2, { align: 'right', baseline: 'middle' });
+ renderId(cardDesc) {
this.get('#card-id').innerHTML = cardDesc.id || '???'
this.get('#card-version').innerHTML = cardDesc.getHighestVersion()
}
@@ -2905,7 +2663,7 @@ font-family: ${CSS_FONT_FAMILY_UNIVERS_55};
return this.get('#content');
}
- renderIsBad(doc, cardDesc, outsideBorder) {
+ renderIsBad(cardDesc, outsideBorder) {
const slash = (color, width=2, offset=lively.pt(0,0)) => {
const start = outsideBorder.topRight().addPt(offset);
const end = outsideBorder.bottomLeft().addPt(offset);
@@ -2929,7 +2687,7 @@ font-family: ${CSS_FONT_FAMILY_UNIVERS_55};
}
}
- renderVersionIndicator(doc, cardDesc, outsideBorder) {
+ renderVersionIndicator(cardDesc, outsideBorder) {
const VERSION_FILL = '#f7d359';
this.get('#version-indicator').style.setProperty("--version-fill", VERSION_FILL);
}
diff --git a/src/components/widgets/ubg-cards.html b/src/components/widgets/ubg-cards.html
index 327e6cac0..ecd71c9eb 100644
--- a/src/components/widgets/ubg-cards.html
+++ b/src/components/widgets/ubg-cards.html
@@ -147,6 +147,7 @@
+
diff --git a/src/components/widgets/ubg-cards.js b/src/components/widgets/ubg-cards.js
index 74b055d43..3e5e4191c 100644
--- a/src/components/widgets/ubg-cards.js
+++ b/src/components/widgets/ubg-cards.js
@@ -11,6 +11,7 @@ import 'https://lively-kernel.org/lively4/ubg-assets/load-assets.js';
import { serialize, deserialize } from 'src/client/serialize.js';
import Card from 'demos/stefan/untitled-board-game/ubg-card.js';
+import 'demos/stefan/untitled-board-game/ubg-cards-exporter.js';
import preloaWebComponents from 'src/client/preload-components.js'
await preloaWebComponents(['ubg-card'])
@@ -2024,6 +2025,7 @@ export default class Cards extends Morph {
/*MD ### BUILD MD*/
async buildCards(doc, cardsToPrint, skipCardBack) {
+ globalThis.doc = doc
const GAP = lively.pt(.2, .2);
const rowsPerPage = Math.max(((doc.internal.pageSize.getHeight() + GAP.y) / (POKER_CARD_SIZE_MM.y + GAP.y)).floor(), 1);
@@ -2279,6 +2281,7 @@ export default class Cards extends Morph {
ruleBox.y = ruleBox.bottom() - height;
ruleBox.height = height;
doc::withGraphicsState(() => {
+ doc.get
doc.setGState(new doc.GState({ opacity: BOX_FILL_OPACITY }));
doc.setFillColor(BOX_FILL_COLOR);
doc.setDrawColor(BOX_STROKE_COLOR);
@@ -3275,10 +3278,23 @@ export default class Cards extends Morph {
const cardsToPrint = this.filterCardsForPrinting(filteredEntries.map(entry => entry.card))
if (await this.checkForLargePrinting(cardsToPrint)) {
- await this.printForExport(cardsToPrint, evt.shiftKey);
+ await this.printForExport(cardsToPrint, evt.shiftKey, false);
}
}
+ async onPrintSelectedNew() {
+ if (!this.cards) {
+ return;
+ }
+
+ const filteredEntries = this.allEntries.filter(entry => entry.isVisible())
+ const cardsToPrint = this.filterCardsForPrinting(filteredEntries.map(entry => entry.card))
+
+ if (await this.checkForLargePrinting(cardsToPrint)) {
+ await this.printForExport(cardsToPrint, false, true);
+ }
+ }
+
async onPrintChanges(evt) {
if (!this.cards) {
return;
@@ -3287,7 +3303,7 @@ export default class Cards extends Morph {
const cardsToPrint = this.filterCardsForPrinting(this.cards.filter(card => !card.getIsPrinted()));
if (await this.checkForLargePrinting(cardsToPrint)) {
- await this.printForExport(cardsToPrint, evt.shiftKey);
+ await this.printForExport(cardsToPrint, evt.shiftKey, false);
}
}
@@ -3299,7 +3315,7 @@ export default class Cards extends Morph {
return true;
}
- async printForExport(cards, quickSavePDF) {
+ async printForExport(cards, quickSavePDF, useHTMLPrinting) {
if (cards.length === 0) {
lively.warn('no cards to print for export');
return;
@@ -3318,6 +3334,11 @@ export default class Cards extends Morph {
this.markAsChanged()
}
+ if (useHTMLPrinting) {
+ await globalThis.__ubg_html_to_pdf_exporter__.execute(cards, this)
+ return;
+ }
+
const doc = await this.buildFullPDF(cards);
if (quickSavePDF) {
this.quicksavePDF(doc);