apexify.js 4.9.28 → 5.0.0
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/README.md +727 -456
- package/dist/cjs/Canvas/ApexPainter.d.ts +96 -145
- package/dist/cjs/Canvas/ApexPainter.d.ts.map +1 -1
- package/dist/cjs/Canvas/ApexPainter.js +1416 -420
- package/dist/cjs/Canvas/ApexPainter.js.map +1 -1
- package/dist/cjs/Canvas/utils/Charts/charts.d.ts +7 -2
- package/dist/cjs/Canvas/utils/Charts/charts.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Charts/charts.js +3 -1
- package/dist/cjs/Canvas/utils/Charts/charts.js.map +1 -1
- package/dist/cjs/Canvas/utils/Custom/advancedLines.d.ts +75 -0
- package/dist/cjs/Canvas/utils/Custom/advancedLines.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Custom/advancedLines.js +263 -0
- package/dist/cjs/Canvas/utils/Custom/advancedLines.js.map +1 -0
- package/dist/cjs/Canvas/utils/Custom/customLines.d.ts +2 -1
- package/dist/cjs/Canvas/utils/Custom/customLines.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Custom/customLines.js +73 -6
- package/dist/cjs/Canvas/utils/Custom/customLines.js.map +1 -1
- package/dist/cjs/Canvas/utils/General/batchOperations.d.ts +17 -0
- package/dist/cjs/Canvas/utils/General/batchOperations.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/General/batchOperations.js +88 -0
- package/dist/cjs/Canvas/utils/General/batchOperations.js.map +1 -0
- package/dist/cjs/Canvas/utils/General/general functions.d.ts +25 -3
- package/dist/cjs/Canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/General/general functions.js +37 -9
- package/dist/cjs/Canvas/utils/General/general functions.js.map +1 -1
- package/dist/cjs/Canvas/utils/General/imageCompression.d.ts +19 -0
- package/dist/cjs/Canvas/utils/General/imageCompression.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/General/imageCompression.js +262 -0
- package/dist/cjs/Canvas/utils/General/imageCompression.js.map +1 -0
- package/dist/cjs/Canvas/utils/General/imageStitching.d.ts +20 -0
- package/dist/cjs/Canvas/utils/General/imageStitching.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/General/imageStitching.js +227 -0
- package/dist/cjs/Canvas/utils/General/imageStitching.js.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageEffects.d.ts +37 -0
- package/dist/cjs/Canvas/utils/Image/imageEffects.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageEffects.js +128 -0
- package/dist/cjs/Canvas/utils/Image/imageEffects.js.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageMasking.d.ts +67 -0
- package/dist/cjs/Canvas/utils/Image/imageMasking.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageMasking.js +276 -0
- package/dist/cjs/Canvas/utils/Image/imageMasking.js.map +1 -0
- package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Image/imageProperties.js +181 -2
- package/dist/cjs/Canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.js +16 -8
- package/dist/cjs/Canvas/utils/Patterns/enhancedPatternRenderer.js.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts +33 -0
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js +237 -32
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/textPathRenderer.d.ts +17 -0
- package/dist/cjs/Canvas/utils/Texts/textPathRenderer.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Texts/textPathRenderer.js +233 -0
- package/dist/cjs/Canvas/utils/Texts/textPathRenderer.js.map +1 -0
- package/dist/cjs/Canvas/utils/types.d.ts +171 -10
- package/dist/cjs/Canvas/utils/types.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/types.js.map +1 -1
- package/dist/cjs/Canvas/utils/utils.d.ts +9 -2
- package/dist/cjs/Canvas/utils/utils.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/utils.js +32 -1
- package/dist/cjs/Canvas/utils/utils.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/Canvas/ApexPainter.d.ts +96 -145
- package/dist/esm/Canvas/ApexPainter.d.ts.map +1 -1
- package/dist/esm/Canvas/ApexPainter.js +1416 -420
- package/dist/esm/Canvas/ApexPainter.js.map +1 -1
- package/dist/esm/Canvas/utils/Charts/charts.d.ts +7 -2
- package/dist/esm/Canvas/utils/Charts/charts.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Charts/charts.js +3 -1
- package/dist/esm/Canvas/utils/Charts/charts.js.map +1 -1
- package/dist/esm/Canvas/utils/Custom/advancedLines.d.ts +75 -0
- package/dist/esm/Canvas/utils/Custom/advancedLines.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Custom/advancedLines.js +263 -0
- package/dist/esm/Canvas/utils/Custom/advancedLines.js.map +1 -0
- package/dist/esm/Canvas/utils/Custom/customLines.d.ts +2 -1
- package/dist/esm/Canvas/utils/Custom/customLines.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Custom/customLines.js +73 -6
- package/dist/esm/Canvas/utils/Custom/customLines.js.map +1 -1
- package/dist/esm/Canvas/utils/General/batchOperations.d.ts +17 -0
- package/dist/esm/Canvas/utils/General/batchOperations.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/General/batchOperations.js +88 -0
- package/dist/esm/Canvas/utils/General/batchOperations.js.map +1 -0
- package/dist/esm/Canvas/utils/General/general functions.d.ts +25 -3
- package/dist/esm/Canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/General/general functions.js +37 -9
- package/dist/esm/Canvas/utils/General/general functions.js.map +1 -1
- package/dist/esm/Canvas/utils/General/imageCompression.d.ts +19 -0
- package/dist/esm/Canvas/utils/General/imageCompression.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/General/imageCompression.js +262 -0
- package/dist/esm/Canvas/utils/General/imageCompression.js.map +1 -0
- package/dist/esm/Canvas/utils/General/imageStitching.d.ts +20 -0
- package/dist/esm/Canvas/utils/General/imageStitching.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/General/imageStitching.js +227 -0
- package/dist/esm/Canvas/utils/General/imageStitching.js.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageEffects.d.ts +37 -0
- package/dist/esm/Canvas/utils/Image/imageEffects.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageEffects.js +128 -0
- package/dist/esm/Canvas/utils/Image/imageEffects.js.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageMasking.d.ts +67 -0
- package/dist/esm/Canvas/utils/Image/imageMasking.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageMasking.js +276 -0
- package/dist/esm/Canvas/utils/Image/imageMasking.js.map +1 -0
- package/dist/esm/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Image/imageProperties.js +181 -2
- package/dist/esm/Canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.js +16 -8
- package/dist/esm/Canvas/utils/Patterns/enhancedPatternRenderer.js.map +1 -1
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts +33 -0
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js +237 -32
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
- package/dist/esm/Canvas/utils/Texts/textPathRenderer.d.ts +17 -0
- package/dist/esm/Canvas/utils/Texts/textPathRenderer.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Texts/textPathRenderer.js +233 -0
- package/dist/esm/Canvas/utils/Texts/textPathRenderer.js.map +1 -0
- package/dist/esm/Canvas/utils/types.d.ts +171 -10
- package/dist/esm/Canvas/utils/types.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/types.js.map +1 -1
- package/dist/esm/Canvas/utils/utils.d.ts +9 -2
- package/dist/esm/Canvas/utils/utils.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/utils.js +32 -1
- package/dist/esm/Canvas/utils/utils.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/Canvas/ApexPainter.ts +1309 -267
- package/lib/Canvas/utils/Charts/charts.ts +16 -7
- package/lib/Canvas/utils/Custom/advancedLines.ts +335 -0
- package/lib/Canvas/utils/Custom/customLines.ts +84 -9
- package/lib/Canvas/utils/General/batchOperations.ts +103 -0
- package/lib/Canvas/utils/General/general functions.ts +85 -41
- package/lib/Canvas/utils/General/imageCompression.ts +316 -0
- package/lib/Canvas/utils/General/imageStitching.ts +252 -0
- package/lib/Canvas/utils/Image/imageEffects.ts +175 -0
- package/lib/Canvas/utils/Image/imageMasking.ts +335 -0
- package/lib/Canvas/utils/Image/imageProperties.ts +207 -2
- package/lib/Canvas/utils/Patterns/enhancedPatternRenderer.ts +455 -444
- package/lib/Canvas/utils/Texts/enhancedTextRenderer.ts +274 -36
- package/lib/Canvas/utils/Texts/textPathRenderer.ts +320 -0
- package/lib/Canvas/utils/types.ts +173 -10
- package/lib/Canvas/utils/utils.ts +49 -2
- package/package.json +69 -34
|
@@ -16,9 +16,12 @@ export class EnhancedTextRenderer {
|
|
|
16
16
|
ctx.save();
|
|
17
17
|
|
|
18
18
|
try {
|
|
19
|
-
// 1. Register custom font if provided
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
// 1. Register custom font if provided (support both new and legacy properties)
|
|
20
|
+
const fontPath = textProps.font?.path || textProps.fontPath;
|
|
21
|
+
const fontName = textProps.font?.name || textProps.fontName;
|
|
22
|
+
|
|
23
|
+
if (fontPath) {
|
|
24
|
+
await this.registerCustomFont(fontPath, fontName || 'customFont');
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
// 2. Apply transformations
|
|
@@ -81,8 +84,9 @@ export class EnhancedTextRenderer {
|
|
|
81
84
|
* @param textProps - Text properties
|
|
82
85
|
*/
|
|
83
86
|
private static setupFont(ctx: SKRSContext2D, textProps: TextProperties): void {
|
|
84
|
-
|
|
85
|
-
const
|
|
87
|
+
// Support both new font object and legacy properties
|
|
88
|
+
const fontSize = textProps.font?.size || textProps.fontSize || 16;
|
|
89
|
+
const fontFamily = textProps.font?.name || textProps.fontName || textProps.font?.family || textProps.fontFamily || 'Arial';
|
|
86
90
|
|
|
87
91
|
// Build font string with decorations
|
|
88
92
|
let fontString = '';
|
|
@@ -121,7 +125,7 @@ export class EnhancedTextRenderer {
|
|
|
121
125
|
* @param textProps - Text properties
|
|
122
126
|
*/
|
|
123
127
|
private static async renderWrappedText(ctx: SKRSContext2D, textProps: TextProperties): Promise<void> {
|
|
124
|
-
const fontSize = textProps.fontSize || 16;
|
|
128
|
+
const fontSize = textProps.font?.size || textProps.fontSize || 16;
|
|
125
129
|
const lineHeight = (textProps.lineHeight || 1.4) * fontSize;
|
|
126
130
|
const maxHeight = textProps.maxHeight;
|
|
127
131
|
const maxLines = maxHeight ? Math.floor(maxHeight / lineHeight) : Infinity;
|
|
@@ -186,7 +190,7 @@ export class EnhancedTextRenderer {
|
|
|
186
190
|
// Calculate text dimensions
|
|
187
191
|
const metrics = ctx.measureText(text);
|
|
188
192
|
const textWidth = metrics.width;
|
|
189
|
-
const fontSize = textProps.fontSize || 16;
|
|
193
|
+
const fontSize = textProps.font?.size || textProps.fontSize || 16;
|
|
190
194
|
const textHeight = fontSize;
|
|
191
195
|
|
|
192
196
|
// Apply highlight background
|
|
@@ -231,13 +235,19 @@ export class EnhancedTextRenderer {
|
|
|
231
235
|
y: number,
|
|
232
236
|
width: number,
|
|
233
237
|
height: number,
|
|
234
|
-
highlight: { color?: string; opacity?: number }
|
|
238
|
+
highlight: { color?: string; gradient?: gradient; opacity?: number }
|
|
235
239
|
): void {
|
|
236
240
|
ctx.save();
|
|
237
241
|
|
|
238
242
|
const opacity = highlight.opacity !== undefined ? highlight.opacity : 0.3;
|
|
239
243
|
ctx.globalAlpha = opacity;
|
|
240
|
-
|
|
244
|
+
|
|
245
|
+
// Set fill style (gradient or color)
|
|
246
|
+
if (highlight.gradient) {
|
|
247
|
+
ctx.fillStyle = this.createGradient(ctx, highlight.gradient, x, y, x + width, y + height);
|
|
248
|
+
} else {
|
|
249
|
+
ctx.fillStyle = highlight.color || '#ffff00';
|
|
250
|
+
}
|
|
241
251
|
|
|
242
252
|
// Adjust highlight position based on text baseline
|
|
243
253
|
const highlightY = y - height * 0.8; // Adjust for different baselines
|
|
@@ -259,18 +269,33 @@ export class EnhancedTextRenderer {
|
|
|
259
269
|
text: string,
|
|
260
270
|
x: number,
|
|
261
271
|
y: number,
|
|
262
|
-
glow: { color?: string; intensity?: number; opacity?: number }
|
|
272
|
+
glow: { color?: string; gradient?: gradient; intensity?: number; opacity?: number }
|
|
263
273
|
): void {
|
|
264
274
|
ctx.save();
|
|
265
275
|
|
|
266
276
|
const intensity = glow.intensity || 10;
|
|
267
277
|
const opacity = glow.opacity !== undefined ? glow.opacity : 0.8;
|
|
268
278
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
279
|
+
// For glow, we need to use shadowColor which only supports solid colors
|
|
280
|
+
// So we'll render the glow with the base color and then overlay with gradient if needed
|
|
281
|
+
if (glow.gradient) {
|
|
282
|
+
// First render with shadow for glow effect
|
|
283
|
+
ctx.shadowColor = '#ffffff'; // Use white as base for glow
|
|
284
|
+
ctx.shadowBlur = intensity;
|
|
285
|
+
ctx.globalAlpha = opacity;
|
|
286
|
+
ctx.fillText(text, x, y);
|
|
287
|
+
|
|
288
|
+
// Then overlay with gradient
|
|
289
|
+
ctx.shadowColor = 'transparent';
|
|
290
|
+
ctx.shadowBlur = 0;
|
|
291
|
+
ctx.fillStyle = this.createGradient(ctx, glow.gradient, x, y, x + ctx.measureText(text).width, y);
|
|
292
|
+
ctx.fillText(text, x, y);
|
|
293
|
+
} else {
|
|
294
|
+
ctx.shadowColor = glow.color || '#ffffff';
|
|
295
|
+
ctx.shadowBlur = intensity;
|
|
296
|
+
ctx.globalAlpha = opacity;
|
|
297
|
+
ctx.fillText(text, x, y);
|
|
298
|
+
}
|
|
274
299
|
|
|
275
300
|
ctx.restore();
|
|
276
301
|
}
|
|
@@ -319,11 +344,14 @@ export class EnhancedTextRenderer {
|
|
|
319
344
|
text: string,
|
|
320
345
|
x: number,
|
|
321
346
|
y: number,
|
|
322
|
-
stroke: { color?: string; width?: number; gradient?: gradient; opacity?: number }
|
|
347
|
+
stroke: { color?: string; width?: number; gradient?: gradient; opacity?: number; style?: 'solid' | 'dashed' | 'dotted' | 'groove' | 'ridge' | 'double' }
|
|
323
348
|
): void {
|
|
324
349
|
ctx.save();
|
|
325
350
|
|
|
326
|
-
|
|
351
|
+
const strokeWidth = stroke.width || 1;
|
|
352
|
+
const strokeStyle = stroke.style || 'solid';
|
|
353
|
+
|
|
354
|
+
ctx.lineWidth = strokeWidth;
|
|
327
355
|
|
|
328
356
|
if (stroke.gradient) {
|
|
329
357
|
ctx.strokeStyle = this.createGradient(ctx, stroke.gradient, x, y, x + ctx.measureText(text).width, y);
|
|
@@ -335,7 +363,15 @@ export class EnhancedTextRenderer {
|
|
|
335
363
|
ctx.globalAlpha = stroke.opacity;
|
|
336
364
|
}
|
|
337
365
|
|
|
338
|
-
|
|
366
|
+
// Apply stroke style
|
|
367
|
+
this.applyTextStrokeStyle(ctx, strokeStyle, strokeWidth);
|
|
368
|
+
|
|
369
|
+
// Handle complex stroke styles
|
|
370
|
+
if (strokeStyle === 'groove' || strokeStyle === 'ridge' || strokeStyle === 'double') {
|
|
371
|
+
this.renderComplexTextStroke(ctx, text, x, y, strokeStyle, strokeWidth, stroke.color, stroke.gradient);
|
|
372
|
+
} else {
|
|
373
|
+
ctx.strokeText(text, x, y);
|
|
374
|
+
}
|
|
339
375
|
|
|
340
376
|
ctx.restore();
|
|
341
377
|
}
|
|
@@ -387,44 +423,69 @@ export class EnhancedTextRenderer {
|
|
|
387
423
|
height: number,
|
|
388
424
|
textProps: TextProperties
|
|
389
425
|
): void {
|
|
390
|
-
|
|
426
|
+
const hasDecorations = textProps.underline || textProps.overline || textProps.strikethrough;
|
|
427
|
+
if (!hasDecorations) {
|
|
391
428
|
return;
|
|
392
429
|
}
|
|
393
430
|
|
|
394
431
|
ctx.save();
|
|
395
432
|
|
|
396
|
-
const fontSize = textProps.fontSize || 16;
|
|
397
|
-
const
|
|
398
|
-
const decorationWidth = Math.max(1, fontSize * 0.05); // 5% of font size
|
|
433
|
+
const fontSize = textProps.font?.size || textProps.fontSize || 16;
|
|
434
|
+
const defaultColor = textProps.color || '#000000';
|
|
399
435
|
|
|
400
|
-
|
|
401
|
-
|
|
436
|
+
// Helper function to render a decoration line
|
|
437
|
+
const renderDecorationLine = (
|
|
438
|
+
decorationY: number,
|
|
439
|
+
decoration: boolean | { color?: string; gradient?: gradient; width?: number } | undefined,
|
|
440
|
+
lineName: string
|
|
441
|
+
) => {
|
|
442
|
+
if (!decoration) return;
|
|
443
|
+
|
|
444
|
+
ctx.save();
|
|
445
|
+
|
|
446
|
+
let decorationColor = defaultColor;
|
|
447
|
+
let decorationWidth = Math.max(1, fontSize * 0.05); // 5% of font size
|
|
448
|
+
|
|
449
|
+
if (typeof decoration === 'object') {
|
|
450
|
+
decorationColor = decoration.color || defaultColor;
|
|
451
|
+
decorationWidth = decoration.width || decorationWidth;
|
|
452
|
+
|
|
453
|
+
// Set stroke style (gradient or color)
|
|
454
|
+
if (decoration.gradient) {
|
|
455
|
+
ctx.strokeStyle = this.createGradient(ctx, decoration.gradient, x, decorationY, x + width, decorationY);
|
|
456
|
+
} else {
|
|
457
|
+
ctx.strokeStyle = decorationColor;
|
|
458
|
+
}
|
|
459
|
+
} else {
|
|
460
|
+
ctx.strokeStyle = decorationColor;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
ctx.lineWidth = decorationWidth;
|
|
464
|
+
|
|
465
|
+
ctx.beginPath();
|
|
466
|
+
ctx.moveTo(x, decorationY);
|
|
467
|
+
ctx.lineTo(x + width, decorationY);
|
|
468
|
+
ctx.stroke();
|
|
469
|
+
|
|
470
|
+
ctx.restore();
|
|
471
|
+
};
|
|
402
472
|
|
|
403
473
|
// Underline
|
|
404
474
|
if (textProps.underline) {
|
|
405
475
|
const underlineY = y + fontSize * 0.1;
|
|
406
|
-
|
|
407
|
-
ctx.moveTo(x, underlineY);
|
|
408
|
-
ctx.lineTo(x + width, underlineY);
|
|
409
|
-
ctx.stroke();
|
|
476
|
+
renderDecorationLine(underlineY, textProps.underline, 'underline');
|
|
410
477
|
}
|
|
411
478
|
|
|
412
479
|
// Overline
|
|
413
480
|
if (textProps.overline) {
|
|
414
481
|
const overlineY = y - fontSize * 0.8;
|
|
415
|
-
|
|
416
|
-
ctx.moveTo(x, overlineY);
|
|
417
|
-
ctx.lineTo(x + width, overlineY);
|
|
418
|
-
ctx.stroke();
|
|
482
|
+
renderDecorationLine(overlineY, textProps.overline, 'overline');
|
|
419
483
|
}
|
|
420
484
|
|
|
421
485
|
// Strikethrough
|
|
422
486
|
if (textProps.strikethrough) {
|
|
423
487
|
const strikethroughY = y - fontSize * 0.3;
|
|
424
|
-
|
|
425
|
-
ctx.moveTo(x, strikethroughY);
|
|
426
|
-
ctx.lineTo(x + width, strikethroughY);
|
|
427
|
-
ctx.stroke();
|
|
488
|
+
renderDecorationLine(strikethroughY, textProps.strikethrough, 'strikethrough');
|
|
428
489
|
}
|
|
429
490
|
|
|
430
491
|
ctx.restore();
|
|
@@ -475,4 +536,181 @@ export class EnhancedTextRenderer {
|
|
|
475
536
|
|
|
476
537
|
return gradient;
|
|
477
538
|
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Applies stroke style to text context
|
|
542
|
+
* @param ctx - Canvas 2D context
|
|
543
|
+
* @param style - Stroke style type
|
|
544
|
+
* @param width - Stroke width for calculating dash patterns
|
|
545
|
+
*/
|
|
546
|
+
private static applyTextStrokeStyle(
|
|
547
|
+
ctx: SKRSContext2D,
|
|
548
|
+
style: 'solid' | 'dashed' | 'dotted' | 'groove' | 'ridge' | 'double',
|
|
549
|
+
width: number
|
|
550
|
+
): void {
|
|
551
|
+
switch (style) {
|
|
552
|
+
case 'solid':
|
|
553
|
+
ctx.setLineDash([]);
|
|
554
|
+
ctx.lineCap = 'butt';
|
|
555
|
+
ctx.lineJoin = 'miter';
|
|
556
|
+
break;
|
|
557
|
+
|
|
558
|
+
case 'dashed':
|
|
559
|
+
ctx.setLineDash([width * 3, width * 2]);
|
|
560
|
+
ctx.lineCap = 'butt';
|
|
561
|
+
ctx.lineJoin = 'miter';
|
|
562
|
+
break;
|
|
563
|
+
|
|
564
|
+
case 'dotted':
|
|
565
|
+
ctx.setLineDash([width, width]);
|
|
566
|
+
ctx.lineCap = 'round';
|
|
567
|
+
ctx.lineJoin = 'round';
|
|
568
|
+
break;
|
|
569
|
+
|
|
570
|
+
case 'groove':
|
|
571
|
+
case 'ridge':
|
|
572
|
+
case 'double':
|
|
573
|
+
ctx.setLineDash([]);
|
|
574
|
+
ctx.lineCap = 'butt';
|
|
575
|
+
ctx.lineJoin = 'miter';
|
|
576
|
+
break;
|
|
577
|
+
|
|
578
|
+
default:
|
|
579
|
+
ctx.setLineDash([]);
|
|
580
|
+
ctx.lineCap = 'butt';
|
|
581
|
+
ctx.lineJoin = 'miter';
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Renders complex text stroke styles that require multiple passes
|
|
588
|
+
* @param ctx - Canvas 2D context
|
|
589
|
+
* @param text - Text to render
|
|
590
|
+
* @param x - X position
|
|
591
|
+
* @param y - Y position
|
|
592
|
+
* @param style - Complex stroke style type
|
|
593
|
+
* @param width - Stroke width
|
|
594
|
+
* @param color - Base stroke color
|
|
595
|
+
* @param gradient - Optional gradient
|
|
596
|
+
*/
|
|
597
|
+
private static renderComplexTextStroke(
|
|
598
|
+
ctx: SKRSContext2D,
|
|
599
|
+
text: string,
|
|
600
|
+
x: number,
|
|
601
|
+
y: number,
|
|
602
|
+
style: 'groove' | 'ridge' | 'double',
|
|
603
|
+
width: number,
|
|
604
|
+
color?: string,
|
|
605
|
+
gradient?: gradient
|
|
606
|
+
): void {
|
|
607
|
+
const halfWidth = width / 2;
|
|
608
|
+
const textWidth = ctx.measureText(text).width;
|
|
609
|
+
|
|
610
|
+
switch (style) {
|
|
611
|
+
case 'groove':
|
|
612
|
+
// Groove: dark outer, light inner
|
|
613
|
+
ctx.lineWidth = halfWidth;
|
|
614
|
+
|
|
615
|
+
// Outer dark stroke
|
|
616
|
+
if (gradient) {
|
|
617
|
+
ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
|
|
618
|
+
} else {
|
|
619
|
+
ctx.strokeStyle = this.darkenColor(color || '#000000', 0.3);
|
|
620
|
+
}
|
|
621
|
+
ctx.strokeText(text, x, y);
|
|
622
|
+
|
|
623
|
+
// Inner light stroke
|
|
624
|
+
ctx.lineWidth = halfWidth;
|
|
625
|
+
if (gradient) {
|
|
626
|
+
ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
|
|
627
|
+
} else {
|
|
628
|
+
ctx.strokeStyle = this.lightenColor(color || '#000000', 0.3);
|
|
629
|
+
}
|
|
630
|
+
ctx.strokeText(text, x, y);
|
|
631
|
+
break;
|
|
632
|
+
|
|
633
|
+
case 'ridge':
|
|
634
|
+
// Ridge: light outer, dark inner
|
|
635
|
+
ctx.lineWidth = halfWidth;
|
|
636
|
+
|
|
637
|
+
// Outer light stroke
|
|
638
|
+
if (gradient) {
|
|
639
|
+
ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
|
|
640
|
+
} else {
|
|
641
|
+
ctx.strokeStyle = this.lightenColor(color || '#000000', 0.3);
|
|
642
|
+
}
|
|
643
|
+
ctx.strokeText(text, x, y);
|
|
644
|
+
|
|
645
|
+
// Inner dark stroke
|
|
646
|
+
ctx.lineWidth = halfWidth;
|
|
647
|
+
if (gradient) {
|
|
648
|
+
ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
|
|
649
|
+
} else {
|
|
650
|
+
ctx.strokeStyle = this.darkenColor(color || '#000000', 0.3);
|
|
651
|
+
}
|
|
652
|
+
ctx.strokeText(text, x, y);
|
|
653
|
+
break;
|
|
654
|
+
|
|
655
|
+
case 'double':
|
|
656
|
+
// Double: two parallel strokes
|
|
657
|
+
ctx.lineWidth = halfWidth;
|
|
658
|
+
|
|
659
|
+
// First stroke (outer)
|
|
660
|
+
if (gradient) {
|
|
661
|
+
ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
|
|
662
|
+
} else {
|
|
663
|
+
ctx.strokeStyle = color || '#000000';
|
|
664
|
+
}
|
|
665
|
+
ctx.strokeText(text, x, y);
|
|
666
|
+
|
|
667
|
+
// Second stroke (inner)
|
|
668
|
+
ctx.lineWidth = halfWidth;
|
|
669
|
+
if (gradient) {
|
|
670
|
+
ctx.strokeStyle = this.createGradient(ctx, gradient, x, y, x + textWidth, y);
|
|
671
|
+
} else {
|
|
672
|
+
ctx.strokeStyle = color || '#000000';
|
|
673
|
+
}
|
|
674
|
+
ctx.strokeText(text, x, y);
|
|
675
|
+
break;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Darkens a color by a factor
|
|
681
|
+
* @param color - Color string
|
|
682
|
+
* @param factor - Darkening factor (0-1)
|
|
683
|
+
* @returns Darkened color string
|
|
684
|
+
*/
|
|
685
|
+
private static darkenColor(color: string, factor: number): string {
|
|
686
|
+
// Simple darkening for hex colors
|
|
687
|
+
if (color.startsWith('#')) {
|
|
688
|
+
const hex = color.slice(1);
|
|
689
|
+
const num = parseInt(hex, 16);
|
|
690
|
+
const r = Math.max(0, Math.floor((num >> 16) * (1 - factor)));
|
|
691
|
+
const g = Math.max(0, Math.floor(((num >> 8) & 0x00FF) * (1 - factor)));
|
|
692
|
+
const b = Math.max(0, Math.floor((num & 0x0000FF) * (1 - factor)));
|
|
693
|
+
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
|
|
694
|
+
}
|
|
695
|
+
return color; // Return original for non-hex colors
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Lightens a color by a factor
|
|
700
|
+
* @param color - Color string
|
|
701
|
+
* @param factor - Lightening factor (0-1)
|
|
702
|
+
* @returns Lightened color string
|
|
703
|
+
*/
|
|
704
|
+
private static lightenColor(color: string, factor: number): string {
|
|
705
|
+
// Simple lightening for hex colors
|
|
706
|
+
if (color.startsWith('#')) {
|
|
707
|
+
const hex = color.slice(1);
|
|
708
|
+
const num = parseInt(hex, 16);
|
|
709
|
+
const r = Math.min(255, Math.floor((num >> 16) + (255 - (num >> 16)) * factor));
|
|
710
|
+
const g = Math.min(255, Math.floor(((num >> 8) & 0x00FF) + (255 - ((num >> 8) & 0x00FF)) * factor));
|
|
711
|
+
const b = Math.min(255, Math.floor((num & 0x0000FF) + (255 - (num & 0x0000FF)) * factor));
|
|
712
|
+
return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
|
|
713
|
+
}
|
|
714
|
+
return color; // Return original for non-hex colors
|
|
715
|
+
}
|
|
478
716
|
}
|