apexify.js 5.1.1 → 5.2.1
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/CHANGELOG.md +240 -0
- package/README.md +244 -1101
- package/dist/cjs/Canvas/ApexPainter.d.ts +183 -204
- package/dist/cjs/Canvas/ApexPainter.d.ts.map +1 -1
- package/dist/cjs/Canvas/ApexPainter.js +524 -1282
- package/dist/cjs/Canvas/ApexPainter.js.map +1 -1
- package/dist/cjs/Canvas/extended/CanvasCreator.d.ts +33 -0
- package/dist/cjs/Canvas/extended/CanvasCreator.d.ts.map +1 -0
- package/dist/cjs/Canvas/extended/CanvasCreator.js +223 -0
- package/dist/cjs/Canvas/extended/CanvasCreator.js.map +1 -0
- package/dist/cjs/Canvas/extended/ChartCreator.d.ts +26 -0
- package/dist/cjs/Canvas/extended/ChartCreator.d.ts.map +1 -0
- package/dist/cjs/Canvas/extended/ChartCreator.js +50 -0
- package/dist/cjs/Canvas/extended/ChartCreator.js.map +1 -0
- package/dist/cjs/Canvas/extended/GIFCreator.d.ts +43 -0
- package/dist/cjs/Canvas/extended/GIFCreator.d.ts.map +1 -0
- package/dist/cjs/Canvas/extended/GIFCreator.js +157 -0
- package/dist/cjs/Canvas/extended/GIFCreator.js.map +1 -0
- package/dist/cjs/Canvas/extended/ImageCreator.d.ts +83 -0
- package/dist/cjs/Canvas/extended/ImageCreator.d.ts.map +1 -0
- package/dist/cjs/Canvas/extended/ImageCreator.js +479 -0
- package/dist/cjs/Canvas/extended/ImageCreator.js.map +1 -0
- package/dist/cjs/Canvas/extended/TextCreator.d.ts +35 -0
- package/dist/cjs/Canvas/extended/TextCreator.d.ts.map +1 -0
- package/dist/cjs/Canvas/extended/TextCreator.js +98 -0
- package/dist/cjs/Canvas/extended/TextCreator.js.map +1 -0
- package/dist/cjs/Canvas/extended/VideoCreator.d.ts +370 -0
- package/dist/cjs/Canvas/extended/VideoCreator.d.ts.map +1 -0
- package/dist/cjs/Canvas/extended/VideoCreator.js +478 -0
- package/dist/cjs/Canvas/extended/VideoCreator.js.map +1 -0
- package/dist/cjs/Canvas/utils/Background/bg.d.ts +1 -1
- package/dist/cjs/Canvas/utils/Background/bg.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Background/bg.js +43 -7
- package/dist/cjs/Canvas/utils/Background/bg.js.map +1 -1
- package/dist/cjs/Canvas/utils/Charts/barchart.d.ts +230 -0
- package/dist/cjs/Canvas/utils/Charts/barchart.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/barchart.js +1891 -0
- package/dist/cjs/Canvas/utils/Charts/barchart.js.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/comparisonchart.d.ts +103 -0
- package/dist/cjs/Canvas/utils/Charts/comparisonchart.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/comparisonchart.js +368 -0
- package/dist/cjs/Canvas/utils/Charts/comparisonchart.js.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.d.ts +181 -0
- package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.js +1389 -0
- package/dist/cjs/Canvas/utils/Charts/horizontalbarchart.js.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/index.d.ts +45 -0
- package/dist/cjs/Canvas/utils/Charts/index.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/index.js +17 -0
- package/dist/cjs/Canvas/utils/Charts/index.js.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/linechart.d.ts +216 -0
- package/dist/cjs/Canvas/utils/Charts/linechart.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/linechart.js +1761 -0
- package/dist/cjs/Canvas/utils/Charts/linechart.js.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/piechart.d.ts +167 -0
- package/dist/cjs/Canvas/utils/Charts/piechart.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Charts/piechart.js +794 -0
- package/dist/cjs/Canvas/utils/Charts/piechart.js.map +1 -0
- package/dist/cjs/Canvas/utils/General/batchOperations.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/General/batchOperations.js +3 -4
- package/dist/cjs/Canvas/utils/General/batchOperations.js.map +1 -1
- package/dist/cjs/Canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/General/general functions.js +62 -33
- package/dist/cjs/Canvas/utils/General/general functions.js.map +1 -1
- package/dist/cjs/Canvas/utils/General/imageStitching.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/General/imageStitching.js +3 -6
- package/dist/cjs/Canvas/utils/General/imageStitching.js.map +1 -1
- package/dist/cjs/Canvas/utils/Image/imageMasking.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Image/imageMasking.js +5 -12
- package/dist/cjs/Canvas/utils/Image/imageMasking.js.map +1 -1
- package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts +4 -4
- package/dist/cjs/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Image/imageProperties.js +44 -9
- package/dist/cjs/Canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts +5 -0
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js +48 -5
- package/dist/cjs/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/textProperties.d.ts +1 -1
- package/dist/cjs/Canvas/utils/Texts/textProperties.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/Texts/textProperties.js +48 -5
- package/dist/cjs/Canvas/utils/Texts/textProperties.js.map +1 -1
- package/dist/cjs/Canvas/utils/Video/videoHelpers.d.ts +489 -0
- package/dist/cjs/Canvas/utils/Video/videoHelpers.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/Video/videoHelpers.js +1835 -0
- package/dist/cjs/Canvas/utils/Video/videoHelpers.js.map +1 -0
- package/dist/cjs/Canvas/utils/errorUtils.d.ts +15 -0
- package/dist/cjs/Canvas/utils/errorUtils.d.ts.map +1 -0
- package/dist/cjs/Canvas/utils/errorUtils.js +26 -0
- package/dist/cjs/Canvas/utils/errorUtils.js.map +1 -0
- package/dist/cjs/Canvas/utils/types.d.ts +17 -178
- 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 +4 -3
- package/dist/cjs/Canvas/utils/utils.d.ts.map +1 -1
- package/dist/cjs/Canvas/utils/utils.js +40 -6
- package/dist/cjs/Canvas/utils/utils.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -8
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +14 -45
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/Canvas/ApexPainter.d.ts +183 -204
- package/dist/esm/Canvas/ApexPainter.d.ts.map +1 -1
- package/dist/esm/Canvas/ApexPainter.js +524 -1282
- package/dist/esm/Canvas/ApexPainter.js.map +1 -1
- package/dist/esm/Canvas/extended/CanvasCreator.d.ts +33 -0
- package/dist/esm/Canvas/extended/CanvasCreator.d.ts.map +1 -0
- package/dist/esm/Canvas/extended/CanvasCreator.js +223 -0
- package/dist/esm/Canvas/extended/CanvasCreator.js.map +1 -0
- package/dist/esm/Canvas/extended/ChartCreator.d.ts +26 -0
- package/dist/esm/Canvas/extended/ChartCreator.d.ts.map +1 -0
- package/dist/esm/Canvas/extended/ChartCreator.js +50 -0
- package/dist/esm/Canvas/extended/ChartCreator.js.map +1 -0
- package/dist/esm/Canvas/extended/GIFCreator.d.ts +43 -0
- package/dist/esm/Canvas/extended/GIFCreator.d.ts.map +1 -0
- package/dist/esm/Canvas/extended/GIFCreator.js +157 -0
- package/dist/esm/Canvas/extended/GIFCreator.js.map +1 -0
- package/dist/esm/Canvas/extended/ImageCreator.d.ts +83 -0
- package/dist/esm/Canvas/extended/ImageCreator.d.ts.map +1 -0
- package/dist/esm/Canvas/extended/ImageCreator.js +479 -0
- package/dist/esm/Canvas/extended/ImageCreator.js.map +1 -0
- package/dist/esm/Canvas/extended/TextCreator.d.ts +35 -0
- package/dist/esm/Canvas/extended/TextCreator.d.ts.map +1 -0
- package/dist/esm/Canvas/extended/TextCreator.js +98 -0
- package/dist/esm/Canvas/extended/TextCreator.js.map +1 -0
- package/dist/esm/Canvas/extended/VideoCreator.d.ts +370 -0
- package/dist/esm/Canvas/extended/VideoCreator.d.ts.map +1 -0
- package/dist/esm/Canvas/extended/VideoCreator.js +478 -0
- package/dist/esm/Canvas/extended/VideoCreator.js.map +1 -0
- package/dist/esm/Canvas/utils/Background/bg.d.ts +1 -1
- package/dist/esm/Canvas/utils/Background/bg.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Background/bg.js +43 -7
- package/dist/esm/Canvas/utils/Background/bg.js.map +1 -1
- package/dist/esm/Canvas/utils/Charts/barchart.d.ts +230 -0
- package/dist/esm/Canvas/utils/Charts/barchart.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Charts/barchart.js +1891 -0
- package/dist/esm/Canvas/utils/Charts/barchart.js.map +1 -0
- package/dist/esm/Canvas/utils/Charts/comparisonchart.d.ts +103 -0
- package/dist/esm/Canvas/utils/Charts/comparisonchart.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Charts/comparisonchart.js +368 -0
- package/dist/esm/Canvas/utils/Charts/comparisonchart.js.map +1 -0
- package/dist/esm/Canvas/utils/Charts/horizontalbarchart.d.ts +181 -0
- package/dist/esm/Canvas/utils/Charts/horizontalbarchart.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Charts/horizontalbarchart.js +1389 -0
- package/dist/esm/Canvas/utils/Charts/horizontalbarchart.js.map +1 -0
- package/dist/esm/Canvas/utils/Charts/index.d.ts +45 -0
- package/dist/esm/Canvas/utils/Charts/index.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Charts/index.js +17 -0
- package/dist/esm/Canvas/utils/Charts/index.js.map +1 -0
- package/dist/esm/Canvas/utils/Charts/linechart.d.ts +216 -0
- package/dist/esm/Canvas/utils/Charts/linechart.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Charts/linechart.js +1761 -0
- package/dist/esm/Canvas/utils/Charts/linechart.js.map +1 -0
- package/dist/esm/Canvas/utils/Charts/piechart.d.ts +167 -0
- package/dist/esm/Canvas/utils/Charts/piechart.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Charts/piechart.js +794 -0
- package/dist/esm/Canvas/utils/Charts/piechart.js.map +1 -0
- package/dist/esm/Canvas/utils/General/batchOperations.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/General/batchOperations.js +3 -4
- package/dist/esm/Canvas/utils/General/batchOperations.js.map +1 -1
- package/dist/esm/Canvas/utils/General/general functions.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/General/general functions.js +62 -33
- package/dist/esm/Canvas/utils/General/general functions.js.map +1 -1
- package/dist/esm/Canvas/utils/General/imageStitching.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/General/imageStitching.js +3 -6
- package/dist/esm/Canvas/utils/General/imageStitching.js.map +1 -1
- package/dist/esm/Canvas/utils/Image/imageMasking.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Image/imageMasking.js +5 -12
- package/dist/esm/Canvas/utils/Image/imageMasking.js.map +1 -1
- package/dist/esm/Canvas/utils/Image/imageProperties.d.ts +4 -4
- package/dist/esm/Canvas/utils/Image/imageProperties.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Image/imageProperties.js +44 -9
- package/dist/esm/Canvas/utils/Image/imageProperties.js.map +1 -1
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts +5 -0
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js +48 -5
- package/dist/esm/Canvas/utils/Texts/enhancedTextRenderer.js.map +1 -1
- package/dist/esm/Canvas/utils/Texts/textProperties.d.ts +1 -1
- package/dist/esm/Canvas/utils/Texts/textProperties.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/Texts/textProperties.js +48 -5
- package/dist/esm/Canvas/utils/Texts/textProperties.js.map +1 -1
- package/dist/esm/Canvas/utils/Video/videoHelpers.d.ts +489 -0
- package/dist/esm/Canvas/utils/Video/videoHelpers.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/Video/videoHelpers.js +1835 -0
- package/dist/esm/Canvas/utils/Video/videoHelpers.js.map +1 -0
- package/dist/esm/Canvas/utils/errorUtils.d.ts +15 -0
- package/dist/esm/Canvas/utils/errorUtils.d.ts.map +1 -0
- package/dist/esm/Canvas/utils/errorUtils.js +26 -0
- package/dist/esm/Canvas/utils/errorUtils.js.map +1 -0
- package/dist/esm/Canvas/utils/types.d.ts +17 -178
- 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 +4 -3
- package/dist/esm/Canvas/utils/utils.d.ts.map +1 -1
- package/dist/esm/Canvas/utils/utils.js +40 -6
- package/dist/esm/Canvas/utils/utils.js.map +1 -1
- package/dist/esm/index.d.ts +1 -8
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +14 -45
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +235 -198
- package/dist/cjs/Canvas/utils/Charts/charts.d.ts +0 -13
- package/dist/cjs/Canvas/utils/Charts/charts.d.ts.map +0 -1
- package/dist/cjs/Canvas/utils/Charts/charts.js +0 -466
- package/dist/cjs/Canvas/utils/Charts/charts.js.map +0 -1
- package/dist/esm/Canvas/utils/Charts/charts.d.ts +0 -13
- package/dist/esm/Canvas/utils/Charts/charts.d.ts.map +0 -1
- package/dist/esm/Canvas/utils/Charts/charts.js +0 -466
- package/dist/esm/Canvas/utils/Charts/charts.js.map +0 -1
- package/lib/Canvas/ApexPainter.ts +0 -5414
- package/lib/Canvas/utils/Background/bg.ts +0 -285
- package/lib/Canvas/utils/Charts/charts.ts +0 -548
- package/lib/Canvas/utils/Custom/advancedLines.ts +0 -387
- package/lib/Canvas/utils/Custom/customLines.ts +0 -206
- package/lib/Canvas/utils/General/batchOperations.ts +0 -103
- package/lib/Canvas/utils/General/conversion.ts +0 -34
- package/lib/Canvas/utils/General/general functions.ts +0 -726
- package/lib/Canvas/utils/General/imageCompression.ts +0 -316
- package/lib/Canvas/utils/General/imageStitching.ts +0 -252
- package/lib/Canvas/utils/Image/imageEffects.ts +0 -175
- package/lib/Canvas/utils/Image/imageFilters.ts +0 -356
- package/lib/Canvas/utils/Image/imageMasking.ts +0 -335
- package/lib/Canvas/utils/Image/imageProperties.ts +0 -587
- package/lib/Canvas/utils/Image/professionalImageFilters.ts +0 -391
- package/lib/Canvas/utils/Image/simpleProfessionalFilters.ts +0 -229
- package/lib/Canvas/utils/Patterns/enhancedPatternRenderer.ts +0 -455
- package/lib/Canvas/utils/Shapes/shapes.ts +0 -528
- package/lib/Canvas/utils/Texts/enhancedTextRenderer.ts +0 -716
- package/lib/Canvas/utils/Texts/textPathRenderer.ts +0 -320
- package/lib/Canvas/utils/Texts/textProperties.ts +0 -231
- package/lib/Canvas/utils/types.ts +0 -983
- package/lib/Canvas/utils/utils.ts +0 -135
- package/lib/index.ts +0 -81
- package/lib/utils.ts +0 -5
|
@@ -1,716 +0,0 @@
|
|
|
1
|
-
import { SKRSContext2D } from '@napi-rs/canvas';
|
|
2
|
-
import { TextProperties, gradient } from '../types';
|
|
3
|
-
import { GlobalFonts } from '@napi-rs/canvas';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Enhanced text renderer with comprehensive styling options
|
|
8
|
-
*/
|
|
9
|
-
export class EnhancedTextRenderer {
|
|
10
|
-
/**
|
|
11
|
-
* Renders text with all enhanced features
|
|
12
|
-
* @param ctx - Canvas 2D context
|
|
13
|
-
* @param textProps - Text properties configuration
|
|
14
|
-
*/
|
|
15
|
-
static async renderText(ctx: SKRSContext2D, textProps: TextProperties): Promise<void> {
|
|
16
|
-
ctx.save();
|
|
17
|
-
|
|
18
|
-
try {
|
|
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');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// 2. Apply transformations
|
|
28
|
-
this.applyTransformations(ctx, textProps);
|
|
29
|
-
|
|
30
|
-
// 3. Setup font and spacing
|
|
31
|
-
this.setupFont(ctx, textProps);
|
|
32
|
-
|
|
33
|
-
// 4. Apply text alignment
|
|
34
|
-
this.setupAlignment(ctx, textProps);
|
|
35
|
-
|
|
36
|
-
// 5. Handle text wrapping or single line rendering
|
|
37
|
-
if (textProps.maxWidth) {
|
|
38
|
-
await this.renderWrappedText(ctx, textProps);
|
|
39
|
-
} else {
|
|
40
|
-
await this.renderSingleLine(ctx, textProps);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
} finally {
|
|
44
|
-
ctx.restore();
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Registers a custom font from file path
|
|
50
|
-
* @param fontPath - Path to font file
|
|
51
|
-
* @param fontName - Name to register the font as
|
|
52
|
-
*/
|
|
53
|
-
private static async registerCustomFont(fontPath: string, fontName: string): Promise<void> {
|
|
54
|
-
try {
|
|
55
|
-
const fullPath = path.join(process.cwd(), fontPath);
|
|
56
|
-
GlobalFonts.registerFromPath(fullPath, fontName);
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.warn(`Failed to register font from path: ${fontPath}`, error);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Applies transformations (rotation, opacity)
|
|
64
|
-
* @param ctx - Canvas 2D context
|
|
65
|
-
* @param textProps - Text properties
|
|
66
|
-
*/
|
|
67
|
-
private static applyTransformations(ctx: SKRSContext2D, textProps: TextProperties): void {
|
|
68
|
-
// Apply rotation
|
|
69
|
-
if (textProps.rotation && textProps.rotation !== 0) {
|
|
70
|
-
ctx.translate(textProps.x, textProps.y);
|
|
71
|
-
ctx.rotate((textProps.rotation * Math.PI) / 180);
|
|
72
|
-
ctx.translate(-textProps.x, -textProps.y);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Apply global opacity
|
|
76
|
-
if (textProps.opacity !== undefined) {
|
|
77
|
-
ctx.globalAlpha = Math.max(0, Math.min(1, textProps.opacity));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Sets up font properties and spacing
|
|
83
|
-
* @param ctx - Canvas 2D context
|
|
84
|
-
* @param textProps - Text properties
|
|
85
|
-
*/
|
|
86
|
-
private static setupFont(ctx: SKRSContext2D, textProps: TextProperties): void {
|
|
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';
|
|
90
|
-
|
|
91
|
-
// Build font string with decorations
|
|
92
|
-
let fontString = '';
|
|
93
|
-
|
|
94
|
-
if (textProps.bold) fontString += 'bold ';
|
|
95
|
-
if (textProps.italic) fontString += 'italic ';
|
|
96
|
-
|
|
97
|
-
fontString += `${fontSize}px "${fontFamily}"`;
|
|
98
|
-
|
|
99
|
-
ctx.font = fontString;
|
|
100
|
-
|
|
101
|
-
// Apply letter spacing
|
|
102
|
-
if (textProps.letterSpacing !== undefined) {
|
|
103
|
-
ctx.letterSpacing = `${textProps.letterSpacing}px`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Apply word spacing
|
|
107
|
-
if (textProps.wordSpacing !== undefined) {
|
|
108
|
-
ctx.wordSpacing = `${textProps.wordSpacing}px`;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Sets up text alignment
|
|
114
|
-
* @param ctx - Canvas 2D context
|
|
115
|
-
* @param textProps - Text properties
|
|
116
|
-
*/
|
|
117
|
-
private static setupAlignment(ctx: SKRSContext2D, textProps: TextProperties): void {
|
|
118
|
-
ctx.textAlign = textProps.textAlign || 'left';
|
|
119
|
-
ctx.textBaseline = textProps.textBaseline || 'alphabetic';
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Renders wrapped text with all effects
|
|
124
|
-
* @param ctx - Canvas 2D context
|
|
125
|
-
* @param textProps - Text properties
|
|
126
|
-
*/
|
|
127
|
-
private static async renderWrappedText(ctx: SKRSContext2D, textProps: TextProperties): Promise<void> {
|
|
128
|
-
const fontSize = textProps.font?.size || textProps.fontSize || 16;
|
|
129
|
-
const lineHeight = (textProps.lineHeight || 1.4) * fontSize;
|
|
130
|
-
const maxHeight = textProps.maxHeight;
|
|
131
|
-
const maxLines = maxHeight ? Math.floor(maxHeight / lineHeight) : Infinity;
|
|
132
|
-
|
|
133
|
-
// Split text into words and wrap
|
|
134
|
-
const words = textProps.text.split(' ');
|
|
135
|
-
const lines: string[] = [];
|
|
136
|
-
let currentLine = '';
|
|
137
|
-
|
|
138
|
-
for (const word of words) {
|
|
139
|
-
const testLine = currentLine ? currentLine + ' ' + word : word;
|
|
140
|
-
const testWidth = ctx.measureText(testLine).width;
|
|
141
|
-
|
|
142
|
-
if (testWidth > (textProps.maxWidth || Infinity) && currentLine) {
|
|
143
|
-
lines.push(currentLine);
|
|
144
|
-
currentLine = word;
|
|
145
|
-
|
|
146
|
-
if (lines.length >= maxLines) {
|
|
147
|
-
currentLine = '...';
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
151
|
-
currentLine = testLine;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (currentLine && lines.length < maxLines) {
|
|
156
|
-
lines.push(currentLine);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Render each line
|
|
160
|
-
for (let i = 0; i < lines.length; i++) {
|
|
161
|
-
const y = textProps.y + (i * lineHeight);
|
|
162
|
-
await this.renderTextLine(ctx, lines[i], textProps.x, y, textProps);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Renders single line text with all effects
|
|
168
|
-
* @param ctx - Canvas 2D context
|
|
169
|
-
* @param textProps - Text properties
|
|
170
|
-
*/
|
|
171
|
-
private static async renderSingleLine(ctx: SKRSContext2D, textProps: TextProperties): Promise<void> {
|
|
172
|
-
await this.renderTextLine(ctx, textProps.text, textProps.x, textProps.y, textProps);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Renders a single line of text with all effects applied
|
|
177
|
-
* @param ctx - Canvas 2D context
|
|
178
|
-
* @param text - Text to render
|
|
179
|
-
* @param x - X position
|
|
180
|
-
* @param y - Y position
|
|
181
|
-
* @param textProps - Text properties
|
|
182
|
-
*/
|
|
183
|
-
private static async renderTextLine(
|
|
184
|
-
ctx: SKRSContext2D,
|
|
185
|
-
text: string,
|
|
186
|
-
x: number,
|
|
187
|
-
y: number,
|
|
188
|
-
textProps: TextProperties
|
|
189
|
-
): Promise<void> {
|
|
190
|
-
// Calculate text dimensions
|
|
191
|
-
const metrics = ctx.measureText(text);
|
|
192
|
-
const textWidth = metrics.width;
|
|
193
|
-
const fontSize = textProps.font?.size || textProps.fontSize || 16;
|
|
194
|
-
const textHeight = fontSize;
|
|
195
|
-
|
|
196
|
-
// Apply highlight background
|
|
197
|
-
if (textProps.highlight) {
|
|
198
|
-
this.renderHighlight(ctx, x, y, textWidth, textHeight, textProps.highlight);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Apply glow effect
|
|
202
|
-
if (textProps.glow) {
|
|
203
|
-
this.renderGlow(ctx, text, x, y, textProps.glow);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Apply shadow effect
|
|
207
|
-
if (textProps.shadow) {
|
|
208
|
-
this.renderShadow(ctx, text, x, y, textProps.shadow);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Apply stroke
|
|
212
|
-
if (textProps.stroke) {
|
|
213
|
-
this.renderStroke(ctx, text, x, y, textProps.stroke);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Apply fill
|
|
217
|
-
this.renderFill(ctx, text, x, y, textProps);
|
|
218
|
-
|
|
219
|
-
// Apply text decorations
|
|
220
|
-
this.renderDecorations(ctx, text, x, y, textWidth, textHeight, textProps);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Renders highlight background
|
|
225
|
-
* @param ctx - Canvas 2D context
|
|
226
|
-
* @param x - X position
|
|
227
|
-
* @param y - Y position
|
|
228
|
-
* @param width - Text width
|
|
229
|
-
* @param height - Text height
|
|
230
|
-
* @param highlight - Highlight options
|
|
231
|
-
*/
|
|
232
|
-
private static renderHighlight(
|
|
233
|
-
ctx: SKRSContext2D,
|
|
234
|
-
x: number,
|
|
235
|
-
y: number,
|
|
236
|
-
width: number,
|
|
237
|
-
height: number,
|
|
238
|
-
highlight: { color?: string; gradient?: gradient; opacity?: number }
|
|
239
|
-
): void {
|
|
240
|
-
ctx.save();
|
|
241
|
-
|
|
242
|
-
const opacity = highlight.opacity !== undefined ? highlight.opacity : 0.3;
|
|
243
|
-
ctx.globalAlpha = opacity;
|
|
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
|
-
}
|
|
251
|
-
|
|
252
|
-
// Adjust highlight position based on text baseline
|
|
253
|
-
const highlightY = y - height * 0.8; // Adjust for different baselines
|
|
254
|
-
ctx.fillRect(x, highlightY, width, height);
|
|
255
|
-
|
|
256
|
-
ctx.restore();
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Renders glow effect
|
|
261
|
-
* @param ctx - Canvas 2D context
|
|
262
|
-
* @param text - Text to render
|
|
263
|
-
* @param x - X position
|
|
264
|
-
* @param y - Y position
|
|
265
|
-
* @param glow - Glow options
|
|
266
|
-
*/
|
|
267
|
-
private static renderGlow(
|
|
268
|
-
ctx: SKRSContext2D,
|
|
269
|
-
text: string,
|
|
270
|
-
x: number,
|
|
271
|
-
y: number,
|
|
272
|
-
glow: { color?: string; gradient?: gradient; intensity?: number; opacity?: number }
|
|
273
|
-
): void {
|
|
274
|
-
ctx.save();
|
|
275
|
-
|
|
276
|
-
const intensity = glow.intensity || 10;
|
|
277
|
-
const opacity = glow.opacity !== undefined ? glow.opacity : 0.8;
|
|
278
|
-
|
|
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
|
-
}
|
|
299
|
-
|
|
300
|
-
ctx.restore();
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Renders shadow effect
|
|
305
|
-
* @param ctx - Canvas 2D context
|
|
306
|
-
* @param text - Text to render
|
|
307
|
-
* @param x - X position
|
|
308
|
-
* @param y - Y position
|
|
309
|
-
* @param shadow - Shadow options
|
|
310
|
-
*/
|
|
311
|
-
private static renderShadow(
|
|
312
|
-
ctx: SKRSContext2D,
|
|
313
|
-
text: string,
|
|
314
|
-
x: number,
|
|
315
|
-
y: number,
|
|
316
|
-
shadow: { color?: string; offsetX?: number; offsetY?: number; blur?: number; opacity?: number }
|
|
317
|
-
): void {
|
|
318
|
-
ctx.save();
|
|
319
|
-
|
|
320
|
-
ctx.shadowColor = shadow.color || 'rgba(0, 0, 0, 0.5)';
|
|
321
|
-
ctx.shadowOffsetX = shadow.offsetX || 2;
|
|
322
|
-
ctx.shadowOffsetY = shadow.offsetY || 2;
|
|
323
|
-
ctx.shadowBlur = shadow.blur || 4;
|
|
324
|
-
|
|
325
|
-
if (shadow.opacity !== undefined) {
|
|
326
|
-
ctx.globalAlpha = shadow.opacity;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
ctx.fillText(text, x, y);
|
|
330
|
-
|
|
331
|
-
ctx.restore();
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Renders stroke/outline
|
|
336
|
-
* @param ctx - Canvas 2D context
|
|
337
|
-
* @param text - Text to render
|
|
338
|
-
* @param x - X position
|
|
339
|
-
* @param y - Y position
|
|
340
|
-
* @param stroke - Stroke options
|
|
341
|
-
*/
|
|
342
|
-
private static renderStroke(
|
|
343
|
-
ctx: SKRSContext2D,
|
|
344
|
-
text: string,
|
|
345
|
-
x: number,
|
|
346
|
-
y: number,
|
|
347
|
-
stroke: { color?: string; width?: number; gradient?: gradient; opacity?: number; style?: 'solid' | 'dashed' | 'dotted' | 'groove' | 'ridge' | 'double' }
|
|
348
|
-
): void {
|
|
349
|
-
ctx.save();
|
|
350
|
-
|
|
351
|
-
const strokeWidth = stroke.width || 1;
|
|
352
|
-
const strokeStyle = stroke.style || 'solid';
|
|
353
|
-
|
|
354
|
-
ctx.lineWidth = strokeWidth;
|
|
355
|
-
|
|
356
|
-
if (stroke.gradient) {
|
|
357
|
-
ctx.strokeStyle = this.createGradient(ctx, stroke.gradient, x, y, x + ctx.measureText(text).width, y);
|
|
358
|
-
} else {
|
|
359
|
-
ctx.strokeStyle = stroke.color || '#000000';
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (stroke.opacity !== undefined) {
|
|
363
|
-
ctx.globalAlpha = stroke.opacity;
|
|
364
|
-
}
|
|
365
|
-
|
|
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
|
-
}
|
|
375
|
-
|
|
376
|
-
ctx.restore();
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Renders text fill
|
|
381
|
-
* @param ctx - Canvas 2D context
|
|
382
|
-
* @param text - Text to render
|
|
383
|
-
* @param x - X position
|
|
384
|
-
* @param y - Y position
|
|
385
|
-
* @param textProps - Text properties
|
|
386
|
-
*/
|
|
387
|
-
private static renderFill(
|
|
388
|
-
ctx: SKRSContext2D,
|
|
389
|
-
text: string,
|
|
390
|
-
x: number,
|
|
391
|
-
y: number,
|
|
392
|
-
textProps: TextProperties
|
|
393
|
-
): void {
|
|
394
|
-
ctx.save();
|
|
395
|
-
|
|
396
|
-
if (textProps.gradient) {
|
|
397
|
-
ctx.fillStyle = this.createGradient(ctx, textProps.gradient, x, y, x + ctx.measureText(text).width, y);
|
|
398
|
-
} else {
|
|
399
|
-
ctx.fillStyle = textProps.color || '#000000';
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
ctx.fillText(text, x, y);
|
|
403
|
-
|
|
404
|
-
ctx.restore();
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Renders text decorations (underline, overline, strikethrough)
|
|
409
|
-
* @param ctx - Canvas 2D context
|
|
410
|
-
* @param text - Text to render
|
|
411
|
-
* @param x - X position
|
|
412
|
-
* @param y - Y position
|
|
413
|
-
* @param width - Text width
|
|
414
|
-
* @param height - Text height
|
|
415
|
-
* @param textProps - Text properties
|
|
416
|
-
*/
|
|
417
|
-
private static renderDecorations(
|
|
418
|
-
ctx: SKRSContext2D,
|
|
419
|
-
text: string,
|
|
420
|
-
x: number,
|
|
421
|
-
y: number,
|
|
422
|
-
width: number,
|
|
423
|
-
height: number,
|
|
424
|
-
textProps: TextProperties
|
|
425
|
-
): void {
|
|
426
|
-
const hasDecorations = textProps.underline || textProps.overline || textProps.strikethrough;
|
|
427
|
-
if (!hasDecorations) {
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
ctx.save();
|
|
432
|
-
|
|
433
|
-
const fontSize = textProps.font?.size || textProps.fontSize || 16;
|
|
434
|
-
const defaultColor = textProps.color || '#000000';
|
|
435
|
-
|
|
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
|
-
};
|
|
472
|
-
|
|
473
|
-
// Underline
|
|
474
|
-
if (textProps.underline) {
|
|
475
|
-
const underlineY = y + fontSize * 0.1;
|
|
476
|
-
renderDecorationLine(underlineY, textProps.underline, 'underline');
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// Overline
|
|
480
|
-
if (textProps.overline) {
|
|
481
|
-
const overlineY = y - fontSize * 0.8;
|
|
482
|
-
renderDecorationLine(overlineY, textProps.overline, 'overline');
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Strikethrough
|
|
486
|
-
if (textProps.strikethrough) {
|
|
487
|
-
const strikethroughY = y - fontSize * 0.3;
|
|
488
|
-
renderDecorationLine(strikethroughY, textProps.strikethrough, 'strikethrough');
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
ctx.restore();
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Creates a gradient for text fill or stroke
|
|
496
|
-
* @param ctx - Canvas 2D context
|
|
497
|
-
* @param gradientOptions - Gradient configuration
|
|
498
|
-
* @param startX - Start X position
|
|
499
|
-
* @param startY - Start Y position
|
|
500
|
-
* @param endX - End X position
|
|
501
|
-
* @param endY - End Y position
|
|
502
|
-
* @returns Canvas gradient
|
|
503
|
-
*/
|
|
504
|
-
private static createGradient(
|
|
505
|
-
ctx: SKRSContext2D,
|
|
506
|
-
gradientOptions: gradient,
|
|
507
|
-
startX: number,
|
|
508
|
-
startY: number,
|
|
509
|
-
endX: number,
|
|
510
|
-
endY: number
|
|
511
|
-
): CanvasGradient {
|
|
512
|
-
if (!gradientOptions || !gradientOptions.type || !gradientOptions.colors) {
|
|
513
|
-
throw new Error("Invalid gradient options. Provide a valid object with type and colors properties.");
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
let gradient: CanvasGradient;
|
|
517
|
-
|
|
518
|
-
if (gradientOptions.type === "linear") {
|
|
519
|
-
gradient = ctx.createLinearGradient(startX, startY, endX, endY);
|
|
520
|
-
} else if (gradientOptions.type === "radial") {
|
|
521
|
-
gradient = ctx.createRadialGradient(
|
|
522
|
-
gradientOptions.startX || startX,
|
|
523
|
-
gradientOptions.startY || startY,
|
|
524
|
-
gradientOptions.startRadius || 0,
|
|
525
|
-
gradientOptions.endX || endX,
|
|
526
|
-
gradientOptions.endY || endY,
|
|
527
|
-
gradientOptions.endRadius || 0
|
|
528
|
-
);
|
|
529
|
-
} else {
|
|
530
|
-
throw new Error('Unsupported gradient type. Use "linear" or "radial".');
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
for (const colorStop of gradientOptions.colors) {
|
|
534
|
-
gradient.addColorStop(colorStop.stop, colorStop.color);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
return gradient;
|
|
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
|
-
}
|
|
716
|
-
}
|