@breakside/jskit 2026.10.0 → 2026.26.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/Frameworks/DOM.jsframework/Info.json +2 -2
- package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
- package/Frameworks/FontKit.jsframework/Info.json +2 -2
- package/Frameworks/FontKit.jsframework/JS/FNTOpenTypeFont.js +331 -22
- package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSAttributedString.js +13 -1
- package/Frameworks/Foundation.jsframework/JS/JSContext.js +44 -17
- package/Frameworks/Foundation.jsframework/JS/JSCubicBezier.js +54 -1
- package/Frameworks/Foundation.jsframework/JS/JSFont.js +8 -9
- package/Frameworks/Foundation.jsframework/JS/JSGradient.js +28 -2
- package/Frameworks/Foundation.jsframework/JS/JSImage+HTML.js +27 -1
- package/Frameworks/Foundation.jsframework/JS/JSNodeHTTPClient.js +34 -14
- package/Frameworks/Foundation.jsframework/JS/JSNodeURLSessionDataTask.js +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSNumberFormatter.js +23 -1
- package/Frameworks/Foundation.jsframework/JS/JSPath.js +192 -6
- package/Frameworks/Foundation.jsframework/JS/JSPoint.js +56 -0
- package/Frameworks/Foundation.jsframework/JS/JSTextRun.js +21 -4
- package/Frameworks/Foundation.jsframework/JS/JSTextStorage.js +5 -0
- package/Frameworks/Foundation.jsframework/JS/JSTextTypesetter.js +6 -1
- package/Frameworks/Foundation.jsframework/JS/JSURLRequest.js +3 -0
- package/Frameworks/Foundation.jsframework/JS/JSXMLParser.js +1 -1
- package/Frameworks/Foundation.jsframework/JS/JSZip.js +155 -1
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/sources.json +1 -0
- package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
- package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
- package/Info.json +2 -2
- package/Node/Docs/DocClass.js +38 -1
- package/Node/Docs/DocComponent.js +26 -1
- package/Node/Docs/DocDictionaryProperty.js +8 -0
- package/Node/Docs/DocEnum.js +35 -2
- package/Node/Docs/DocEnumOption.js +3 -0
- package/Node/Docs/DocExtension.js +130 -0
- package/Node/Docs/DocFunction.js +8 -0
- package/Node/Docs/DocMethod.js +3 -0
- package/Node/Docs/DocProperty.js +11 -0
- package/Node/Docs/DocProtocol.js +4 -0
- package/Node/Docs/DocSpec.js +4 -0
- package/Node/Docs/DocSpecProperty.js +8 -0
- package/Node/Docs/DocTopicBasedComponent.js +75 -65
- package/Node/Documentation.js +73 -4
- package/Node/HTMLProjectServer.js +1 -1
- package/Node/Markdown.js +2 -2
- package/Node/io.breakside.jskit-bundle.js +3 -3
- package/Node/jskit +1 -0
- package/Resources/doc-default.css +2 -2
- package/Root/Frameworks/APIKit/Info.yaml +1 -1
- package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/AuthKit/Info.yaml +1 -1
- package/Root/Frameworks/CSSOM/Info.yaml +1 -1
- package/Root/Frameworks/ChartKit/Info.yaml +1 -1
- package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
- package/Root/Frameworks/DBKit/Info.yaml +1 -1
- package/Root/Frameworks/DOM/Info.yaml +1 -1
- package/Root/Frameworks/Dispatch/Info.yaml +1 -1
- package/Root/Frameworks/FontKit/FNTOpenTypeFont.js +331 -22
- package/Root/Frameworks/FontKit/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSAttributedString.js +13 -1
- package/Root/Frameworks/Foundation/JSContext.js +44 -17
- package/Root/Frameworks/Foundation/JSCubicBezier.js +54 -1
- package/Root/Frameworks/Foundation/JSFont.js +8 -9
- package/Root/Frameworks/Foundation/JSGradient.js +28 -2
- package/Root/Frameworks/Foundation/JSImage+HTML.js +27 -1
- package/Root/Frameworks/Foundation/JSNodeHTTPClient.js +34 -14
- package/Root/Frameworks/Foundation/JSNodeURLSessionDataTask.js +2 -2
- package/Root/Frameworks/Foundation/JSNumberFormatter.js +23 -1
- package/Root/Frameworks/Foundation/JSPath.js +192 -6
- package/Root/Frameworks/Foundation/JSPoint.js +56 -0
- package/Root/Frameworks/Foundation/JSTextRun.js +21 -4
- package/Root/Frameworks/Foundation/JSTextStorage.js +5 -0
- package/Root/Frameworks/Foundation/JSTextTypesetter.js +6 -1
- package/Root/Frameworks/Foundation/JSURLRequest.js +3 -0
- package/Root/Frameworks/Foundation/JSXMLParser.js +1 -1
- package/Root/Frameworks/Foundation/JSZip.js +155 -1
- package/Root/Frameworks/ImageKit/IKHTMLCanvasBitmapContext.js +187 -101
- package/Root/Frameworks/ImageKit/IKNodeBitmapContext.js +4 -4
- package/Root/Frameworks/ImageKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
- package/Root/Frameworks/PDFKit/Info.yaml +1 -1
- package/Root/Frameworks/QRKit/Info.yaml +1 -1
- package/Root/Frameworks/SearchKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/TKAssert.js +4 -4
- package/Root/Frameworks/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UIApplication.js +9 -1
- package/Root/Frameworks/UIKit/UICollectionView.js +4 -0
- package/Root/Frameworks/UIKit/UIColorPanel.js +46 -0
- package/Root/Frameworks/UIKit/UIColorWell.js +8 -0
- package/Root/Frameworks/UIKit/UIHTMLDisplayServer.js +21 -2
- package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +150 -69
- package/Root/Frameworks/UIKit/UIHTMLTextRun.js +5 -0
- package/Root/Frameworks/UIKit/UIHTMLTextTypesetter.js +18 -3
- package/Root/Frameworks/UIKit/UIListView.js +7 -5
- package/Root/Frameworks/UIKit/UIMenu.js +50 -32
- package/Root/Frameworks/UIKit/UIMenuItem.js +12 -0
- package/Root/Frameworks/UIKit/UIMenuView.js +27 -5
- package/Root/Frameworks/UIKit/UIPlatform.js +7 -0
- package/Root/Frameworks/UIKit/UIPopupButton.js +7 -1
- package/Root/Frameworks/UIKit/UIResponder.js +8 -0
- package/Root/Frameworks/UIKit/UITextEditor.js +14 -7
- package/Root/Frameworks/UIKit/UITokenField.js +65 -0
- package/Root/Frameworks/UIKit/UIToolbar.js +1 -1
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
|
@@ -77,9 +77,14 @@ JSClass("JSTextTypesetter", JSObject, {
|
|
|
77
77
|
var attributes = this._attributedString.attributesAtIndex(range.location);
|
|
78
78
|
attributes = this.resolveAttributes(attributes);
|
|
79
79
|
var font = attributes.font;
|
|
80
|
+
if (this.useDisplayMetrics){
|
|
81
|
+
return JSTextLine.initWithHeight(font.displayLineHeight, -font.displayDescender, range.location);
|
|
82
|
+
}
|
|
80
83
|
return JSTextLine.initWithHeight(font.lineHeight, -font.descender, range.location);
|
|
81
84
|
},
|
|
82
85
|
|
|
86
|
+
useDisplayMetrics: false,
|
|
87
|
+
|
|
83
88
|
_createLineFromLayout: function(layout){
|
|
84
89
|
// Create runs from the adjusted run descriptors
|
|
85
90
|
var runs = [];
|
|
@@ -88,7 +93,7 @@ JSClass("JSTextTypesetter", JSObject, {
|
|
|
88
93
|
var runDescriptor;
|
|
89
94
|
for (var i = 0, l = layout.runDescriptors.length; i < l; ++i){
|
|
90
95
|
runDescriptor = layout.runDescriptors[i];
|
|
91
|
-
run = JSTextRun.initWithGlyphs(runDescriptor.glyphs, runDescriptor.glyphCharacterLengths, runDescriptor.font, runDescriptor.attributes, JSRange(runDescriptor.location, runDescriptor.length));
|
|
96
|
+
run = JSTextRun.initWithGlyphs(runDescriptor.glyphs, runDescriptor.glyphCharacterLengths, runDescriptor.font, runDescriptor.attributes, JSRange(runDescriptor.location, runDescriptor.length), this.useDisplayMetrics);
|
|
92
97
|
run.origin.x = x;
|
|
93
98
|
x += run.size.width;
|
|
94
99
|
runs.push(run);
|
|
@@ -46,6 +46,9 @@ JSClass("JSURLRequest", JSObject, {
|
|
|
46
46
|
},
|
|
47
47
|
|
|
48
48
|
redirectedRequestToURL: function(url){
|
|
49
|
+
if (!url.isAbsolute){
|
|
50
|
+
url.resolveToBaseURL(this.url);
|
|
51
|
+
}
|
|
49
52
|
var request = JSURLRequest.initWithURL(url);
|
|
50
53
|
request._method = this._method;
|
|
51
54
|
request._headerMap = this._headerMap;
|
|
@@ -475,7 +475,7 @@ JSClass("JSXMLParser", JSObject, {
|
|
|
475
475
|
}
|
|
476
476
|
obj = readObject();
|
|
477
477
|
}
|
|
478
|
-
if (!this.isStopped && this.delegate.xmlParserDidEndDocument){
|
|
478
|
+
if (!this.isStopped && this.delegate && this.delegate.xmlParserDidEndDocument){
|
|
479
479
|
this.delegate.xmlParserDidEndDocument(this);
|
|
480
480
|
}
|
|
481
481
|
}catch (e){
|
|
@@ -11,9 +11,160 @@ JSClass("JSZip", JSObject, {
|
|
|
11
11
|
init: function(){
|
|
12
12
|
this.chunks = [];
|
|
13
13
|
this.directory = [];
|
|
14
|
+
this.directoryIndexByFilename = {};
|
|
14
15
|
this.offset = 0;
|
|
15
16
|
},
|
|
16
17
|
|
|
18
|
+
initWithData: function(data){
|
|
19
|
+
if (data === null || data === undefined){
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
if (data.length < 22){
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
this._data = data;
|
|
26
|
+
this.directory = [];
|
|
27
|
+
this.directoryIndexByFilename = {};
|
|
28
|
+
var offset = this._data.length - 22;
|
|
29
|
+
var minOffset = Math.max(0, offset - 0xFFFF);
|
|
30
|
+
while (offset >= minOffset && !(this._data[offset] === 0x50 && this._data[offset+1] === 0x4b && this._data[offset+2] === 0x05 && this._data[offset+3] === 0x06)){
|
|
31
|
+
offset -= 1;
|
|
32
|
+
}
|
|
33
|
+
if (offset < minOffset){
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
var end = this._data.subdataInRange(JSRange(offset, this._data.length - offset));
|
|
37
|
+
var dataView = end.dataView();
|
|
38
|
+
// End of Central Directory Record (APPNOTE.txt 4.3.16)
|
|
39
|
+
// everything is little-endian
|
|
40
|
+
var signature = dataView.getUint32(0, true);
|
|
41
|
+
if (signature !== 0x06054b50){
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
var diskNumber = dataView.getUint16(4, true);
|
|
45
|
+
var diskNumberWithDirectoryStart = dataView.getUint16(6, true);
|
|
46
|
+
var numberOfItemsOnDisk = dataView.getUint16(8, true);
|
|
47
|
+
var numberOfItemsTotal = dataView.getUint16(10, true);
|
|
48
|
+
var sizeOfDirectory = dataView.getUint32(12, true);
|
|
49
|
+
var offsetOfDirectoryStart = dataView.getUint32(16, true);
|
|
50
|
+
var commentLength = dataView.getUint16(20, true);
|
|
51
|
+
if (diskNumber !== 0 || diskNumberWithDirectoryStart !== 0){
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
if (offsetOfDirectoryStart + sizeOfDirectory > this._data.length){
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
var directory = this._data.subdataInRange(JSRange(offsetOfDirectoryStart, sizeOfDirectory));
|
|
58
|
+
dataView = directory.dataView();
|
|
59
|
+
var crc;
|
|
60
|
+
var compressedLength;
|
|
61
|
+
var uncompressedLength;
|
|
62
|
+
var nameLength;
|
|
63
|
+
var extraFieldLength;
|
|
64
|
+
var name;
|
|
65
|
+
var headerOffset;
|
|
66
|
+
var offset = 0;
|
|
67
|
+
for (var i = 0; i < numberOfItemsTotal; ++i){
|
|
68
|
+
// Central Directory File Header (APPNOTE.txt 4.3.12)
|
|
69
|
+
// Everything is little-endian
|
|
70
|
+
if (offset + 46 > sizeOfDirectory){
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
signature = dataView.getUint32(offset + 0, true);
|
|
74
|
+
if (signature !== 0x02014b50){
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
crc = dataView.getUint32(offset + 16, true);
|
|
78
|
+
compressedLength = dataView.getUint32(offset + 20, true);
|
|
79
|
+
uncompressedLength = dataView.getUint32(offset + 24, true);
|
|
80
|
+
nameLength = dataView.getUint16(offset + 28, true);
|
|
81
|
+
extraFieldLength = dataView.getUint16(offset + 30, true);
|
|
82
|
+
commentLength = dataView.getUint16(offset + 32, true);
|
|
83
|
+
headerOffset = dataView.getUint32(offset + 42, true);
|
|
84
|
+
if (offset + 46 + nameLength > sizeOfDirectory){
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
name = directory.subdataInRange(JSRange(offset + 46, nameLength)).stringByDecodingUTF8();
|
|
88
|
+
this.directory.push({
|
|
89
|
+
name: name,
|
|
90
|
+
offset: headerOffset,
|
|
91
|
+
header: this.data.subdataInRange(JSRange(headerOffset, 30 + nameLength + extraFieldLength)),
|
|
92
|
+
crc: crc,
|
|
93
|
+
compressedLength: compressedLength,
|
|
94
|
+
uncompressedLength: uncompressedLength
|
|
95
|
+
});
|
|
96
|
+
this.directoryIndexByFilename[name] = i;
|
|
97
|
+
offset += 46 + nameLength + extraFieldLength + commentLength;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
directoryIndexByFilename: null,
|
|
103
|
+
filenames: JSReadOnlyProperty(),
|
|
104
|
+
|
|
105
|
+
getFilenames: function(){
|
|
106
|
+
var filenames = [];
|
|
107
|
+
for (var i = 0, l = this.directory.length; i < l; ++i){
|
|
108
|
+
filenames.push(this.directory[i].name);
|
|
109
|
+
}
|
|
110
|
+
return filenames;
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
dataForFilename: function(filename){
|
|
114
|
+
var index = this.directoryIndexByFilename[filename];
|
|
115
|
+
if (index === undefined){
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
var file = this.directory[index];
|
|
119
|
+
var dataView = file.header.dataView();
|
|
120
|
+
var signature = dataView.getUint32(0, true);
|
|
121
|
+
if (signature !== 0x04034b50){
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
var version = dataView.getUint16(4, true);
|
|
125
|
+
var flags = dataView.getUint16(6, true);
|
|
126
|
+
var method = dataView.getUint16(8, true);
|
|
127
|
+
var crc = dataView.getUint32(14, true);
|
|
128
|
+
var compressedLength = dataView.getUint32(18, true);
|
|
129
|
+
var uncompressedLength = dataView.getUint32(22, true);
|
|
130
|
+
var nameLength = dataView.getUint16(26, true);
|
|
131
|
+
var extraFieldLength = dataView.getUint16(28, true);
|
|
132
|
+
var offset = file.offset + 30 + nameLength + extraFieldLength;
|
|
133
|
+
if (version > 20){
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
if (method !== 8){
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
if ((flags & 0x8) !== 0){
|
|
140
|
+
crc = file.crc;
|
|
141
|
+
compressedLength = file.compressedLength;
|
|
142
|
+
uncompressedLength = file.uncompressedLength;
|
|
143
|
+
}
|
|
144
|
+
if (offset + compressedLength > this.data.length){
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
if (compressedLength === 0 || uncompressedLength === 0){
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
var compressedData = this.data.subdataInRange(JSRange(offset, compressedLength));
|
|
151
|
+
var data = JSData.initWithLength(uncompressedLength);
|
|
152
|
+
var stream = DeflateStream();
|
|
153
|
+
stream.input = compressedData;
|
|
154
|
+
stream.output = data;
|
|
155
|
+
stream.inflate(true);
|
|
156
|
+
if (stream.state !== DeflateStream.State.done){
|
|
157
|
+
data = null;
|
|
158
|
+
}
|
|
159
|
+
if (data === null){
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (JSCRC32(data) !== crc){
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
return data;
|
|
166
|
+
},
|
|
167
|
+
|
|
17
168
|
offset: 0,
|
|
18
169
|
|
|
19
170
|
addFile: function(file, completion, target){
|
|
@@ -83,7 +234,10 @@ JSClass("JSZip", JSObject, {
|
|
|
83
234
|
this.directory.push({
|
|
84
235
|
name: name,
|
|
85
236
|
offset: this.offset,
|
|
86
|
-
header: header
|
|
237
|
+
header: header,
|
|
238
|
+
crc: crc,
|
|
239
|
+
compressedLength: storedData.length,
|
|
240
|
+
uncompressedLength: data.length
|
|
87
241
|
});
|
|
88
242
|
this.chunks.push(header);
|
|
89
243
|
this.chunks.push(storedData);
|
|
@@ -167,9 +167,11 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
167
167
|
drawPath: function(drawingMode){
|
|
168
168
|
var path = this.path.copy();
|
|
169
169
|
this.enqueueOperation(function(state, completion, target){
|
|
170
|
+
this.canvasContext.save();
|
|
170
171
|
this.canvasContext.setTransform(1, 0, 0, 1, 0, 0);
|
|
171
172
|
this.canvasContext.beginPath();
|
|
172
173
|
path.addToIKHTMLCanvasContext(this.canvasContext);
|
|
174
|
+
this.canvasContext.restore();
|
|
173
175
|
switch (drawingMode){
|
|
174
176
|
case JSContext.DrawingMode.fill:
|
|
175
177
|
this.canvasContext.fill();
|
|
@@ -213,19 +215,21 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
213
215
|
return;
|
|
214
216
|
}
|
|
215
217
|
var scale = Math.ceil(Math.max(state.transform.a, state.transform.b));
|
|
218
|
+
var size = JSSize(rect.size.width * scale, rect.size.height * scale);
|
|
216
219
|
var maskCanvas = this.canvasContext.canvas.ownerDocument.createElement("canvas");
|
|
217
|
-
maskCanvas.width =
|
|
218
|
-
maskCanvas.height =
|
|
220
|
+
maskCanvas.width = size.width;
|
|
221
|
+
maskCanvas.height = size.height;
|
|
219
222
|
var maskContext = maskCanvas.getContext('2d');
|
|
220
223
|
maskContext.fillStyle = state.fillColor.cssString();
|
|
221
|
-
maskContext.fillRect(0, 0,
|
|
224
|
+
maskContext.fillRect(0, 0, size.width, size.height);
|
|
222
225
|
maskContext.globalCompositeOperation = 'destination-in';
|
|
223
|
-
maskContext.drawImage(imgElement, 0, 0,
|
|
226
|
+
maskContext.drawImage(imgElement, 0, 0, size.width, size.height);
|
|
224
227
|
this.canvasContext.drawImage(maskCanvas, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
225
228
|
completion.call(target);
|
|
226
229
|
}, this);
|
|
227
230
|
});
|
|
228
231
|
},
|
|
232
|
+
|
|
229
233
|
// ----------------------------------------------------------------------
|
|
230
234
|
// MARK: - Images
|
|
231
235
|
|
|
@@ -249,17 +253,7 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
249
253
|
drawLinearGradient: function(gradient, rect){
|
|
250
254
|
this.enqueueOperation(function(state, completion, target){
|
|
251
255
|
this.canvasContext.save();
|
|
252
|
-
var canvasGradient = this.canvasContext
|
|
253
|
-
rect.origin.x + gradient.start.x * rect.size.width,
|
|
254
|
-
rect.origin.y + gradient.start.y * rect.size.height,
|
|
255
|
-
rect.origin.x + gradient.end.x * rect.size.width,
|
|
256
|
-
rect.origin.y + gradient.end.y * rect.size.height
|
|
257
|
-
);
|
|
258
|
-
var stop;
|
|
259
|
-
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
260
|
-
stop = gradient.stops[i];
|
|
261
|
-
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
262
|
-
}
|
|
256
|
+
var canvasGradient = this._linearGradientForCanvasContext(this.canvasContext, gradient, rect);
|
|
263
257
|
this.canvasContext.fillStyle = canvasGradient;
|
|
264
258
|
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
265
259
|
this.canvasContext.restore();
|
|
@@ -269,30 +263,8 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
269
263
|
|
|
270
264
|
drawRadialGradient: function(gradient, rect){
|
|
271
265
|
this.enqueueOperation(function(state, completion, target){
|
|
272
|
-
var
|
|
273
|
-
var start = JSPoint(
|
|
274
|
-
rect.origin.x + gradient.start.x * rect.size.width,
|
|
275
|
-
rect.origin.y + gradient.start.y * rect.size.height
|
|
276
|
-
);
|
|
277
|
-
var end = JSPoint(
|
|
278
|
-
rect.origin.x + gradient.end.x * rect.size.width,
|
|
279
|
-
rect.origin.y + gradient.end.y * rect.size.height
|
|
280
|
-
);
|
|
281
|
-
var r1 = start.distanceToPoint(end);
|
|
266
|
+
var canvasGradient = this._radialGradientForCanvasContext(this.canvasContext, gradient, rect);
|
|
282
267
|
this.canvasContext.save();
|
|
283
|
-
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
284
|
-
start.x,
|
|
285
|
-
start.y,
|
|
286
|
-
r0,
|
|
287
|
-
start.x,
|
|
288
|
-
start.y,
|
|
289
|
-
r1
|
|
290
|
-
);
|
|
291
|
-
var stop;
|
|
292
|
-
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
293
|
-
stop = gradient.stops[i];
|
|
294
|
-
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
295
|
-
}
|
|
296
268
|
this.canvasContext.fillStyle = canvasGradient;
|
|
297
269
|
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
298
270
|
this.canvasContext.restore();
|
|
@@ -300,22 +272,61 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
300
272
|
});
|
|
301
273
|
},
|
|
302
274
|
|
|
303
|
-
|
|
275
|
+
drawMaskedLinearGradient: function(gradient, rect, maskImage){
|
|
276
|
+
this.enqueueOperation(function(state, completion, target){
|
|
277
|
+
drawableElementForImage(maskImage, this.canvasContext.canvas.ownerDocument, function(imgElement){
|
|
278
|
+
if (imgElement === null){
|
|
279
|
+
completion.call(target);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
var scale = Math.ceil(Math.max(state.transform.a, state.transform.b));
|
|
283
|
+
var size = JSSize(rect.size.width * scale, rect.size.height * scale);
|
|
284
|
+
var maskCanvas = this.canvasContext.canvas.ownerDocument.createElement("canvas");
|
|
285
|
+
maskCanvas.width = size.width;
|
|
286
|
+
maskCanvas.height = size.height;
|
|
287
|
+
var maskContext = maskCanvas.getContext('2d');
|
|
288
|
+
var canvasGradient = this._linearGradientForCanvasContext(maskContext, gradient, JSRect(JSPoint.Zero, size));
|
|
289
|
+
maskContext.fillStyle = canvasGradient;
|
|
290
|
+
maskContext.fillRect(0, 0, size.width, size.height);
|
|
291
|
+
maskContext.globalCompositeOperation = 'destination-in';
|
|
292
|
+
maskContext.drawImage(imgElement, 0, 0, size.width, size.height);
|
|
293
|
+
this.canvasContext.drawImage(maskCanvas, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
294
|
+
completion.call(target);
|
|
295
|
+
}, this);
|
|
296
|
+
});
|
|
297
|
+
},
|
|
298
|
+
|
|
299
|
+
drawMaskedRadialGradient: function(gradient, rect, maskImage){
|
|
300
|
+
this.enqueueOperation(function(state, completion, target){
|
|
301
|
+
drawableElementForImage(maskImage, this.canvasContext.canvas.ownerDocument, function(imgElement){
|
|
302
|
+
if (imgElement === null){
|
|
303
|
+
completion.call(target);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
var scale = Math.ceil(Math.max(state.transform.a, state.transform.b));
|
|
307
|
+
var size = JSSize(rect.size.width * scale, rect.size.height * scale);
|
|
308
|
+
var maskCanvas = this.canvasContext.canvas.ownerDocument.createElement("canvas");
|
|
309
|
+
maskCanvas.width = size.width;
|
|
310
|
+
maskCanvas.height = size.height;
|
|
311
|
+
var maskContext = maskCanvas.getContext('2d');
|
|
312
|
+
var canvasGradient = this._radialGradientForCanvasContext(maskContext, gradient, JSRect(JSPoint.Zero, size));
|
|
313
|
+
maskContext.fillStyle = canvasGradient;
|
|
314
|
+
maskContext.fillRect(0, 0, size.width, size.height);
|
|
315
|
+
maskContext.globalCompositeOperation = 'destination-in';
|
|
316
|
+
maskContext.drawImage(imgElement, 0, 0, size.width, size.height);
|
|
317
|
+
this.canvasContext.drawImage(maskCanvas, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
318
|
+
completion.call(target);
|
|
319
|
+
}, this);
|
|
320
|
+
});
|
|
321
|
+
},
|
|
322
|
+
|
|
323
|
+
drawLinearGradientStroke: function(gradient, path, alternateRect){
|
|
304
324
|
this.enqueueOperation(function(state, completion, target){
|
|
305
325
|
var rect = path.boundingRect;
|
|
306
326
|
this.canvasContext.save();
|
|
307
|
-
this.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
rect.origin.y + gradient.start.y * rect.size.height,
|
|
311
|
-
rect.origin.x + gradient.end.x * rect.size.width,
|
|
312
|
-
rect.origin.y + gradient.end.y * rect.size.height
|
|
313
|
-
);
|
|
314
|
-
var stop;
|
|
315
|
-
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
316
|
-
stop = gradient.stops[i];
|
|
317
|
-
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
318
|
-
}
|
|
327
|
+
this.canvasContext.beginPath();
|
|
328
|
+
path.addToIKHTMLCanvasContext(this.canvasContext);
|
|
329
|
+
var canvasGradient = this._linearGradientForCanvasContext(this.canvasContext, gradient, alternateRect || rect);
|
|
319
330
|
this.canvasContext.strokeStyle = canvasGradient;
|
|
320
331
|
this.canvasContext.stroke();
|
|
321
332
|
this.canvasContext.restore();
|
|
@@ -324,34 +335,13 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
324
335
|
this.beginPath();
|
|
325
336
|
},
|
|
326
337
|
|
|
327
|
-
drawRadialGradientStroke: function(gradient, path){
|
|
338
|
+
drawRadialGradientStroke: function(gradient, path, alternateRect){
|
|
328
339
|
this.enqueueOperation(function(state, completion, target){
|
|
329
340
|
var rect = path.boundingRect;
|
|
330
|
-
var r0 = 0;
|
|
331
|
-
var start = JSPoint(
|
|
332
|
-
rect.origin.x + gradient.start.x * rect.size.width,
|
|
333
|
-
rect.origin.y + gradient.start.y * rect.size.height
|
|
334
|
-
);
|
|
335
|
-
var end = JSPoint(
|
|
336
|
-
rect.origin.x + gradient.end.x * rect.size.width,
|
|
337
|
-
rect.origin.y + gradient.end.y * rect.size.height
|
|
338
|
-
);
|
|
339
|
-
var r1 = start.distanceToPoint(end);
|
|
340
341
|
this.canvasContext.save();
|
|
341
|
-
this.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
start.y,
|
|
345
|
-
r0,
|
|
346
|
-
start.x,
|
|
347
|
-
start.y,
|
|
348
|
-
r1
|
|
349
|
-
);
|
|
350
|
-
var stop;
|
|
351
|
-
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
352
|
-
stop = gradient.stops[i];
|
|
353
|
-
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
354
|
-
}
|
|
342
|
+
this.canvasContext.beginPath();
|
|
343
|
+
path.addToIKHTMLCanvasContext(this.canvasContext);
|
|
344
|
+
var canvasGradient = this._radialGradientForCanvasContext(this.canvasContext, gradient, alternateRect || rect);
|
|
355
345
|
this.canvasContext.strokeStyle = canvasGradient;
|
|
356
346
|
this.canvasContext.stroke();
|
|
357
347
|
this.canvasContext.restore();
|
|
@@ -360,6 +350,105 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
360
350
|
this.beginPath();
|
|
361
351
|
},
|
|
362
352
|
|
|
353
|
+
_linearGradientForCanvasContext: function(canvasContext, gradient, rect){
|
|
354
|
+
var canvasGradient = canvasContext.createLinearGradient(
|
|
355
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
356
|
+
rect.origin.y + gradient.start.y * rect.size.height,
|
|
357
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
358
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
359
|
+
);
|
|
360
|
+
var stop;
|
|
361
|
+
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
362
|
+
stop = gradient.stops[i];
|
|
363
|
+
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
364
|
+
}
|
|
365
|
+
return canvasGradient;
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
_radialGradientForCanvasContext: function(canvasContext, gradient, rect){
|
|
369
|
+
var r0 = 0;
|
|
370
|
+
var start = JSPoint(
|
|
371
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
372
|
+
rect.origin.y + gradient.start.y * rect.size.height
|
|
373
|
+
);
|
|
374
|
+
var end = JSPoint(
|
|
375
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
376
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
377
|
+
);
|
|
378
|
+
var r1 = start.distanceToPoint(end);
|
|
379
|
+
var canvasGradient = canvasContext.createRadialGradient(
|
|
380
|
+
start.x,
|
|
381
|
+
start.y,
|
|
382
|
+
r0,
|
|
383
|
+
start.x,
|
|
384
|
+
start.y,
|
|
385
|
+
r1
|
|
386
|
+
);
|
|
387
|
+
var stop;
|
|
388
|
+
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
389
|
+
stop = gradient.stops[i];
|
|
390
|
+
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
391
|
+
}
|
|
392
|
+
return canvasGradient;
|
|
393
|
+
},
|
|
394
|
+
|
|
395
|
+
// ----------------------------------------------------------------------
|
|
396
|
+
// MARK: - Transparency Layers
|
|
397
|
+
|
|
398
|
+
_reusableTransparencyLayer: null,
|
|
399
|
+
|
|
400
|
+
createTransparencyLayer: function(){
|
|
401
|
+
if (this._reusableTransparencyLayer !== null){
|
|
402
|
+
layer = this._reusableTransparencyLayer;
|
|
403
|
+
this._reusableTransparencyLayer = null;
|
|
404
|
+
layer.context.resetTransform();
|
|
405
|
+
layer.context.clearRect(0, 0, layer.canvas.width, layer.canvas.height);
|
|
406
|
+
this._canvasContextAdoptState(layer.context, this.state);
|
|
407
|
+
layer.parentContext = this.canvasContext;
|
|
408
|
+
this.canvasContext = layer.context;
|
|
409
|
+
return layer;
|
|
410
|
+
}
|
|
411
|
+
var parentContext = this.canvasContext;
|
|
412
|
+
var canvas = this.canvasElement.ownerDocument.createElement("canvas");
|
|
413
|
+
canvas.width = this.canvasElement.width;
|
|
414
|
+
canvas.height = this.canvasElement.height;
|
|
415
|
+
var context = canvas.getContext("2d");
|
|
416
|
+
this._canvasContextAdoptState(context, this.state);
|
|
417
|
+
var layer = {
|
|
418
|
+
canvas: canvas,
|
|
419
|
+
context: context,
|
|
420
|
+
parentContext: parentContext
|
|
421
|
+
};
|
|
422
|
+
this.canvasContext = context;
|
|
423
|
+
return layer;
|
|
424
|
+
},
|
|
425
|
+
|
|
426
|
+
drawTransparencyLayer: function(transparencyLayer){
|
|
427
|
+
this.canvasContext = transparencyLayer.parentContext;
|
|
428
|
+
this.canvasContext.resetTransform();
|
|
429
|
+
this.canvasContext.drawImage(transparencyLayer.canvas, 0, 0);
|
|
430
|
+
this._reusableTransparencyLayer = transparencyLayer;
|
|
431
|
+
},
|
|
432
|
+
|
|
433
|
+
_canvasContextAdoptState: function(context, state){
|
|
434
|
+
context.globalAlpha = state.alpha;
|
|
435
|
+
context.fillStyle = state.fillColor ? state.fillColor.cssString() : '';
|
|
436
|
+
context.strokeStyle = state.strokeColor ? state.strokeColor.cssString() : '';
|
|
437
|
+
context.shadowOffsetX = state.shadowOffset.x;
|
|
438
|
+
context.shadowOffsetY = state.shadowOffset.y;
|
|
439
|
+
context.shadowBlur = state.shadowBlur;
|
|
440
|
+
context.shadowColor = state.shadowColor ? state.shadowColor.cssString() : '';
|
|
441
|
+
context.lineWidth = state.lineWidth;
|
|
442
|
+
context.lineCap = state.lineCap;
|
|
443
|
+
context.lineJoin = state.lineJoin;
|
|
444
|
+
context.miterLimit = state.miterLimit;
|
|
445
|
+
context.lineDashOffset = state.lineDashPhase;
|
|
446
|
+
context.setLineDash(state.lineDashArray);
|
|
447
|
+
var transform = state.transform;
|
|
448
|
+
context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty);
|
|
449
|
+
context.font = state.font ? state.font.cssString() : '';
|
|
450
|
+
},
|
|
451
|
+
|
|
363
452
|
// ----------------------------------------------------------------------
|
|
364
453
|
// MARK: - Text
|
|
365
454
|
|
|
@@ -502,31 +591,24 @@ JSPath.definePropertiesFromExtensions({
|
|
|
502
591
|
|
|
503
592
|
addToIKHTMLCanvasContext: function(canvasContext){
|
|
504
593
|
var i, l;
|
|
505
|
-
var
|
|
506
|
-
var
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
segment.curve.cp2.y,
|
|
524
|
-
segment.curve.p2.x,
|
|
525
|
-
segment.curve.p2.y
|
|
526
|
-
);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
if (subpath.closed){
|
|
594
|
+
var elements = this.elements;
|
|
595
|
+
var element;
|
|
596
|
+
for (i = 0, l = elements.length; i < l; ++i){
|
|
597
|
+
element = elements[i];
|
|
598
|
+
if (element.type === JSPathElement.Type.move){
|
|
599
|
+
canvasContext.moveTo(element.point.x, element.point.y);
|
|
600
|
+
}else if (element.type === JSPathElement.Type.line){
|
|
601
|
+
canvasContext.lineTo(element.point.x, element.point.y);
|
|
602
|
+
}else if (element.type === JSPathElement.Type.cubicCurve){
|
|
603
|
+
canvasContext.bezierCurveTo(
|
|
604
|
+
element.curve.cp1.x,
|
|
605
|
+
element.curve.cp1.y,
|
|
606
|
+
element.curve.cp2.x,
|
|
607
|
+
element.curve.cp2.y,
|
|
608
|
+
element.curve.p2.x,
|
|
609
|
+
element.curve.p2.y
|
|
610
|
+
);
|
|
611
|
+
}else if (element.type === JSPathElement.Type.close){
|
|
530
612
|
canvasContext.closePath();
|
|
531
613
|
}
|
|
532
614
|
}
|
|
@@ -535,6 +617,10 @@ JSPath.definePropertiesFromExtensions({
|
|
|
535
617
|
});
|
|
536
618
|
|
|
537
619
|
var drawableElementForImage = function(image, domDocument, completion, target){
|
|
620
|
+
if (image._htmlImage !== undefined && image._htmlImage !== null){
|
|
621
|
+
completion.call(target, image._htmlImage);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
538
624
|
var imgElement = domDocument.createElement("img");
|
|
539
625
|
imgElement.setAttribute("crossorigin", "anonymous");
|
|
540
626
|
imgElement.src = image.htmlURLString();
|
|
@@ -185,10 +185,10 @@ JSClass("IKNodeBitmapContext", IKBitmapContext, {
|
|
|
185
185
|
squarePath.addLineToPoint(JSPoint(1, 1));
|
|
186
186
|
squarePath.addLineToPoint(JSPoint(0, 1));
|
|
187
187
|
squarePath.close();
|
|
188
|
-
var p1 = squarePath.
|
|
189
|
-
var p2 = squarePath.
|
|
190
|
-
var p3 = squarePath.
|
|
191
|
-
var p4 = squarePath.
|
|
188
|
+
var p1 = squarePath.elements[0].point;
|
|
189
|
+
var p2 = squarePath.elements[1].point;
|
|
190
|
+
var p3 = squarePath.elements[2].point;
|
|
191
|
+
var p4 = squarePath.elements[3].point;
|
|
192
192
|
for (var i = 0; p1.y < bitmap.size.height; ++p1.y, ++p2.y, ++p3.y, ++p4.y){
|
|
193
193
|
for (p1.x = 0, p2.x = 1, p3.x = 1, p4.x = 0; p1.x < bitmap.size.width; ++p1.x, ++p2.x, ++p3.x, ++p4.x){
|
|
194
194
|
r = bitmap.data[i++];
|