abstract-image 13.0.13 → 13.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dynamic-image/dynamic-image.d.ts +4 -3
- package/lib/dynamic-image/dynamic-image.d.ts.map +1 -1
- package/lib/dynamic-image/dynamic-image.js +7 -6
- package/lib/dynamic-image/dynamic-image.js.map +1 -1
- package/lib/exporters/dxf2d-export-image.d.ts +3 -3
- package/lib/exporters/dxf2d-export-image.d.ts.map +1 -1
- package/lib/exporters/dxf2d-export-image.js +48 -22
- package/lib/exporters/dxf2d-export-image.js.map +1 -1
- package/lib/exporters/react-svg-export-image.d.ts +6 -1
- package/lib/exporters/react-svg-export-image.d.ts.map +1 -1
- package/lib/exporters/react-svg-export-image.js +10 -7
- package/lib/exporters/react-svg-export-image.js.map +1 -1
- package/lib/exporters/svg-export-image.d.ts +8 -1
- package/lib/exporters/svg-export-image.d.ts.map +1 -1
- package/lib/exporters/svg-export-image.js +15 -9
- package/lib/exporters/svg-export-image.js.map +1 -1
- package/package.json +3 -3
- package/src/dynamic-image/dynamic-image.ts +10 -5
- package/src/exporters/dxf2d-export-image.ts +185 -76
- package/src/exporters/react-svg-export-image.tsx +22 -6
- package/src/exporters/svg-export-image.ts +23 -9
|
@@ -53,14 +53,14 @@ export const DXF_ENTITIES: string[] = [
|
|
|
53
53
|
"VERTEX",
|
|
54
54
|
"VIEWPORT",
|
|
55
55
|
"WIPEOUT",
|
|
56
|
-
"XLINE"
|
|
56
|
+
"XLINE",
|
|
57
57
|
];
|
|
58
58
|
|
|
59
59
|
export type DxfOptions = {
|
|
60
60
|
readonly imageDataByUrl: Record<string, `${typeof DXF_DATA_URL}${string}`>;
|
|
61
|
-
readonly fillPolygons
|
|
62
|
-
readonly useStrokeThickness
|
|
63
|
-
readonly useColor
|
|
61
|
+
readonly fillPolygons: boolean;
|
|
62
|
+
readonly useStrokeThickness: boolean;
|
|
63
|
+
readonly useColor: boolean;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
export type DxfSpace = "*Model_Space" | "*Paper_Space";
|
|
@@ -96,7 +96,7 @@ export function dxf2dExportImage(root: AbstractImage, options?: Optional<DxfOpti
|
|
|
96
96
|
const modelSpaceHandle = newHandle();
|
|
97
97
|
const paperSpaceHandle = newHandle();
|
|
98
98
|
|
|
99
|
-
const opts:
|
|
99
|
+
const opts: DxfOptions = {
|
|
100
100
|
imageDataByUrl: options?.imageDataByUrl ?? {},
|
|
101
101
|
fillPolygons: options?.fillPolygons ?? false,
|
|
102
102
|
useColor: options?.useColor ?? false,
|
|
@@ -112,7 +112,15 @@ export function dxf2dExportImage(root: AbstractImage, options?: Optional<DxfOpti
|
|
|
112
112
|
blocks += createSpaceBlock("*Model_Space", modelSpaceHandle, newHandle);
|
|
113
113
|
blocks += createSpaceBlock("*Paper_Space", paperSpaceHandle, newHandle);
|
|
114
114
|
for (const component of root.components) {
|
|
115
|
-
const [newEntities, newBlocks, newBlockRecords] = componentDxf(
|
|
115
|
+
const [newEntities, newBlocks, newBlockRecords] = componentDxf(
|
|
116
|
+
component,
|
|
117
|
+
layer,
|
|
118
|
+
root.size,
|
|
119
|
+
modelSpaceHandle,
|
|
120
|
+
externalCache,
|
|
121
|
+
opts,
|
|
122
|
+
newHandle
|
|
123
|
+
);
|
|
116
124
|
entities += newEntities;
|
|
117
125
|
blocks += newBlocks;
|
|
118
126
|
blockRecords.push(...newBlockRecords);
|
|
@@ -165,14 +173,30 @@ export function dxf2dExportImage(root: AbstractImage, options?: Optional<DxfOpti
|
|
|
165
173
|
return header + dxf;
|
|
166
174
|
}
|
|
167
175
|
|
|
168
|
-
function componentDxf(
|
|
176
|
+
function componentDxf(
|
|
177
|
+
c: Component,
|
|
178
|
+
layer: number,
|
|
179
|
+
size: Size,
|
|
180
|
+
modelSpaceHandle: string,
|
|
181
|
+
externalCache: Map<string, DxfInsert>,
|
|
182
|
+
options: Required<DxfOptions>,
|
|
183
|
+
newHandle: () => string
|
|
184
|
+
): readonly [string, string, ReadonlyArray<BlockRecord>] {
|
|
169
185
|
let entities = "";
|
|
170
186
|
let blocks = "";
|
|
171
187
|
let blockRecords: Array<BlockRecord> = [];
|
|
172
188
|
|
|
173
189
|
if (c.type === "group") {
|
|
174
190
|
for (const child of c.children) {
|
|
175
|
-
const [newEntities, newBlocks, newBlockRecords] = componentDxf(
|
|
191
|
+
const [newEntities, newBlocks, newBlockRecords] = componentDxf(
|
|
192
|
+
child,
|
|
193
|
+
layer,
|
|
194
|
+
size,
|
|
195
|
+
modelSpaceHandle,
|
|
196
|
+
externalCache,
|
|
197
|
+
options,
|
|
198
|
+
newHandle
|
|
199
|
+
);
|
|
176
200
|
entities += newEntities;
|
|
177
201
|
blocks += newBlocks;
|
|
178
202
|
blockRecords.push(...newBlockRecords);
|
|
@@ -193,7 +217,10 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
193
217
|
if (!dxfStringRaw) {
|
|
194
218
|
return [entities, blocks, blockRecords];
|
|
195
219
|
}
|
|
196
|
-
const dxfString = dxfStringRaw
|
|
220
|
+
const dxfString = dxfStringRaw
|
|
221
|
+
.split("\n")
|
|
222
|
+
.map((v) => v.trim())
|
|
223
|
+
.join("\n");
|
|
197
224
|
|
|
198
225
|
const version = extractStandard(dxfString);
|
|
199
226
|
if (version !== DXF_STANDARD) {
|
|
@@ -216,7 +243,9 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
216
243
|
const externalBlockRecords = extractBlockRecords(dxfString);
|
|
217
244
|
|
|
218
245
|
const newBlockRecordHandle = newHandle();
|
|
219
|
-
const newName = `EMBEDED_IMAGE_${randomID()}_${scale.x.toPrecision(4).replace(".", "_")}X${scale.y
|
|
246
|
+
const newName = `EMBEDED_IMAGE_${randomID()}_${scale.x.toPrecision(4).replace(".", "_")}X${scale.y
|
|
247
|
+
.toPrecision(4)
|
|
248
|
+
.replace(".", "_")}`;
|
|
220
249
|
|
|
221
250
|
const initOldHandlesMap = new Map<string, string>();
|
|
222
251
|
|
|
@@ -225,7 +254,7 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
225
254
|
initOldHandlesMap.set(br.id, newBlockRecordHandle);
|
|
226
255
|
} else if (br.name === "*Paper_Space") {
|
|
227
256
|
initOldHandlesMap.set(br.id, newBlockRecordHandle);
|
|
228
|
-
} else if(!initOldHandlesMap.has(br.id)) {
|
|
257
|
+
} else if (!initOldHandlesMap.has(br.id)) {
|
|
229
258
|
const newId = newHandle();
|
|
230
259
|
initOldHandlesMap.set(br.id, newId);
|
|
231
260
|
blockRecords.push({ name: br.name, id: newId });
|
|
@@ -249,7 +278,7 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
249
278
|
let blockRecordName = newName;
|
|
250
279
|
let blockRecordId = "0";
|
|
251
280
|
const existingBlockRecord = blockRecords.find((v) => v.name.localeCompare(newName) === 0);
|
|
252
|
-
if(existingBlockRecord !== undefined) {
|
|
281
|
+
if (existingBlockRecord !== undefined) {
|
|
253
282
|
blockRecordName = existingBlockRecord.name;
|
|
254
283
|
blockRecordId = existingBlockRecord.id;
|
|
255
284
|
} else {
|
|
@@ -262,23 +291,35 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
262
291
|
|
|
263
292
|
const newBlock =
|
|
264
293
|
"0\nBLOCK\n" +
|
|
265
|
-
"5\n" +
|
|
266
|
-
|
|
294
|
+
"5\n" +
|
|
295
|
+
newHandle() +
|
|
296
|
+
"\n" +
|
|
297
|
+
"330\n" +
|
|
298
|
+
blockRecordId +
|
|
299
|
+
"\n" +
|
|
267
300
|
"100\nAcDbEntity\n" +
|
|
268
301
|
"8\n0\n" +
|
|
269
302
|
"100\nAcDbBlockBegin\n" +
|
|
270
|
-
"2\n" +
|
|
303
|
+
"2\n" +
|
|
304
|
+
blockRecordName +
|
|
305
|
+
"\n" +
|
|
271
306
|
"70\n0\n" +
|
|
272
307
|
"10\n0\n" +
|
|
273
|
-
"20\n0\n" +
|
|
308
|
+
"20\n0\n" +
|
|
274
309
|
"30\n0\n" +
|
|
275
|
-
"3\n" +
|
|
310
|
+
"3\n" +
|
|
311
|
+
blockRecordName +
|
|
312
|
+
"\n" +
|
|
276
313
|
"1\n\n" +
|
|
277
314
|
newEntities +
|
|
278
315
|
"\n" +
|
|
279
316
|
"0\nENDBLK\n" +
|
|
280
|
-
"5\n" +
|
|
281
|
-
|
|
317
|
+
"5\n" +
|
|
318
|
+
newHandle() +
|
|
319
|
+
"\n" +
|
|
320
|
+
"330\n" +
|
|
321
|
+
blockRecordId +
|
|
322
|
+
"\n" +
|
|
282
323
|
"100\nAcDbEntity\n" +
|
|
283
324
|
"8\n0\n" +
|
|
284
325
|
"100\nAcDbBlockEnd\n";
|
|
@@ -289,7 +330,7 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
289
330
|
const insert: DxfInsert = {
|
|
290
331
|
blockRecordId: blockRecordId,
|
|
291
332
|
name: blockRecordName,
|
|
292
|
-
extents
|
|
333
|
+
extents,
|
|
293
334
|
};
|
|
294
335
|
externalCache.set(cachKey, insert);
|
|
295
336
|
entities += createExternalInsert(insert, c, size, modelSpaceHandle, newHandle);
|
|
@@ -305,7 +346,7 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
305
346
|
entities += "100\nAcDbEntity\n";
|
|
306
347
|
entities += "8\n" + layer + "\n";
|
|
307
348
|
|
|
308
|
-
if(options.useColor && !isBlack(c.strokeColor)) {
|
|
349
|
+
if (options.useColor && !isBlack(c.strokeColor)) {
|
|
309
350
|
entities += "60\n0\n";
|
|
310
351
|
entities += "62\n256\n";
|
|
311
352
|
entities += "420\n" + colorToInteger(c.strokeColor) + "\n";
|
|
@@ -315,12 +356,15 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
315
356
|
entities += "10\n0\n20\n0\n30\n0\n";
|
|
316
357
|
entities += "70\n0\n";
|
|
317
358
|
|
|
318
|
-
if(options.useStrokeThickness) {
|
|
359
|
+
if (options.useStrokeThickness) {
|
|
319
360
|
entities += "40\n" + (c.strokeThickness ?? 0) + "\n";
|
|
320
361
|
entities += "41\n" + (c.strokeThickness ?? 0) + "\n";
|
|
321
362
|
}
|
|
322
363
|
|
|
323
|
-
const points: ReadonlyArray<Point> = [
|
|
364
|
+
const points: ReadonlyArray<Point> = [
|
|
365
|
+
{ x: c.start.x, y: invert(c.start.y, size.height) },
|
|
366
|
+
{ x: c.end.x, y: invert(c.end.y, size.height) },
|
|
367
|
+
];
|
|
324
368
|
for (const point of points) {
|
|
325
369
|
entities += "0\nVERTEX\n";
|
|
326
370
|
entities += "5\n" + newHandle() + "\n";
|
|
@@ -351,7 +395,7 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
351
395
|
entities += "100\nAcDbEntity\n";
|
|
352
396
|
entities += "8\n" + layer + "\n";
|
|
353
397
|
|
|
354
|
-
if(options.useColor && !isBlack(c.strokeColor)) {
|
|
398
|
+
if (options.useColor && !isBlack(c.strokeColor)) {
|
|
355
399
|
entities += "60\n0\n";
|
|
356
400
|
entities += "62\n256\n";
|
|
357
401
|
entities += "420\n" + colorToInteger(c.strokeColor) + "\n";
|
|
@@ -361,7 +405,7 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
361
405
|
entities += "10\n0\n20\n0\n30\n0\n";
|
|
362
406
|
entities += "70\n0\n";
|
|
363
407
|
|
|
364
|
-
if(options.useStrokeThickness) {
|
|
408
|
+
if (options.useStrokeThickness) {
|
|
365
409
|
entities += "40\n" + (c.strokeThickness ?? 0) + "\n";
|
|
366
410
|
entities += "41\n" + (c.strokeThickness ?? 0) + "\n";
|
|
367
411
|
}
|
|
@@ -399,7 +443,7 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
399
443
|
entities += "100\nAcDbEntity\n";
|
|
400
444
|
entities += "8\nText\n";
|
|
401
445
|
|
|
402
|
-
if(options.useColor && !isBlack(c.textColor)) {
|
|
446
|
+
if (options.useColor && !isBlack(c.textColor)) {
|
|
403
447
|
entities += "60\n0\n";
|
|
404
448
|
entities += "62\n256\n";
|
|
405
449
|
entities += "420\n" + colorToInteger(c.textColor) + "\n";
|
|
@@ -417,7 +461,7 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
417
461
|
entities += "71\n0\n";
|
|
418
462
|
entities += "72\n" + horizontalAlignment.toString() + "\n";
|
|
419
463
|
|
|
420
|
-
if(horizontalAlignment === 0 && verticalAlignment === 0) {
|
|
464
|
+
if (horizontalAlignment === 0 && verticalAlignment === 0) {
|
|
421
465
|
entities += "100\nAcDbText\n";
|
|
422
466
|
entities += "73\n0\n";
|
|
423
467
|
} else {
|
|
@@ -441,21 +485,51 @@ function componentDxf(c: Component, layer: number, size: Size, modelSpaceHandle:
|
|
|
441
485
|
const t = (2 * Math.PI * i) / numPoints;
|
|
442
486
|
const x = c.topLeft.x + r1 + r1 * Math.cos(t);
|
|
443
487
|
const y = c.topLeft.y + r2 + r2 * Math.sin(t);
|
|
444
|
-
points.push({x, y});
|
|
488
|
+
points.push({ x, y });
|
|
445
489
|
}
|
|
446
490
|
|
|
447
|
-
entities += createPolygon(
|
|
491
|
+
entities += createPolygon(
|
|
492
|
+
modelSpaceHandle,
|
|
493
|
+
layer.toString(),
|
|
494
|
+
points,
|
|
495
|
+
c.strokeColor,
|
|
496
|
+
c.fillColor,
|
|
497
|
+
c.strokeThickness,
|
|
498
|
+
size.height,
|
|
499
|
+
options,
|
|
500
|
+
newHandle
|
|
501
|
+
);
|
|
448
502
|
return [entities, blocks, blockRecords];
|
|
449
503
|
}
|
|
450
504
|
|
|
451
505
|
if (c.type === "polygon") {
|
|
452
|
-
entities += createPolygon(
|
|
506
|
+
entities += createPolygon(
|
|
507
|
+
modelSpaceHandle,
|
|
508
|
+
layer.toString(),
|
|
509
|
+
c.points,
|
|
510
|
+
c.strokeColor,
|
|
511
|
+
c.fillColor,
|
|
512
|
+
c.strokeThickness,
|
|
513
|
+
size.height,
|
|
514
|
+
options,
|
|
515
|
+
newHandle
|
|
516
|
+
);
|
|
453
517
|
return [entities, blocks, blockRecords];
|
|
454
518
|
}
|
|
455
519
|
|
|
456
520
|
if (c.type === "rectangle") {
|
|
457
521
|
const cors = corners(c);
|
|
458
|
-
entities += createPolygon(
|
|
522
|
+
entities += createPolygon(
|
|
523
|
+
modelSpaceHandle,
|
|
524
|
+
layer.toString(),
|
|
525
|
+
cors,
|
|
526
|
+
c.strokeColor,
|
|
527
|
+
c.fillColor,
|
|
528
|
+
c.strokeThickness,
|
|
529
|
+
size.height,
|
|
530
|
+
options,
|
|
531
|
+
newHandle
|
|
532
|
+
);
|
|
459
533
|
return [entities, blocks, blockRecords];
|
|
460
534
|
}
|
|
461
535
|
|
|
@@ -474,11 +548,10 @@ function stripBlocks(blocks: string, blocksToStrip: ReadonlyArray<string>): stri
|
|
|
474
548
|
let currentBlock: Array<string> = [];
|
|
475
549
|
let currentBlockName = undefined;
|
|
476
550
|
let i = 0;
|
|
477
|
-
while(i < b.length) {
|
|
478
|
-
if(b[i] === "0" && b[i+1] === "BLOCK") {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
if(currentBlockName && !s.has(currentBlockName)) {
|
|
551
|
+
while (i < b.length) {
|
|
552
|
+
if (b[i] === "0" && b[i + 1] === "BLOCK") {
|
|
553
|
+
if (i !== 0) {
|
|
554
|
+
if (currentBlockName && !s.has(currentBlockName)) {
|
|
482
555
|
validBlocks.push(...currentBlock);
|
|
483
556
|
currentBlock = [];
|
|
484
557
|
currentBlockName = undefined;
|
|
@@ -488,10 +561,10 @@ function stripBlocks(blocks: string, blocksToStrip: ReadonlyArray<string>): stri
|
|
|
488
561
|
}
|
|
489
562
|
}
|
|
490
563
|
|
|
491
|
-
currentBlock.push(b[i], b[i+1]);
|
|
564
|
+
currentBlock.push(b[i], b[i + 1]);
|
|
492
565
|
i += 2;
|
|
493
|
-
} else if(b[i] === "2") {
|
|
494
|
-
currentBlockName = b[i+1];
|
|
566
|
+
} else if (b[i] === "2") {
|
|
567
|
+
currentBlockName = b[i + 1];
|
|
495
568
|
currentBlock.push(b[i]);
|
|
496
569
|
i += 1;
|
|
497
570
|
} else {
|
|
@@ -500,7 +573,7 @@ function stripBlocks(blocks: string, blocksToStrip: ReadonlyArray<string>): stri
|
|
|
500
573
|
}
|
|
501
574
|
}
|
|
502
575
|
|
|
503
|
-
if(currentBlockName && !s.has(currentBlockName)) {
|
|
576
|
+
if (currentBlockName && !s.has(currentBlockName)) {
|
|
504
577
|
validBlocks.push(...currentBlock);
|
|
505
578
|
}
|
|
506
579
|
|
|
@@ -526,7 +599,9 @@ function extractEntities(dxf: string): string | undefined {
|
|
|
526
599
|
}
|
|
527
600
|
|
|
528
601
|
function extractBlockRecords(dxf: string): ReadonlyArray<BlockRecord> {
|
|
529
|
-
return [
|
|
602
|
+
return [
|
|
603
|
+
...dxf.matchAll(/^\s*0\s*\n\s*BLOCK_RECORD[\s\S]*?\n\s*5\s*\n\s*([0-9A-Fa-f]+)[\s\S]*?\n\s*2\s*\n\s*([^\r\n]+)/gm),
|
|
604
|
+
].map((match) => ({
|
|
530
605
|
name: match[2],
|
|
531
606
|
id: match[1],
|
|
532
607
|
}));
|
|
@@ -534,7 +609,7 @@ function extractBlockRecords(dxf: string): ReadonlyArray<BlockRecord> {
|
|
|
534
609
|
|
|
535
610
|
function extractBlocks(dxf: string, newModelSpace: string, newPaperSpace: string): string {
|
|
536
611
|
const blockMatch = /0\s+SECTION\s+2\s+BLOCKS\s+([\s\S]*?)0\s+ENDSEC/m.exec(dxf);
|
|
537
|
-
if(blockMatch === null) {
|
|
612
|
+
if (blockMatch === null) {
|
|
538
613
|
return "";
|
|
539
614
|
}
|
|
540
615
|
|
|
@@ -564,7 +639,13 @@ function extractStandard(dxf: string): string | undefined {
|
|
|
564
639
|
return version ? version[1] : undefined;
|
|
565
640
|
}
|
|
566
641
|
|
|
567
|
-
function remapHandleIds(
|
|
642
|
+
function remapHandleIds(
|
|
643
|
+
entities: string | undefined,
|
|
644
|
+
blocks: string | undefined,
|
|
645
|
+
initHandleMap: Map<string, string>,
|
|
646
|
+
rootModelHandle: string,
|
|
647
|
+
newHandle: () => string
|
|
648
|
+
): [string | undefined, string] {
|
|
568
649
|
if (entities === undefined || blocks === undefined) {
|
|
569
650
|
return [undefined, ""];
|
|
570
651
|
}
|
|
@@ -582,16 +663,16 @@ function remapHandleIds(entities: string | undefined, blocks: string | undefined
|
|
|
582
663
|
while (i < lines.length) {
|
|
583
664
|
const groupCode = lines[i].trim();
|
|
584
665
|
const next = (lines[i + 1] ?? "").trim();
|
|
585
|
-
|
|
586
|
-
if(groupCode === "0" && ents.has(next)) {
|
|
666
|
+
|
|
667
|
+
if (groupCode === "0" && ents.has(next)) {
|
|
587
668
|
inEntityHeader = true;
|
|
588
669
|
}
|
|
589
670
|
|
|
590
|
-
if(groupCode === "100" && next === "AcDbEntity") {
|
|
671
|
+
if (groupCode === "100" && next === "AcDbEntity") {
|
|
591
672
|
inEntityHeader = false;
|
|
592
673
|
}
|
|
593
674
|
|
|
594
|
-
if (inEntityHeader &&
|
|
675
|
+
if (inEntityHeader && i + 1 < lines.length && handleGroupCodes.has(groupCode)) {
|
|
595
676
|
const value = lines[i + 1].trim();
|
|
596
677
|
if (/^[0-9A-Fa-f]+$/.test(value)) {
|
|
597
678
|
out.push(groupCode);
|
|
@@ -618,7 +699,7 @@ function remapHandleIds(entities: string | undefined, blocks: string | undefined
|
|
|
618
699
|
}
|
|
619
700
|
|
|
620
701
|
function scaleDxf(dxfString: string | undefined, sx: number, sy: number): string | undefined {
|
|
621
|
-
if(!dxfString) {
|
|
702
|
+
if (!dxfString) {
|
|
622
703
|
return undefined;
|
|
623
704
|
}
|
|
624
705
|
|
|
@@ -629,11 +710,11 @@ function scaleDxf(dxfString: string | undefined, sx: number, sy: number): string
|
|
|
629
710
|
const scaledLines: string[] = [];
|
|
630
711
|
|
|
631
712
|
let currentAcDbEntity = "";
|
|
632
|
-
for (let i = 0; i < lines.length; i+=2) {
|
|
713
|
+
for (let i = 0; i < lines.length; i += 2) {
|
|
633
714
|
const codeLine = lines[i];
|
|
634
715
|
const valueLine = lines[i + 1];
|
|
635
716
|
|
|
636
|
-
if(codeLine === "100") {
|
|
717
|
+
if (codeLine === "100") {
|
|
637
718
|
currentAcDbEntity = valueLine;
|
|
638
719
|
}
|
|
639
720
|
|
|
@@ -650,17 +731,19 @@ function scaleDxf(dxfString: string | undefined, sx: number, sy: number): string
|
|
|
650
731
|
if (!isNaN(num)) {
|
|
651
732
|
value = (num * sx).toString();
|
|
652
733
|
}
|
|
653
|
-
} else if(yCoordinateCodes.has(code)) {
|
|
734
|
+
} else if (yCoordinateCodes.has(code)) {
|
|
654
735
|
const num = parseFloat(valueLine);
|
|
655
736
|
if (!isNaN(num)) {
|
|
656
737
|
value = (num * sy).toString();
|
|
657
738
|
}
|
|
658
|
-
} else if(code === 40 && currentAcDbEntity === "AcDbText") {
|
|
739
|
+
} else if (code === 40 && currentAcDbEntity === "AcDbText") {
|
|
740
|
+
//font size
|
|
659
741
|
const num = parseInt(valueLine.trim(), 10);
|
|
660
742
|
if (!isNaN(num)) {
|
|
661
743
|
value = Math.round((num + 2) * Math.max(sx, sy)).toString();
|
|
662
744
|
}
|
|
663
|
-
} else if((code === 41 || code === 40) && currentAcDbEntity === "AcDb2dPolyline") {
|
|
745
|
+
} else if ((code === 41 || code === 40) && currentAcDbEntity === "AcDb2dPolyline") {
|
|
746
|
+
// stroke thickness
|
|
664
747
|
const num = parseInt(valueLine.trim(), 10);
|
|
665
748
|
if (!isNaN(num)) {
|
|
666
749
|
value = (num * Math.max(sx, sy)).toString();
|
|
@@ -686,12 +769,17 @@ function getScale(extents: DxfExtents, c: BinaryImage): { readonly x: number; re
|
|
|
686
769
|
const sy = targetH / srcH;
|
|
687
770
|
return {
|
|
688
771
|
x: sx,
|
|
689
|
-
y: sy
|
|
690
|
-
}
|
|
772
|
+
y: sy,
|
|
773
|
+
};
|
|
691
774
|
}
|
|
692
775
|
|
|
693
|
-
function createExternalInsert(
|
|
694
|
-
|
|
776
|
+
function createExternalInsert(
|
|
777
|
+
ins: DxfInsert,
|
|
778
|
+
c: BinaryImage,
|
|
779
|
+
size: Size,
|
|
780
|
+
modelSpaceHandle: string,
|
|
781
|
+
newHandle: () => string
|
|
782
|
+
): string {
|
|
695
783
|
const minX = Math.min(c.topLeft.x, c.bottomRight.x);
|
|
696
784
|
const maxY = Math.max(c.topLeft.y, c.bottomRight.y);
|
|
697
785
|
const x = minX - ins.extents.minX;
|
|
@@ -791,7 +879,6 @@ function createLTypeTable(newHandle: () => string): string {
|
|
|
791
879
|
}
|
|
792
880
|
|
|
793
881
|
function createLayerTable(newHandle: () => string): string {
|
|
794
|
-
|
|
795
882
|
const layers = ["0", "1", "A3D", "Lines", "Text"];
|
|
796
883
|
const layerId = newHandle();
|
|
797
884
|
|
|
@@ -803,7 +890,7 @@ function createLayerTable(newHandle: () => string): string {
|
|
|
803
890
|
table += "100\nAcDbSymbolTable\n";
|
|
804
891
|
table += "70\n" + layers.length.toString() + "\n";
|
|
805
892
|
|
|
806
|
-
for(const layer of layers) {
|
|
893
|
+
for (const layer of layers) {
|
|
807
894
|
table += "0\nLAYER\n";
|
|
808
895
|
table += "5\n" + newHandle() + "\n";
|
|
809
896
|
table += "330\n" + layerId + "\n";
|
|
@@ -952,11 +1039,16 @@ function createDimStyleTable(newHandle: () => string): string {
|
|
|
952
1039
|
return table;
|
|
953
1040
|
}
|
|
954
1041
|
|
|
955
|
-
function createBlockRecordsTable(
|
|
1042
|
+
function createBlockRecordsTable(
|
|
1043
|
+
modelSpaceHandle: string,
|
|
1044
|
+
paperSpaceHandle: string,
|
|
1045
|
+
blockRecords: ReadonlyArray<BlockRecord>,
|
|
1046
|
+
newHandle: () => string
|
|
1047
|
+
): string {
|
|
956
1048
|
const br: ReadonlyArray<BlockRecord> = [
|
|
957
1049
|
{ id: modelSpaceHandle, name: "*Model_Space" },
|
|
958
1050
|
{ id: paperSpaceHandle, name: "*Paper_Space" },
|
|
959
|
-
...blockRecords
|
|
1051
|
+
...blockRecords,
|
|
960
1052
|
];
|
|
961
1053
|
|
|
962
1054
|
const blockRecordsHandle = newHandle();
|
|
@@ -969,7 +1061,7 @@ function createBlockRecordsTable(modelSpaceHandle: string, paperSpaceHandle: str
|
|
|
969
1061
|
table += "100\nAcDbSymbolTable\n";
|
|
970
1062
|
table += "70\n" + br.length.toString() + "\n";
|
|
971
1063
|
|
|
972
|
-
for(const record of br) {
|
|
1064
|
+
for (const record of br) {
|
|
973
1065
|
table += "0\nBLOCK_RECORD\n";
|
|
974
1066
|
table += "5\n" + record.id + "\n";
|
|
975
1067
|
table += "330\n" + blockRecordsHandle + "\n";
|
|
@@ -985,7 +1077,12 @@ function createBlockRecordsTable(modelSpaceHandle: string, paperSpaceHandle: str
|
|
|
985
1077
|
return table;
|
|
986
1078
|
}
|
|
987
1079
|
|
|
988
|
-
function createObjects(
|
|
1080
|
+
function createObjects(
|
|
1081
|
+
modelSpaceHandle: string,
|
|
1082
|
+
paperSpaceHandle: string,
|
|
1083
|
+
root: AbstractImage,
|
|
1084
|
+
newHandle: () => string
|
|
1085
|
+
): string {
|
|
989
1086
|
let objects = "";
|
|
990
1087
|
const rootDictId = newHandle();
|
|
991
1088
|
const groupDictId = newHandle();
|
|
@@ -1012,7 +1109,8 @@ function createObjects(modelSpaceHandle: string, paperSpaceHandle: string, root:
|
|
|
1012
1109
|
objects += "0\nLAYOUT\n5\n" + layoutModelId + "\n102\n{ACAD_REACTORS\n330\n" + layoutDictId + "\n102\n}\n";
|
|
1013
1110
|
objects += "330\n" + layoutDictId + "\n100\nAcDbPlotSettings\n1\n\n2\nnone_device\n4\n\n6\n\n";
|
|
1014
1111
|
objects += "40\n0.0\n41\n0.0\n42\n0.0\n43\n0.0\n44\n0.0\n45\n0.0\n46\n0.0\n47\n0.0\n48\n0.0\n49\n0.0\n";
|
|
1015
|
-
objects +=
|
|
1112
|
+
objects +=
|
|
1113
|
+
"140\n0.0\n141\n0.0\n142\n1.0\n143\n1.0\n70\n1712\n72\n0\n73\n0\n74\n0\n7\n\n75\n0\n147\n1.0\n148\n0.0\n149\n0.0\n";
|
|
1016
1114
|
objects += "100\nAcDbLayout\n1\nModel\n70\n1\n71\n0\n";
|
|
1017
1115
|
objects += "10\n0.0\n20\n0.0\n11\n" + root.size.width + "\n21\n" + root.size.height + "\n";
|
|
1018
1116
|
objects += "12\n0.0\n22\n0.0\n32\n0.0\n14\n0.0\n24\n0.0\n34\n0.0\n";
|
|
@@ -1024,7 +1122,8 @@ function createObjects(modelSpaceHandle: string, paperSpaceHandle: string, root:
|
|
|
1024
1122
|
objects += "0\nLAYOUT\n5\n" + layoutPaperId + "\n102\n{ACAD_REACTORS\n330\n" + layoutDictId + "\n102\n}\n";
|
|
1025
1123
|
objects += "330\n" + layoutDictId + "\n100\nAcDbPlotSettings\n1\n\n2\nnone_device\n4\n\n6\n\n";
|
|
1026
1124
|
objects += "40\n0.0\n41\n0.0\n42\n0.0\n43\n0.0\n44\n0.0\n45\n0.0\n46\n0.0\n47\n0.0\n48\n0.0\n49\n0.0\n";
|
|
1027
|
-
objects +=
|
|
1125
|
+
objects +=
|
|
1126
|
+
"140\n0.0\n141\n0.0\n142\n1.0\n143\n1.0\n70\n688\n72\n0\n73\n0\n74\n5\n7\n\n75\n16\n147\n1.0\n148\n0.0\n149\n0.0\n";
|
|
1028
1127
|
objects += "100\nAcDbLayout\n1\nLayout1\n70\n1\n71\n1\n";
|
|
1029
1128
|
objects += "10\n0.0\n20\n0.0\n11\n" + root.size.width + "\n21\n" + root.size.height + "\n";
|
|
1030
1129
|
objects += "12\n0.0\n22\n0.0\n32\n0.0\n14\n1.0E+20\n24\n1.0E+20\n34\n1.0E+20\n";
|
|
@@ -1069,7 +1168,7 @@ function createHatch(
|
|
|
1069
1168
|
height: number,
|
|
1070
1169
|
newHandle: () => string
|
|
1071
1170
|
): string {
|
|
1072
|
-
const invertedPoints = points.map(p => ({ x: p.x, y: invert(p.y, height) }));
|
|
1171
|
+
const invertedPoints = points.map((p) => ({ x: p.x, y: invert(p.y, height) }));
|
|
1073
1172
|
const cx = invertedPoints.reduce((s, p) => s + p.x, 0) / invertedPoints.length;
|
|
1074
1173
|
const cy = invertedPoints.reduce((s, p) => s + p.y, 0) / invertedPoints.length;
|
|
1075
1174
|
|
|
@@ -1108,21 +1207,31 @@ function createHatch(
|
|
|
1108
1207
|
return hatch;
|
|
1109
1208
|
}
|
|
1110
1209
|
|
|
1111
|
-
function createPolygon(
|
|
1210
|
+
function createPolygon(
|
|
1211
|
+
modelSpaceHandle: string,
|
|
1212
|
+
layer: string,
|
|
1213
|
+
points: ReadonlyArray<Point>,
|
|
1214
|
+
strokeColor: Color,
|
|
1215
|
+
fillColor: Color,
|
|
1216
|
+
strokeThickness: number | undefined,
|
|
1217
|
+
height: number,
|
|
1218
|
+
options: Required<DxfOptions>,
|
|
1219
|
+
newHandle: () => string
|
|
1220
|
+
): string {
|
|
1112
1221
|
const handle = newHandle();
|
|
1113
1222
|
let polygon = "";
|
|
1114
1223
|
|
|
1115
|
-
if(options.fillPolygons) {
|
|
1224
|
+
if (options.fillPolygons) {
|
|
1116
1225
|
polygon += createHatch(modelSpaceHandle, layer, fillColor, points, height, newHandle);
|
|
1117
1226
|
}
|
|
1118
|
-
|
|
1227
|
+
|
|
1119
1228
|
polygon += "0\nPOLYLINE\n";
|
|
1120
1229
|
polygon += "5\n" + handle + "\n";
|
|
1121
1230
|
polygon += "330\n" + modelSpaceHandle + "\n";
|
|
1122
1231
|
polygon += "100\nAcDbEntity\n";
|
|
1123
1232
|
polygon += "8\n" + layer.toString() + "\n";
|
|
1124
1233
|
|
|
1125
|
-
if(options.useColor && !isBlack(strokeColor)) {
|
|
1234
|
+
if (options.useColor && !isBlack(strokeColor)) {
|
|
1126
1235
|
polygon += "60\n0\n";
|
|
1127
1236
|
polygon += "62\n256\n";
|
|
1128
1237
|
polygon += "420\n" + colorToInteger(strokeColor) + "\n";
|
|
@@ -1133,7 +1242,7 @@ function createPolygon(modelSpaceHandle: string, layer: string, points: Readonly
|
|
|
1133
1242
|
polygon += "70\n1\n";
|
|
1134
1243
|
polygon += "10\n0.0\n20\n0.0\n30\n0.0\n";
|
|
1135
1244
|
|
|
1136
|
-
if(options.useStrokeThickness && strokeThickness && strokeThickness >= Number.EPSILON) {
|
|
1245
|
+
if (options.useStrokeThickness && strokeThickness && strokeThickness >= Number.EPSILON) {
|
|
1137
1246
|
polygon += "40\n" + strokeThickness.toPrecision(4) + "\n";
|
|
1138
1247
|
polygon += "41\n" + strokeThickness.toPrecision(4) + "\n";
|
|
1139
1248
|
}
|
|
@@ -1161,16 +1270,16 @@ function createPolygon(modelSpaceHandle: string, layer: string, points: Readonly
|
|
|
1161
1270
|
return polygon;
|
|
1162
1271
|
}
|
|
1163
1272
|
|
|
1164
|
-
function handleGenerator(): { newHandle: () => string
|
|
1273
|
+
function handleGenerator(): { newHandle: () => string; currentHandle: () => string } {
|
|
1165
1274
|
let index = 0x1000;
|
|
1166
1275
|
return {
|
|
1167
1276
|
newHandle: () => (index++).toString(16).toUpperCase(),
|
|
1168
|
-
currentHandle: () =>
|
|
1277
|
+
currentHandle: () => index.toString(16).toUpperCase(),
|
|
1169
1278
|
};
|
|
1170
1279
|
}
|
|
1171
1280
|
|
|
1172
1281
|
function randomID(): string {
|
|
1173
|
-
return "xxxxxxxxxxxxxxxx".replaceAll("x", () =>
|
|
1282
|
+
return "xxxxxxxxxxxxxxxx".replaceAll("x", () => Math.round(Math.random() * 16).toString(16)).toLocaleUpperCase();
|
|
1174
1283
|
}
|
|
1175
1284
|
|
|
1176
1285
|
function isBlack(color: Color): boolean {
|
|
@@ -1179,8 +1288,8 @@ function isBlack(color: Color): boolean {
|
|
|
1179
1288
|
|
|
1180
1289
|
function colorToInteger(color: Color): number {
|
|
1181
1290
|
const colorAsInt = (color.r << 16) + (color.g << 8) + color.b;
|
|
1182
|
-
if(Number.isNaN(colorAsInt)) {
|
|
1291
|
+
if (Number.isNaN(colorAsInt)) {
|
|
1183
1292
|
return 0;
|
|
1184
1293
|
}
|
|
1185
1294
|
return colorAsInt;
|
|
1186
|
-
}
|
|
1295
|
+
}
|
|
@@ -4,6 +4,7 @@ import { AbstractImage } from "../model/abstract-image.js";
|
|
|
4
4
|
import { createPoint, Point } from "../model/point.js";
|
|
5
5
|
import { AbstractFontWeight, BinaryFormat, Component, GrowthDirection, ImageData } from "../model/component.js";
|
|
6
6
|
import { Color } from "../model/color.js";
|
|
7
|
+
import { Optional } from "../model/shared.js";
|
|
7
8
|
|
|
8
9
|
export interface ReactSvgCallbacks {
|
|
9
10
|
readonly onClick?: MouseCallback;
|
|
@@ -14,13 +15,22 @@ export interface ReactSvgCallbacks {
|
|
|
14
15
|
|
|
15
16
|
export type MouseCallback = (id: string | undefined, point: Point) => void;
|
|
16
17
|
|
|
18
|
+
export type ReactSvgOptions = {
|
|
19
|
+
readonly imageDataByUrl: Record<string, `data:image/${string},${string}`>;
|
|
20
|
+
};
|
|
21
|
+
|
|
17
22
|
export function ReactSvg({
|
|
18
23
|
image,
|
|
19
24
|
callbacks,
|
|
25
|
+
options,
|
|
20
26
|
}: {
|
|
21
27
|
readonly image: AbstractImage;
|
|
22
28
|
readonly callbacks?: ReactSvgCallbacks;
|
|
29
|
+
readonly options?: Optional<ReactSvgOptions>;
|
|
23
30
|
}): React.JSX.Element {
|
|
31
|
+
const opts: ReactSvgOptions = {
|
|
32
|
+
imageDataByUrl: options?.imageDataByUrl ?? {},
|
|
33
|
+
};
|
|
24
34
|
const cb = callbacks || {};
|
|
25
35
|
const id = "ai_root";
|
|
26
36
|
return (
|
|
@@ -35,7 +45,7 @@ export function ReactSvg({
|
|
|
35
45
|
onContextMenu={_callback(cb.onContextMenu, id)}
|
|
36
46
|
>
|
|
37
47
|
{image.components.map((c, i) => (
|
|
38
|
-
<JsxComponent key={i} component={c} />
|
|
48
|
+
<JsxComponent key={i} component={c} options={opts} />
|
|
39
49
|
))}
|
|
40
50
|
</svg>
|
|
41
51
|
);
|
|
@@ -74,18 +84,24 @@ function getIdAttr(target: Element | undefined, rootId: string): string | undefi
|
|
|
74
84
|
return parts[1];
|
|
75
85
|
}
|
|
76
86
|
|
|
77
|
-
function JsxComponent({
|
|
87
|
+
function JsxComponent({
|
|
88
|
+
component,
|
|
89
|
+
options,
|
|
90
|
+
}: {
|
|
91
|
+
readonly component: Component;
|
|
92
|
+
readonly options: ReactSvgOptions;
|
|
93
|
+
}): React.JSX.Element {
|
|
78
94
|
switch (component.type) {
|
|
79
95
|
case "group":
|
|
80
96
|
return (
|
|
81
97
|
<g name={component.name}>
|
|
82
98
|
{component.children.flatMap((c, i) => (
|
|
83
|
-
<JsxComponent key={i} component={c} />
|
|
99
|
+
<JsxComponent key={i} component={c} options={options} />
|
|
84
100
|
))}
|
|
85
101
|
</g>
|
|
86
102
|
);
|
|
87
103
|
case "binaryimage":
|
|
88
|
-
const url = getImageUrl(component.format, component.data);
|
|
104
|
+
const url = getImageUrl(component.format, component.data, options);
|
|
89
105
|
return (
|
|
90
106
|
<image
|
|
91
107
|
x={component.topLeft.x}
|
|
@@ -270,9 +286,9 @@ function getTextFontWeight(fontWeight: AbstractFontWeight): React.CSSProperties[
|
|
|
270
286
|
}
|
|
271
287
|
}
|
|
272
288
|
|
|
273
|
-
function getImageUrl(format: BinaryFormat, data: ImageData): string {
|
|
289
|
+
function getImageUrl(format: BinaryFormat, data: ImageData, options: ReactSvgOptions): string {
|
|
274
290
|
if (data.type === "url") {
|
|
275
|
-
return data.url;
|
|
291
|
+
return options.imageDataByUrl[data.url] ?? data.url;
|
|
276
292
|
} else if (format === "png") {
|
|
277
293
|
const base64 = fromByteArray(data.bytes);
|
|
278
294
|
return `data:image/png;base64,${base64}`;
|