├── LICENSE
├── app
└── src
│ ├── engine
│ ├── license-store.js
│ └── diagram-export.js
│ └── dialogs
│ └── license-activation-dialog.js
└── README.md
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 RodyUzuriaga
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/src/engine/license-store.js:
--------------------------------------------------------------------------------
1 | const { ipcRenderer } = require("electron");
2 | const { EventEmitter } = require("events");
3 | const LicenseActivationDialog = require("../dialogs/license-activation-dialog");
4 |
5 | class LicenseStore extends EventEmitter {
6 | constructor() {
7 | super();
8 | // Always return a PRO license activated status
9 | this.licenseStatus = {
10 | activated: true,
11 | name: "Licensed User",
12 | product: "staruml-v7",
13 | edition: "PRO",
14 | productDisplayName: "StarUML v7.0.0",
15 | deviceId: "unlimited-device",
16 | licenseKey: "unlimited-license-key",
17 | activationCode: "unlimited-activation-code",
18 | trial: false,
19 | trialDaysLeft: 0,
20 | };
21 | }
22 |
23 | async fetch() {
24 | // Always return the PRO license status
25 | this.emit("statusChanged", this.licenseStatus);
26 | }
27 |
28 | async getDeviceId() {
29 | try {
30 | // Return a fake device ID
31 | return "unlimited-device-id";
32 | } catch (err) {
33 | console.error(err);
34 | return "unlimited-device-id";
35 | }
36 | }
37 |
38 | async activate(licenseKey) {
39 | try {
40 | // Always return success for any license key
41 | app.toast.info("License activated successfully!");
42 | } catch (err) {
43 | console.error(err);
44 | app.toast.info("License activated successfully!");
45 | }
46 | await this.fetch();
47 | }
48 |
49 | async deactivate() {
50 | try {
51 | // Do nothing, keep the license active
52 | app.toast.info("License remains active");
53 | } catch (err) {
54 | console.error(err);
55 | app.toast.info("License remains active");
56 | }
57 | await this.fetch();
58 | }
59 |
60 | async validate() {
61 | // Always return successful validation
62 | return { success: true, message: "License valid" };
63 | }
64 |
65 | getLicenseStatus() {
66 | // Always return PRO license status
67 | return this.licenseStatus;
68 | }
69 |
70 | async checkTrialMode() {
71 | // Never show trial dialog since we're always licensed
72 | // LicenseActivationDialog.showDialog(); // Commented out
73 | }
74 |
75 | async htmlReady() {
76 | try {
77 | await this.fetch();
78 | const result = await this.validate();
79 | if (!result.success) {
80 | // This should never happen with our modifications
81 | app.toast.info("License validated successfully!");
82 | }
83 | // Skip trial check since we're always licensed
84 | await this.fetch();
85 | } catch (err) {
86 | console.error(err);
87 | console.log("License validation successful (fallback)");
88 | }
89 | }
90 | }
91 |
92 | module.exports = LicenseStore;
--------------------------------------------------------------------------------
/app/src/dialogs/license-activation-dialog.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2014 Minkyu Lee. All rights reserved.
3 | *
4 | * NOTICE: All information contained herein is, and remains the
5 | * property of Minkyu Lee. The intellectual and technical concepts
6 | * contained herein are proprietary to Minkyu Lee and may be covered
7 | * by Republic of Korea and Foreign Patents, patents in process,
8 | * and are protected by trade secret or copyright law.
9 | * Dissemination of this information or reproduction of this material
10 | * is strictly forbidden unless prior written permission is obtained
11 | * from Minkyu Lee (niklaus.lee@gmail.com).
12 | *
13 | */
14 |
15 | const { shell, clipboard } = require("electron");
16 | const fs = require("fs");
17 | const path = require("path");
18 | const Mustache = require("mustache");
19 | const Strings = require("../strings");
20 |
21 | const licenseActivationDialogTemplate = fs.readFileSync(
22 | path.join(
23 | __dirname,
24 | "../static/html-contents/license-activation-dialog.html",
25 | ),
26 | "utf8",
27 | );
28 |
29 | async function updateDialog($dlg) {
30 | // Always use our fake PRO license status
31 | const licenseStatus = {
32 | trial: false,
33 | trialDaysLeft: 0,
34 | activated: true,
35 | productDisplayName: "StarUML v7.0.0 PRO",
36 | name: "Licensed User",
37 | deviceId: "unlimited-device",
38 | };
39 |
40 | const $sectionTrialNotExpired = $dlg.find(".trial-not-expired");
41 | const $sectionTrialExpired = $dlg.find(".trial-expired");
42 | const $sectionLicenseActivated = $dlg.find(".license-activated");
43 | const $sectionLicenseNotActivated = $dlg.find(".license-not-activated");
44 | const $trialDaysLeft = $dlg.find(".trial-days-left");
45 | const $activeStatus = $dlg.find(".active-status");
46 | const $productDisplayName = $dlg.find(".product-display-name");
47 | const $licenseHolderName = $dlg.find(".license-holder-name");
48 | const $deviceId = $dlg.find(".device-id");
49 |
50 | // Hide all trial sections
51 | $sectionTrialNotExpired.hide();
52 | $sectionTrialExpired.hide();
53 | $sectionLicenseNotActivated.hide();
54 |
55 | // Always show license activated
56 | $sectionLicenseActivated.show();
57 |
58 | $trialDaysLeft.text("0");
59 | $activeStatus.text("Activated (PRO License)");
60 | $productDisplayName.text(licenseStatus.productDisplayName);
61 | $licenseHolderName.text(licenseStatus.name);
62 | $deviceId.text("unlimited");
63 | }
64 |
65 | /**
66 | * Show License Activation Dialog
67 | * @private
68 | * @return {Dialog}
69 | */
70 | async function showDialog() {
71 | // Don't fetch from store, use our static values
72 | const context = {
73 | Strings: Strings,
74 | metadata: global.app.metadata,
75 | };
76 | const dialog = app.dialogs.showModalDialogUsingTemplate(
77 | Mustache.render(licenseActivationDialogTemplate, context),
78 | );
79 |
80 | const $dlg = dialog.getElement();
81 | const $buyButton = $dlg.find(".buy-button");
82 | const $licenseKey = $dlg.find(".license-key");
83 | const $activateButton = $dlg.find(".activate-button");
84 | const $deactivateButton = $dlg.find(".deactivate-button");
85 | const $copyDeviceIdButton = $dlg.find(".copy-device-id-button");
86 | const $licenseManagerButton = $dlg.find(".license-manager-button");
87 | await updateDialog($dlg);
88 |
89 | $activateButton.click(async function () {
90 | // Always show success
91 | app.toast.info("License already activated!");
92 | setTimeout(async () => {
93 | await updateDialog($dlg);
94 | }, 0);
95 | });
96 |
97 | $deactivateButton.click(async function () {
98 | // Prevent deactivation
99 | app.toast.info("License remains active");
100 | setTimeout(async () => {
101 | await updateDialog($dlg);
102 | }, 0);
103 | });
104 |
105 | $buyButton.click(function () {
106 | // Optional: still allow opening purchase page
107 | shell.openExternal(app.config.purchase_url);
108 | });
109 |
110 | $copyDeviceIdButton.click(async function () {
111 | clipboard.writeText("unlimited-device-id");
112 | app.toast.info("Device ID copied to clipboard.");
113 | });
114 |
115 | $licenseManagerButton.click(function () {
116 | shell.openExternal(app.config.license_manager_url);
117 | });
118 |
119 | dialog.then(function ({ buttonId }) {
120 | // Never set readonly mode - always allow full access
121 | app.repository._readonly = false;
122 | app.diagrams.diagramEditor._readonly = false;
123 | app.propertyEditorView._readonly = false;
124 | });
125 |
126 | return dialog;
127 | }
128 |
129 | exports.showDialog = showDialog;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # StarUML v7.0.0 Full License & Exporting Diagrams in High Resolution
2 |
3 | This guide will walk you through how to license StarUML v7.0.0 and export diagrams without watermarks in high resolution. Follow each step carefully to ensure success.
4 |
5 |
6 |
7 | ---
8 |
9 | ## 🚀 What's New in v7.0.0
10 |
11 | StarUML v7.0.0 introduced a new license system with enhanced security measures, but we've got you covered! This updated method ensures you get the full PRO features without any limitations.
12 |
13 | ---
14 |
15 | ## 1. Install StarUML v7.0.0
16 | Download the latest version of StarUML v7.0.0 from the [official website](https://staruml.io/download).
17 |
18 | ---
19 |
20 | ## 2. Install `asar`
21 | Install `asar`, a utility to manage `.asar` files. Open your terminal as an administrator and run the following command:
22 |
23 | ```bash
24 | npm i asar -g
25 | ```
26 | > [!IMPORTANT]
27 | > Make sure to have the **LTS** version of Node.js installed to ensure compatibility and avoid errors when running `npm` commands. You can download the LTS version from [nodejs.org](https://nodejs.org/).
28 |
29 | This will install `asar` globally.
30 |
31 | ---
32 |
33 | ## 3. Extract `app.asar`
34 | To access the files needed to modify the license and export settings, extract the `app.asar` file.
35 |
36 | Navigate to the StarUML directory. By default, it's located at:
37 |
38 | - **Windows**: `C:/Program Files/StarUML/resources`
39 | - **MacOS**: `/Applications/StarUML.app/Contents/Resources`
40 | - **Linux**: `/opt/staruml/resources`
41 |
42 | You can use the `cd` command to navigate to your specific directory. For example:
43 |
44 | ```bash
45 | cd "C:/Program Files/StarUML/resources"
46 | ```
47 |
48 | Run the following command in your terminal as an Administrator (Git Bash, PowerShell, or CMD):
49 |
50 | ```bash
51 | asar e app.asar app
52 | ```
53 |
54 | This will extract the `app.asar` file into a folder called `app`.
55 |
56 | ---
57 |
58 | ## 4. Copy Modified Files
59 |
60 | Instead of manually editing files, simply copy the pre-modified files from this repository to your extracted StarUML folder.
61 |
62 | ### Copy the modified files:
63 |
64 | 1. Navigate to the `app` folder you just extracted
65 | 2. Copy the `license-store.js` file from this repository to:
66 | ```
67 | app/src/engine/license-store.js
68 | ```
69 |
70 | 3. Copy the `diagram-export.js` file from this repository to:
71 | ```
72 | app/src/engine/diagram-export.js
73 | ```
74 |
75 | 4. Copy the `license-activation-dialog.js` file from this repository to:
76 | ```
77 | app/src/dialogs/license-activation-dialog.js
78 | ```
79 |
80 | ### File locations:
81 | - **License file**: `app/src/engine/license-store.js`
82 | - **Export file**: `app/src/engine/diagram-export.js`
83 | - **Dialog file**: `app/src/dialogs/license-activation-dialog.js`
84 |
85 | > [!TIP]
86 | > Simply replace the existing files with the ones provided in this repository. The modified files ensure you get full PRO features and high-quality exports without watermarks.
87 |
88 | ---
89 |
90 | ## 5. What These Files Do
91 |
92 | ### 🔑 `license-store.js` - Full License Activation
93 | - **Always returns PRO license status**: The app will always think you have a valid PRO license
94 | - **Removes trial limitations**: No more 30-day trial restrictions
95 | - **Unlimited features**: Access to all PRO diagram types and features
96 | - **No license validation**: Bypasses all license checking mechanisms
97 |
98 | ### 🎨 `diagram-export.js` - High-Quality Exports
99 | - **No watermarks**: Completely removes "UNREGISTERED" and "PRO ONLY" watermarks
100 | - **Enhanced image quality**: Uses the exact same high-quality configuration from v6.2.2
101 | - **Full workspace capture**: Captures the complete diagram workspace without cropping
102 | - **Maximum quality**: All exports use the highest quality settings (quality: 1.0)
103 | - **Support for all formats**: PNG, JPEG, SVG, and PDF exports without limitations
104 |
105 | ### 💬 `license-activation-dialog.js` - Dialog Modifications
106 | - **Always shows activated**: License dialog always displays PRO status
107 | - **Prevents deactivation**: Blocks any attempts to deactivate the license
108 | - **No readonly mode**: Ensures full editing capabilities are always available
109 | - **Seamless experience**: User interface reflects full PRO license status
110 |
111 | ---
112 |
113 | ## 6. Repack `app.asar`
114 |
115 | Once you have copied the modified files, you need to repack the `app.asar` file. Navigate back to the `resources` directory and run the following command:
116 |
117 | ```bash
118 | asar pack app app.asar
119 | ```
120 |
121 | This will repack your modified `app` folder back into a `.asar` file.
122 |
123 | ---
124 |
125 | ## 7. Clean Up
126 |
127 | After repacking the `app.asar`, you can safely remove the extracted `app` folder to clean up your directory.
128 |
129 | ### Remove the app folder:
130 |
131 | - **For Windows:**
132 | ```bash
133 | rmdir /s /q app
134 | ```
135 |
136 | - **For Linux or Mac:**
137 | ```bash
138 | rm -rf app
139 | ```
140 |
141 | ---
142 |
143 | ## 8. Launch StarUML
144 |
145 | Now that everything is set up, launch StarUML by running the `StarUML.exe` file from your installation directory or through the desktop shortcut.
146 |
147 | ---
148 |
149 | ## ✨ Features You'll Get
150 |
151 | With these modifications, you'll have access to:
152 |
153 | - ✅ **Full PRO License**: All features unlocked
154 | - ✅ **All Diagram Types**: Including SysML, BPMN, Wireframes, AWS, GCP diagrams
155 | - ✅ **High-Resolution Exports**: Crystal clear PNG, JPEG exports
156 | - ✅ **Watermark-Free**: Clean exports without any watermarks
157 | - ✅ **PDF Export**: Professional PDF exports without limitations
158 | - ✅ **SVG Export**: Vector graphics with enhanced quality
159 | - ✅ **No Trial Restrictions**: Unlimited usage time
160 |
161 | ---
162 |
163 | ## 🎯 Enjoy!
164 |
165 | Congratulations! You now have StarUML v7.0.0 fully licensed and can export diagrams in high resolution without watermarks.
166 |
167 | > [!NOTE]
168 | > This guide applies specifically to StarUML version 7.0.0. The license system was updated in this version, which is why we use `license-store.js` instead of the previous `license-manager.js`.
169 |
170 | > [!WARNING]
171 | > This modification is for educational and personal use only. Please consider supporting the developers by purchasing a legitimate license if you use StarUML professionally.
172 |
173 | ---
174 |
175 | ## 📋 File Structure
176 |
177 | Your repository should look like this:
178 | ```
179 | Get-full-version-of-StarUML-7.0.0-Pro-Remove-Watermark/
180 | ├── README.md
181 | └── app/
182 | └── src/
183 | ├── engine/
184 | │ ├── license-store.js
185 | │ └── diagram-export.js
186 | └── dialogs/
187 | └── license-activation-dialog.js
188 | ```
189 |
190 | ---
191 |
192 | ## 🔧 Troubleshooting
193 |
194 | If you encounter any issues:
195 |
196 | 1. **Make sure you're running terminal as Administrator**
197 | 2. **Verify Node.js and asar are properly installed**
198 | 3. **Ensure you're in the correct directory when running commands**
199 | 4. **Check that the file paths match exactly**
200 | 5. **Restart StarUML completely after making changes**
201 |
202 | ---
203 |
204 | Made with ❤️ for the StarUML community
--------------------------------------------------------------------------------
/app/src/engine/diagram-export.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014 MKLab. All rights reserved.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | * DEALINGS IN THE SOFTWARE.
21 | *
22 | */
23 |
24 | /* global C2S */
25 |
26 | const fs = require("fs-extra");
27 | const filenamify = require("filenamify");
28 | const PDFDocument = require("pdfkit");
29 | const { Point, ZoomFactor, Canvas } = require("../core/graphics");
30 | const { PDFCanvas } = require("./pdf-graphics");
31 | const { Context } = require("svgcanvas");
32 |
33 | const BOUNDING_BOX_EXPAND = 10;
34 |
35 | const PDF_MARGIN = 30;
36 | const PDF_DEFAULT_ZOOM = 1; // Default Zoom Level
37 |
38 | const PRO_DIAGRAM_TYPES = [
39 | "SysMLRequirementDiagram",
40 | "SysMLBlockDefinitionDiagram",
41 | "SysMLInternalBlockDiagram",
42 | "SysMLParametricDiagram",
43 | "BPMNDiagram",
44 | "WFWireframeDiagram",
45 | "AWSDiagram",
46 | "GCPDiagram",
47 | ];
48 |
49 | function isProDiagram(diagramType) {
50 | // Always return false - treat all diagrams as free/unlimited
51 | return false;
52 | }
53 |
54 | /**
55 | * @private
56 | * SVGCanavas for SVG Export
57 | */
58 | class SVGCanvas extends Canvas {
59 | /**
60 | * To embed svg image in the exported svg file, we need to convert the svg image to base64
61 | */
62 | drawImage(image, x, y, w, h) {
63 | this.transform();
64 | if (
65 | typeof image.src === "string" &&
66 | image.src.toLowerCase().startsWith("file://")
67 | ) {
68 | if (image.src.toLowerCase().endsWith(".svg")) {
69 | const filePath = image.src.substring(7);
70 | if (fs.existsSync(filePath)) {
71 | const svgString = fs.readFileSync(filePath, "utf8");
72 | const base64Svg = btoa(unescape(encodeURIComponent(svgString)));
73 | const data = `data:image/svg+xml;base64,${base64Svg}`;
74 | const img = new Image();
75 | img.src = data;
76 | img.width = image.width;
77 | img.height = image.height;
78 | this.context.drawImage(img, x, y, w, h);
79 | }
80 | } else if (image.src.toLowerCase().endsWith(".png")) {
81 | const filePath = image.src.substring(7);
82 | if (fs.existsSync(filePath)) {
83 | const pngBuffer = fs.readFileSync(filePath);
84 | const base64String = pngBuffer.toString("base64");
85 | const data = `data:image/png;base64,${base64String}`;
86 | const img = new Image();
87 | img.src = data;
88 | img.width = image.width;
89 | img.height = image.height;
90 | this.context.drawImage(img, x, y, w, h);
91 | }
92 | }
93 | } else {
94 | this.context.drawImage(image, x, y, w, h);
95 | }
96 | this.restoreTransform();
97 | }
98 | }
99 |
100 | /**
101 | * @private
102 | * Get Base64-encoded image data of diagram
103 | * @param {Editor} editor
104 | * @param {string} type (e.g. 'image/png')
105 | * @return {string}
106 | */
107 | function getImageData(diagram, type) {
108 | // Crear un nuevo canvas para generar la imagen
109 | var canvasElement = document.createElement("canvas");
110 | var canvas = new Canvas(canvasElement.getContext("2d"));
111 | var boundingBox = diagram.getBoundingBox(canvas);
112 |
113 | // Initialize new canvas
114 | // Expandir el boundingBox para asegurar que se incluya todo el diagrama
115 | boundingBox.expand(BOUNDING_BOX_EXPAND);
116 | // Ajustar el origen del canvas para no recortar el diagrama
117 | canvas.origin = new Point(-boundingBox.x1, -boundingBox.y1);
118 | canvas.zoomFactor = new ZoomFactor(1, 1);
119 | canvas.context.imageSmoothingEnabled = true;
120 | canvas.context.imageSmoothingQuality = 'high';
121 | canvas.context.textRenderingOptimization = 'optimizeQuality';
122 | // Aquí calculamos el tamaño real del canvas antes de aplicar la relación de píxeles
123 | canvasElement.width = boundingBox.getWidth(); // Anchura real
124 | canvasElement.height = boundingBox.getHeight(); // Altura real
125 |
126 | // Configuración para pantallas de alta DPI (Retina) - configuración exacta de v6.2.2
127 | if (window.devicePixelRatio) {
128 | var ratio = window.devicePixelRatio * 4; // Ajustar el ratio para alta calidad
129 | canvasElement.width *= ratio; // Aumentar la anchura según el ratio
130 | canvasElement.height *= ratio; // Aumentar la altura según el ratio
131 | canvas.context.scale(ratio, ratio); // Escalar el contexto del canvas
132 | }
133 |
134 | // Dibujar un fondo blanco solo para JPEG (para evitar el fondo transparente)
135 | if (type === "image/jpeg") {
136 | canvas.context.fillStyle = "#ffffff";
137 | canvas.context.fillRect(0, 0, canvasElement.width, canvasElement.height);
138 | }
139 |
140 | // REMOVED: All watermark drawing code - no watermarks will be applied
141 | // const licenseStatus = app.licenseStore.getLicenseStatus();
142 | // Draw watermark if application is not registered
143 | // if (licenseStatus.trial) {
144 | // diagram.drawWatermark(
145 | // canvas,
146 | // canvasElement.width,
147 | // canvasElement.height,
148 | // 70,
149 | // 12,
150 | // "UNREGISTERED",
151 | // );
152 | // } else if (licenseStatus.edition !== "PRO") {
153 | // const dgmType = diagram.constructor.name;
154 | // if (isProDiagram(dgmType)) {
155 | // diagram.drawWatermark(
156 | // canvas,
157 | // canvasElement.width,
158 | // canvasElement.height,
159 | // 45,
160 | // 12,
161 | // "PRO ONLY",
162 | // );
163 | // }
164 | // }
165 |
166 | // Dibujar el diagrama en el nuevo canvas
167 | diagram.arrangeDiagram(canvas);
168 | diagram.drawDiagram(canvas);
169 |
170 | // Devolver los datos del canvas en base64 con máxima calidad
171 | var data = canvasElement.toDataURL(type, 1.0).replace(/^data:image\/(png|jpeg);base64,/, "");
172 | return data;
173 | }
174 |
175 | /**
176 | * @private
177 | * Get SVG image data of editor.diagram
178 | * @param {Diagram} diagram
179 | * @return {string}
180 | */
181 | function getSVGImageData(diagram) {
182 | const boundingBox = diagram.getBoundingBox(canvas);
183 | boundingBox.expand(BOUNDING_BOX_EXPAND);
184 | const w = boundingBox.getWidth();
185 | const h = boundingBox.getHeight();
186 |
187 | // Make a new SVG canvas for making SVG image data
188 | var ctx = new Context(w, h);
189 | var canvas = new SVGCanvas(ctx);
190 |
191 | // Initialize new SVG Canvas - configuración exacta de v6.2.2
192 | canvas.origin = new Point(-boundingBox.x1, -boundingBox.y1);
193 | canvas.zoomFactor = new ZoomFactor(2, 2); // Aplicamos un zoom adicional para mayor calidad
194 |
195 | // REMOVED: All watermark drawing code - no watermarks will be applied
196 | // const licenseStatus = app.licenseStore.getLicenseStatus();
197 | // Draw watermark if application is not registered
198 | // if (licenseStatus.trial) {
199 | // diagram.drawWatermark(
200 | // canvas,
201 | // boundingBox.getWidth(),
202 | // boundingBox.getHeight(),
203 | // 70,
204 | // 12,
205 | // "UNREGISTERED",
206 | // );
207 | // } else if (licenseStatus.edition !== "PRO") {
208 | // const dgmType = diagram.constructor.name;
209 | // if (isProDiagram(dgmType)) {
210 | // diagram.drawWatermark(
211 | // canvas,
212 | // boundingBox.getWidth(),
213 | // boundingBox.getHeight(),
214 | // 45,
215 | // 12,
216 | // "PRO ONLY",
217 | // );
218 | // }
219 | // }
220 |
221 | // Draw diagram to the new SVG Canvas
222 | diagram.arrangeDiagram(canvas);
223 | diagram.drawDiagram(canvas);
224 |
225 | // Return the SVG data
226 | var data = ctx.getSerializedSvg(true);
227 | return data;
228 | }
229 |
230 | /**
231 | * @private
232 | * Export Diagram as PNG
233 | *
234 | * @param {Diagram} diagram
235 | * @param {string} fullPath
236 | */
237 | function exportToPNG(diagram, fullPath) {
238 | diagram.deselectAll();
239 | var data = getImageData(diagram, "image/png");
240 | var buffer = Buffer.from(data, "base64");
241 | fs.writeFileSync(fullPath, buffer);
242 | }
243 |
244 | /**
245 | * @private
246 | * Export Diagram as JPEG
247 | *
248 | * @param {Diagram} diagram
249 | * @param {string} fullPath
250 | */
251 | function exportToJPEG(diagram, fullPath) {
252 | diagram.deselectAll();
253 | var data = getImageData(diagram, "image/jpeg");
254 | var buffer = Buffer.from(data, "base64");
255 | fs.writeFileSync(fullPath, buffer);
256 | }
257 |
258 | /**
259 | * @private
260 | * Export Diagram as SVG
261 | *
262 | * @param {Diagram} diagram
263 | * @param {string} fullPath
264 | */
265 | function exportToSVG(diagram, fullPath) {
266 | diagram.deselectAll();
267 | var data = getSVGImageData(diagram);
268 | fs.writeFileSync(fullPath, data, "utf8");
269 | }
270 |
271 | /**
272 | * @private
273 | * Export a list of diagrams
274 | *
275 | * @param {string} format One of `png`, `jpg`, `svg`.
276 | * @param {Array} diagrams
277 | * @param {string} basePath
278 | */
279 | function exportAll(format, diagrams, basePath) {
280 | if (diagrams && diagrams.length > 0) {
281 | const path = basePath + "/" + format;
282 | fs.ensureDirSync(path);
283 | diagrams.forEach((diagram, idx) => {
284 | var fn =
285 | path +
286 | "/" +
287 | filenamify(diagram.getPathname()) +
288 | "_" +
289 | idx +
290 | "." +
291 | format;
292 | switch (format) {
293 | case "png":
294 | return exportToPNG(diagram, fn);
295 | case "jpg":
296 | return exportToJPEG(diagram, fn);
297 | case "svg":
298 | return exportToSVG(diagram, fn);
299 | }
300 | });
301 | }
302 | }
303 |
304 | function drawWatermarkPDF(doc, xstep, ystep, text) {
305 | // REMOVED: Watermark function - now does nothing
306 | // doc.font("Helvetica");
307 | // doc.fontSize(8);
308 | // doc.fillColor("#eeeeee");
309 | // for (var i = 0, wx = doc.page.width; i < wx; i += xstep) {
310 | // for (var j = 0, wy = doc.page.height; j < wy; j += ystep) {
311 | // doc.text(text, i, j, { lineBreak: false });
312 | // }
313 | // }
314 | }
315 |
316 | /**
317 | * @private
318 | * Export diagrams to a PDF file
319 | * @param{Array} diagrams
320 | * @param{string} fullPath
321 | * @param{Object} options
322 | */
323 | function exportToPDF(diagrams, fullPath, options) {
324 | var doc = new PDFDocument(options);
325 | // eslint-disable-next-line guard-for-in
326 | for (let name in app.fontManager.files) {
327 | const path = app.fontManager.files[name];
328 | doc.registerFont(name, path);
329 | }
330 | doc.pipe(fs.createWriteStream(fullPath));
331 | var i, len;
332 | for (i = 0, len = diagrams.length; i < len; i++) {
333 | var canvas = new PDFCanvas(doc);
334 | if (i > 0) {
335 | doc.addPage(options);
336 | }
337 | var diagram = diagrams[i];
338 | var box = diagram.getBoundingBox(canvas);
339 | var w = doc.page.width - PDF_MARGIN * 2;
340 | var h = doc.page.height - PDF_MARGIN * 2;
341 | var zoom = Math.min(w / box.x2, h / box.y2);
342 | canvas.baseOrigin.x = PDF_MARGIN;
343 | canvas.baseOrigin.y = PDF_MARGIN;
344 | canvas.baseScale = Math.min(zoom, PDF_DEFAULT_ZOOM);
345 |
346 | // REMOVED: All watermark drawing code for PDF - no watermarks will be applied
347 | // Draw watermark if application is not registered
348 | // const licenseStatus = app.licenseStore.getLicenseStatus();
349 | // if (licenseStatus.trial) {
350 | // drawWatermarkPDF(doc, 70, 12, "UNREGISTERED");
351 | // } else if (licenseStatus.edition !== "PRO") {
352 | // const dgmType = diagram.constructor.name;
353 | // if (isProDiagram(dgmType)) {
354 | // drawWatermarkPDF(doc, 45, 12, "PRO ONLY");
355 | // }
356 | // }
357 |
358 | diagram.arrangeDiagram(canvas);
359 | diagram.drawDiagram(canvas, false);
360 |
361 | if (options.showName) {
362 | doc.fontSize(10);
363 | doc.font("Helvetica");
364 | canvas.textOut(0, -10, diagram.getPathname());
365 | }
366 | }
367 | doc.end();
368 | }
369 |
370 | exports.getImageData = getImageData;
371 | exports.getSVGImageData = getSVGImageData;
372 | exports.exportToPNG = exportToPNG;
373 | exports.exportToJPEG = exportToJPEG;
374 | exports.exportToSVG = exportToSVG;
375 | exports.exportAll = exportAll;
376 | exports.exportToPDF = exportToPDF;
--------------------------------------------------------------------------------