@breakside/jskit 2026.4.1 → 2026.8.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/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSContext.js +23 -1
- package/Frameworks/Foundation.jsframework/JS/JSGradient.js +25 -0
- package/Frameworks/Foundation.jsframework/JS/JSPath.js +80 -0
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- 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/TestCommand.js +1 -1
- package/Node/io.breakside.jskit-bundle.js +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/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSContext.js +23 -1
- package/Root/Frameworks/Foundation/JSGradient.js +25 -0
- package/Root/Frameworks/Foundation/JSPath.js +80 -0
- package/Root/Frameworks/ImageKit/IKHTMLCanvasBitmapContext.js +91 -13
- 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/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UICollectionViewGridLayout.js +59 -19
- package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +87 -13
- package/Root/Frameworks/UIKit/UILayer.js +6 -0
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "framework",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.JSKit.DOM",
|
|
4
|
-
"JSBundleVersion": "2026.
|
|
4
|
+
"JSBundleVersion": "2026.8.0",
|
|
5
5
|
"JSDevelopmentLanguage": "en",
|
|
6
6
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
7
7
|
"JSBundleEnvironments": {
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
"node": "DOM+Node.js"
|
|
10
10
|
},
|
|
11
11
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
12
|
-
"GitRevision": "
|
|
12
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
13
13
|
}
|
|
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "framework",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.JSKit.DOM",
|
|
6
|
-
"JSBundleVersion": "2026.
|
|
6
|
+
"JSBundleVersion": "2026.8.0",
|
|
7
7
|
"JSDevelopmentLanguage": "en",
|
|
8
8
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
9
9
|
"JSBundleEnvironments": {
|
|
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
|
|
|
11
11
|
"node": "DOM+Node.js"
|
|
12
12
|
},
|
|
13
13
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
14
|
-
"GitRevision": "
|
|
14
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
15
15
|
},
|
|
16
16
|
"Resources": [],
|
|
17
17
|
"ResourceLookup": {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "framework",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.JSKit.FontKit",
|
|
4
|
-
"JSBundleVersion": "2026.
|
|
4
|
+
"JSBundleVersion": "2026.8.0",
|
|
5
5
|
"JSDevelopmentLanguage": "en",
|
|
6
6
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
7
7
|
"JSBundleEnvironments": {
|
|
8
8
|
"html": "FontKit+HTML.js"
|
|
9
9
|
},
|
|
10
10
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
11
|
-
"GitRevision": "
|
|
11
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
12
12
|
}
|
|
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.JSKit.FontKit'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "framework",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.JSKit.FontKit",
|
|
6
|
-
"JSBundleVersion": "2026.
|
|
6
|
+
"JSBundleVersion": "2026.8.0",
|
|
7
7
|
"JSDevelopmentLanguage": "en",
|
|
8
8
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
9
9
|
"JSBundleEnvironments": {
|
|
10
10
|
"html": "FontKit+HTML.js"
|
|
11
11
|
},
|
|
12
12
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
13
|
-
"GitRevision": "
|
|
13
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
14
14
|
},
|
|
15
15
|
"Resources": [],
|
|
16
16
|
"ResourceLookup": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "framework",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.JSKit.Foundation",
|
|
4
|
-
"JSBundleVersion": "2026.
|
|
4
|
+
"JSBundleVersion": "2026.8.0",
|
|
5
5
|
"JSDevelopmentLanguage": "en",
|
|
6
6
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
7
7
|
"JSBundleEnvironments": {
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
"node": "Foundation+Node.js"
|
|
10
10
|
},
|
|
11
11
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
12
|
-
"GitRevision": "
|
|
12
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
13
13
|
}
|
|
@@ -209,7 +209,29 @@ JSClass("JSContext", JSObject, {
|
|
|
209
209
|
drawLinearGradient: function(gradient, rect){
|
|
210
210
|
},
|
|
211
211
|
|
|
212
|
-
drawRadialGradient: function(gradient, rect
|
|
212
|
+
drawRadialGradient: function(gradient, rect){
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
drawLinearGradientStroke: function(gradient, path){
|
|
216
|
+
// FIXME: gradient should be aligned to original path rect
|
|
217
|
+
var strokePath = path.pathThatFillsStroke(this.state.lineWidth, this.state.lineCap, this.state.lineJoin, this.state.miterLimit);
|
|
218
|
+
this.save();
|
|
219
|
+
var rect = strokePath.boundingRect;
|
|
220
|
+
this.addPath(path);
|
|
221
|
+
this.clip();
|
|
222
|
+
this.drawLinearGradient(gradient, rect);
|
|
223
|
+
this.restore();
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
drawRadialGradientStroke: function(gradient, path){
|
|
227
|
+
// FIXME: gradient should be aligned to original path rect
|
|
228
|
+
var strokePath = path.pathThatFillsStroke(this.state.lineWidth, this.state.lineCap, this.state.lineJoin, this.state.miterLimit);
|
|
229
|
+
this.save();
|
|
230
|
+
var rect = strokePath.boundingRect;
|
|
231
|
+
this.addPath(path);
|
|
232
|
+
this.clip();
|
|
233
|
+
this.drawRadialGradient(gradient, rect);
|
|
234
|
+
this.restore();
|
|
213
235
|
},
|
|
214
236
|
|
|
215
237
|
// ----------------------------------------------------------------------
|
|
@@ -86,6 +86,31 @@ JSClass('JSGradient', JSObject, {
|
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
88
|
|
|
89
|
+
initFromDictionary: function(dictionary){
|
|
90
|
+
if (dictionary === null || dictionary === undefined){
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
this.start = JSPoint(dictionary.x0, dictionary.y0);
|
|
94
|
+
this.end = JSPoint(dictionary.x1, dictionary.y1);
|
|
95
|
+
this.stops = [];
|
|
96
|
+
var i, l;
|
|
97
|
+
for (i = 0, l = dictionary.stops.length; i < l; ++i){
|
|
98
|
+
this.addStop(dictionary.stops[i][0], JSColor.initWithRGBAHexString(dictionary.stops[i][1]));
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
dictionaryRepresentation: function(){
|
|
103
|
+
return {
|
|
104
|
+
x0: this.start.x,
|
|
105
|
+
y0: this.start.y,
|
|
106
|
+
x1: this.end.x,
|
|
107
|
+
y1: this.end.y,
|
|
108
|
+
stops: this.stops.map(function(s){
|
|
109
|
+
return [s.position, s.color.rgbaHexStringRepresentation()];
|
|
110
|
+
})
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
|
|
89
114
|
initWithStops: function(position1, color1 /* , ... */){
|
|
90
115
|
this.init();
|
|
91
116
|
var args = Array.prototype.slice.call(arguments, 0);
|
|
@@ -838,6 +838,83 @@ JSClass("JSPath", JSObject, {
|
|
|
838
838
|
return JSRect(min, JSSize(max.x - min.x, max.y - min.y));
|
|
839
839
|
},
|
|
840
840
|
|
|
841
|
+
initWithSVGPathData: function(svgPathData){
|
|
842
|
+
if (svgPathData === null || svgPathData === undefined){
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
var parts = svgPathData.split(" ").filter(function(p){
|
|
846
|
+
return p !== "";
|
|
847
|
+
});
|
|
848
|
+
this.subpaths = [];
|
|
849
|
+
var part;
|
|
850
|
+
var subpath = null;
|
|
851
|
+
var point = JSPoint.Zero;
|
|
852
|
+
var cp1;
|
|
853
|
+
var cp2;
|
|
854
|
+
var curve;
|
|
855
|
+
while (parts.length > 0){
|
|
856
|
+
part = parts.shift();
|
|
857
|
+
if (part === "M"){
|
|
858
|
+
if (parts.length < 2){
|
|
859
|
+
break;
|
|
860
|
+
}
|
|
861
|
+
point = JSPoint.Zero;
|
|
862
|
+
part = parts.shift();
|
|
863
|
+
point.x = parseFloat(part);
|
|
864
|
+
part = parts.shift();
|
|
865
|
+
point.y = parseFloat(part);
|
|
866
|
+
subpath = Subpath(point);
|
|
867
|
+
this.subpaths.push(subpath);
|
|
868
|
+
this._currentPoint = point;
|
|
869
|
+
}else if (part === "L"){
|
|
870
|
+
if (parts.length < 2){
|
|
871
|
+
break;
|
|
872
|
+
}
|
|
873
|
+
if (subpath === null){
|
|
874
|
+
subpath = Subpath(point);
|
|
875
|
+
this.subpaths.push(subpath);
|
|
876
|
+
}
|
|
877
|
+
point = JSPoint.Zero;
|
|
878
|
+
part = parts.shift();
|
|
879
|
+
point.x = parseFloat(part);
|
|
880
|
+
part = parts.shift();
|
|
881
|
+
point.y = parseFloat(part);
|
|
882
|
+
subpath.segments.push({type: JSPath.SegmentType.line, end: point});
|
|
883
|
+
this._currentPoint = point;
|
|
884
|
+
}else if (part === "C"){
|
|
885
|
+
if (parts.length < 6){
|
|
886
|
+
break;
|
|
887
|
+
}
|
|
888
|
+
if (subpath === null){
|
|
889
|
+
subpath = Subpath(point);
|
|
890
|
+
this.subpaths.push(subpath);
|
|
891
|
+
}
|
|
892
|
+
cp1 = JSPoint.Zero;
|
|
893
|
+
cp2 = JSPoint.Zero;
|
|
894
|
+
point = JSPoint.Zero;
|
|
895
|
+
part = parts.shift();
|
|
896
|
+
cp1.x = parseFloat(part);
|
|
897
|
+
part = parts.shift();
|
|
898
|
+
cp1.y = parseFloat(part);
|
|
899
|
+
part = parts.shift();
|
|
900
|
+
cp2.x = parseFloat(part);
|
|
901
|
+
part = parts.shift();
|
|
902
|
+
cp2.y = parseFloat(part);
|
|
903
|
+
part = parts.shift();
|
|
904
|
+
point.x = parseFloat(part);
|
|
905
|
+
part = parts.shift();
|
|
906
|
+
point.y = parseFloat(part);
|
|
907
|
+
subpath.segments.push({type: JSPath.SegmentType.curve, curve: JSCubicBezier(this._currentPoint, cp1, cp2, point)});
|
|
908
|
+
this._currentPoint = point;
|
|
909
|
+
}else if (part === "Z"){
|
|
910
|
+
if (subpath !== null){
|
|
911
|
+
subpath.closed = true;
|
|
912
|
+
subpath = null;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
},
|
|
917
|
+
|
|
841
918
|
svgPathData: function(){
|
|
842
919
|
var subpath;
|
|
843
920
|
var segment;
|
|
@@ -868,6 +945,9 @@ JSClass("JSPath", JSObject, {
|
|
|
868
945
|
data += "Z ";
|
|
869
946
|
}
|
|
870
947
|
}
|
|
948
|
+
if (data.length > 0 && data[data.length - 1] == " "){
|
|
949
|
+
data = data.substr(0, data.length - 1);
|
|
950
|
+
}
|
|
871
951
|
return data;
|
|
872
952
|
},
|
|
873
953
|
|
|
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "framework",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.JSKit.Foundation",
|
|
6
|
-
"JSBundleVersion": "2026.
|
|
6
|
+
"JSBundleVersion": "2026.8.0",
|
|
7
7
|
"JSDevelopmentLanguage": "en",
|
|
8
8
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
9
9
|
"JSBundleEnvironments": {
|
|
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
|
|
|
11
11
|
"node": "Foundation+Node.js"
|
|
12
12
|
},
|
|
13
13
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
14
|
-
"GitRevision": "
|
|
14
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
15
15
|
},
|
|
16
16
|
"Resources": [
|
|
17
17
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "framework",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
|
|
4
|
-
"JSBundleVersion": "2026.
|
|
4
|
+
"JSBundleVersion": "2026.8.0",
|
|
5
5
|
"JSDevelopmentLanguage": "en",
|
|
6
6
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
7
7
|
"JSBundleEnvironments": {
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
"node": "SecurityKit+Node.js"
|
|
10
10
|
},
|
|
11
11
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
12
|
-
"GitRevision": "
|
|
12
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
13
13
|
}
|
|
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "framework",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
|
|
6
|
-
"JSBundleVersion": "2026.
|
|
6
|
+
"JSBundleVersion": "2026.8.0",
|
|
7
7
|
"JSDevelopmentLanguage": "en",
|
|
8
8
|
"JSCopyright": "Copyright © 2020 Breakside Inc.",
|
|
9
9
|
"JSBundleEnvironments": {
|
|
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
|
|
|
11
11
|
"node": "SecurityKit+Node.js"
|
|
12
12
|
},
|
|
13
13
|
"JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
|
|
14
|
-
"GitRevision": "
|
|
14
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
15
15
|
},
|
|
16
16
|
"Resources": [],
|
|
17
17
|
"ResourceLookup": {
|
package/Info.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"JSBundleType": "node",
|
|
3
3
|
"JSBundleIdentifier": "io.breakside.jskit",
|
|
4
|
-
"JSBundleVersion": "2026.
|
|
4
|
+
"JSBundleVersion": "2026.8.0",
|
|
5
5
|
"JSExecutableName": "jskit",
|
|
6
6
|
"NPMOrganization": "breakside",
|
|
7
7
|
"JSResources": [
|
|
8
8
|
"Tests/HTMLTestRunner.js",
|
|
9
9
|
"Tests/NodeTestRunner.js"
|
|
10
10
|
],
|
|
11
|
-
"GitRevision": "
|
|
11
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
12
12
|
}
|
package/Node/TestCommand.js
CHANGED
|
@@ -239,7 +239,7 @@ JSClass("TestCommand", Command, {
|
|
|
239
239
|
var query = url.query;
|
|
240
240
|
query.add("headless");
|
|
241
241
|
url.query = query;
|
|
242
|
-
var page = await browser.newPage();
|
|
242
|
+
var page = await browser.newPage({locale: Intl.DateTimeFormat().resolvedOptions().locale});
|
|
243
243
|
var cmd = this;
|
|
244
244
|
await new Promise(function(resolve, reject){
|
|
245
245
|
page.exposeFunction("headlessPrint", function(text, ttyOnly){
|
|
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.jskit'] = {
|
|
|
3
3
|
"Info": {
|
|
4
4
|
"JSBundleType": "node",
|
|
5
5
|
"JSBundleIdentifier": "io.breakside.jskit",
|
|
6
|
-
"JSBundleVersion": "2026.
|
|
6
|
+
"JSBundleVersion": "2026.8.0",
|
|
7
7
|
"JSExecutableName": "jskit",
|
|
8
8
|
"NPMOrganization": "breakside",
|
|
9
9
|
"JSResources": [
|
|
10
10
|
"Tests/HTMLTestRunner.js",
|
|
11
11
|
"Tests/NodeTestRunner.js"
|
|
12
12
|
],
|
|
13
|
-
"GitRevision": "
|
|
13
|
+
"GitRevision": "b4a1f6046edfde1343010e48660aff5aa3e8353e"
|
|
14
14
|
},
|
|
15
15
|
"Resources": [
|
|
16
16
|
{
|
|
@@ -209,7 +209,29 @@ JSClass("JSContext", JSObject, {
|
|
|
209
209
|
drawLinearGradient: function(gradient, rect){
|
|
210
210
|
},
|
|
211
211
|
|
|
212
|
-
drawRadialGradient: function(gradient, rect
|
|
212
|
+
drawRadialGradient: function(gradient, rect){
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
drawLinearGradientStroke: function(gradient, path){
|
|
216
|
+
// FIXME: gradient should be aligned to original path rect
|
|
217
|
+
var strokePath = path.pathThatFillsStroke(this.state.lineWidth, this.state.lineCap, this.state.lineJoin, this.state.miterLimit);
|
|
218
|
+
this.save();
|
|
219
|
+
var rect = strokePath.boundingRect;
|
|
220
|
+
this.addPath(path);
|
|
221
|
+
this.clip();
|
|
222
|
+
this.drawLinearGradient(gradient, rect);
|
|
223
|
+
this.restore();
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
drawRadialGradientStroke: function(gradient, path){
|
|
227
|
+
// FIXME: gradient should be aligned to original path rect
|
|
228
|
+
var strokePath = path.pathThatFillsStroke(this.state.lineWidth, this.state.lineCap, this.state.lineJoin, this.state.miterLimit);
|
|
229
|
+
this.save();
|
|
230
|
+
var rect = strokePath.boundingRect;
|
|
231
|
+
this.addPath(path);
|
|
232
|
+
this.clip();
|
|
233
|
+
this.drawRadialGradient(gradient, rect);
|
|
234
|
+
this.restore();
|
|
213
235
|
},
|
|
214
236
|
|
|
215
237
|
// ----------------------------------------------------------------------
|
|
@@ -86,6 +86,31 @@ JSClass('JSGradient', JSObject, {
|
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
88
|
|
|
89
|
+
initFromDictionary: function(dictionary){
|
|
90
|
+
if (dictionary === null || dictionary === undefined){
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
this.start = JSPoint(dictionary.x0, dictionary.y0);
|
|
94
|
+
this.end = JSPoint(dictionary.x1, dictionary.y1);
|
|
95
|
+
this.stops = [];
|
|
96
|
+
var i, l;
|
|
97
|
+
for (i = 0, l = dictionary.stops.length; i < l; ++i){
|
|
98
|
+
this.addStop(dictionary.stops[i][0], JSColor.initWithRGBAHexString(dictionary.stops[i][1]));
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
dictionaryRepresentation: function(){
|
|
103
|
+
return {
|
|
104
|
+
x0: this.start.x,
|
|
105
|
+
y0: this.start.y,
|
|
106
|
+
x1: this.end.x,
|
|
107
|
+
y1: this.end.y,
|
|
108
|
+
stops: this.stops.map(function(s){
|
|
109
|
+
return [s.position, s.color.rgbaHexStringRepresentation()];
|
|
110
|
+
})
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
|
|
89
114
|
initWithStops: function(position1, color1 /* , ... */){
|
|
90
115
|
this.init();
|
|
91
116
|
var args = Array.prototype.slice.call(arguments, 0);
|
|
@@ -838,6 +838,83 @@ JSClass("JSPath", JSObject, {
|
|
|
838
838
|
return JSRect(min, JSSize(max.x - min.x, max.y - min.y));
|
|
839
839
|
},
|
|
840
840
|
|
|
841
|
+
initWithSVGPathData: function(svgPathData){
|
|
842
|
+
if (svgPathData === null || svgPathData === undefined){
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
var parts = svgPathData.split(" ").filter(function(p){
|
|
846
|
+
return p !== "";
|
|
847
|
+
});
|
|
848
|
+
this.subpaths = [];
|
|
849
|
+
var part;
|
|
850
|
+
var subpath = null;
|
|
851
|
+
var point = JSPoint.Zero;
|
|
852
|
+
var cp1;
|
|
853
|
+
var cp2;
|
|
854
|
+
var curve;
|
|
855
|
+
while (parts.length > 0){
|
|
856
|
+
part = parts.shift();
|
|
857
|
+
if (part === "M"){
|
|
858
|
+
if (parts.length < 2){
|
|
859
|
+
break;
|
|
860
|
+
}
|
|
861
|
+
point = JSPoint.Zero;
|
|
862
|
+
part = parts.shift();
|
|
863
|
+
point.x = parseFloat(part);
|
|
864
|
+
part = parts.shift();
|
|
865
|
+
point.y = parseFloat(part);
|
|
866
|
+
subpath = Subpath(point);
|
|
867
|
+
this.subpaths.push(subpath);
|
|
868
|
+
this._currentPoint = point;
|
|
869
|
+
}else if (part === "L"){
|
|
870
|
+
if (parts.length < 2){
|
|
871
|
+
break;
|
|
872
|
+
}
|
|
873
|
+
if (subpath === null){
|
|
874
|
+
subpath = Subpath(point);
|
|
875
|
+
this.subpaths.push(subpath);
|
|
876
|
+
}
|
|
877
|
+
point = JSPoint.Zero;
|
|
878
|
+
part = parts.shift();
|
|
879
|
+
point.x = parseFloat(part);
|
|
880
|
+
part = parts.shift();
|
|
881
|
+
point.y = parseFloat(part);
|
|
882
|
+
subpath.segments.push({type: JSPath.SegmentType.line, end: point});
|
|
883
|
+
this._currentPoint = point;
|
|
884
|
+
}else if (part === "C"){
|
|
885
|
+
if (parts.length < 6){
|
|
886
|
+
break;
|
|
887
|
+
}
|
|
888
|
+
if (subpath === null){
|
|
889
|
+
subpath = Subpath(point);
|
|
890
|
+
this.subpaths.push(subpath);
|
|
891
|
+
}
|
|
892
|
+
cp1 = JSPoint.Zero;
|
|
893
|
+
cp2 = JSPoint.Zero;
|
|
894
|
+
point = JSPoint.Zero;
|
|
895
|
+
part = parts.shift();
|
|
896
|
+
cp1.x = parseFloat(part);
|
|
897
|
+
part = parts.shift();
|
|
898
|
+
cp1.y = parseFloat(part);
|
|
899
|
+
part = parts.shift();
|
|
900
|
+
cp2.x = parseFloat(part);
|
|
901
|
+
part = parts.shift();
|
|
902
|
+
cp2.y = parseFloat(part);
|
|
903
|
+
part = parts.shift();
|
|
904
|
+
point.x = parseFloat(part);
|
|
905
|
+
part = parts.shift();
|
|
906
|
+
point.y = parseFloat(part);
|
|
907
|
+
subpath.segments.push({type: JSPath.SegmentType.curve, curve: JSCubicBezier(this._currentPoint, cp1, cp2, point)});
|
|
908
|
+
this._currentPoint = point;
|
|
909
|
+
}else if (part === "Z"){
|
|
910
|
+
if (subpath !== null){
|
|
911
|
+
subpath.closed = true;
|
|
912
|
+
subpath = null;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
},
|
|
917
|
+
|
|
841
918
|
svgPathData: function(){
|
|
842
919
|
var subpath;
|
|
843
920
|
var segment;
|
|
@@ -868,6 +945,9 @@ JSClass("JSPath", JSObject, {
|
|
|
868
945
|
data += "Z ";
|
|
869
946
|
}
|
|
870
947
|
}
|
|
948
|
+
if (data.length > 0 && data[data.length - 1] == " "){
|
|
949
|
+
data = data.substr(0, data.length - 1);
|
|
950
|
+
}
|
|
871
951
|
return data;
|
|
872
952
|
},
|
|
873
953
|
|
|
@@ -248,38 +248,116 @@ JSClass("IKHTMLCanvasBitmapContext", IKBitmapContext, {
|
|
|
248
248
|
|
|
249
249
|
drawLinearGradient: function(gradient, rect){
|
|
250
250
|
this.enqueueOperation(function(state, completion, target){
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
251
|
+
this.canvasContext.save();
|
|
252
|
+
var canvasGradient = this.canvasContext.createLinearGradient(
|
|
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
|
+
);
|
|
256
258
|
var stop;
|
|
257
259
|
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
258
260
|
stop = gradient.stops[i];
|
|
259
261
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
260
262
|
}
|
|
261
263
|
this.canvasContext.fillStyle = canvasGradient;
|
|
262
|
-
this.canvasContext.fillRect(
|
|
264
|
+
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
265
|
+
this.canvasContext.restore();
|
|
263
266
|
completion.call(target);
|
|
264
267
|
});
|
|
265
268
|
},
|
|
266
269
|
|
|
267
|
-
drawRadialGradient: function(gradient, rect
|
|
270
|
+
drawRadialGradient: function(gradient, rect){
|
|
268
271
|
this.enqueueOperation(function(state, completion, target){
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
var r0 = 0;
|
|
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);
|
|
282
|
+
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
|
+
);
|
|
274
291
|
var stop;
|
|
275
292
|
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
276
293
|
stop = gradient.stops[i];
|
|
277
294
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
278
295
|
}
|
|
279
296
|
this.canvasContext.fillStyle = canvasGradient;
|
|
280
|
-
this.canvasContext.fillRect(
|
|
297
|
+
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
298
|
+
this.canvasContext.restore();
|
|
299
|
+
completion.call(target);
|
|
300
|
+
});
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
drawLinearGradientStroke: function(gradient, path){
|
|
304
|
+
this.enqueueOperation(function(state, completion, target){
|
|
305
|
+
var rect = path.boundingRect;
|
|
306
|
+
this.canvasContext.save();
|
|
307
|
+
this.addPath(path);
|
|
308
|
+
var canvasGradient = this.canvasContext.createLinearGradient(
|
|
309
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
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
|
+
}
|
|
319
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
320
|
+
this.canvasContext.stroke();
|
|
321
|
+
this.canvasContext.restore();
|
|
281
322
|
completion.call(target);
|
|
282
323
|
});
|
|
324
|
+
this.beginPath();
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
drawRadialGradientStroke: function(gradient, path){
|
|
328
|
+
this.enqueueOperation(function(state, completion, target){
|
|
329
|
+
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
|
+
this.canvasContext.save();
|
|
341
|
+
this.addPath(path);
|
|
342
|
+
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
343
|
+
start.x,
|
|
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
|
+
}
|
|
355
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
356
|
+
this.canvasContext.stroke();
|
|
357
|
+
this.canvasContext.restore();
|
|
358
|
+
completion.call(target);
|
|
359
|
+
});
|
|
360
|
+
this.beginPath();
|
|
283
361
|
},
|
|
284
362
|
|
|
285
363
|
// ----------------------------------------------------------------------
|
|
@@ -17,6 +17,14 @@
|
|
|
17
17
|
/* global UICollectionView */
|
|
18
18
|
"use strict";
|
|
19
19
|
|
|
20
|
+
JSProtocol("UICollectionViewGridLayoutDelegate", JSProtocol, {
|
|
21
|
+
|
|
22
|
+
heightForCollectionViewHeaderInSection: function(collectionView, sectionIndex){},
|
|
23
|
+
heightForCollectionViewFooterInSection: function(collectionView, sectionIndex){},
|
|
24
|
+
cellSizeForCollectionViewInSection: function(collectionView, sectionIndex){},
|
|
25
|
+
|
|
26
|
+
});
|
|
27
|
+
|
|
20
28
|
JSClass("UICollectionViewGridLayout", UICollectionViewLayout, {
|
|
21
29
|
|
|
22
30
|
init: function(){
|
|
@@ -228,33 +236,63 @@ JSClass("UICollectionViewGridLayout", UICollectionViewLayout, {
|
|
|
228
236
|
var rowOffset = 0;
|
|
229
237
|
var sectionHeaderAndSpacingHeight = 0;
|
|
230
238
|
var sectionFooterAndSpacingHeight = 0;
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
sectionFooterAndSpacingHeight= this._sectionFooterHeight + this._sectionFooterSpacing;
|
|
236
|
-
}
|
|
239
|
+
var sectionHeaderHeight;
|
|
240
|
+
var sectionFooterHeight;
|
|
241
|
+
var sectionCellSize;
|
|
242
|
+
var sectionColumns;
|
|
237
243
|
for (sectionIndex = 0; sectionIndex < sectionCount; ++sectionIndex){
|
|
244
|
+
sectionHeaderHeight = this._sectionHeaderHeight;
|
|
245
|
+
sectionFooterHeight = this._sectionFooterHeight;
|
|
246
|
+
sectionCellSize = this._cellSize;
|
|
247
|
+
if (this.collectionView.delegate && this.collectionView.delegate.heightForCollectionViewHeaderInSection){
|
|
248
|
+
sectionHeaderHeight = this.collectionView.delegate.heightForCollectionViewHeaderInSection(this.collectionView, sectionIndex);
|
|
249
|
+
}
|
|
250
|
+
if (this.collectionView.delegate && this.collectionView.delegate.heightForCollectionViewFooterInSection){
|
|
251
|
+
sectionFooterHeight = this.collectionView.delegate.heightForCollectionViewFooterInSection(this.collectionView, sectionIndex);
|
|
252
|
+
}
|
|
253
|
+
if (this.collectionView.delegate && this.collectionView.delegate.cellSizeForCollectionViewInSection){
|
|
254
|
+
sectionCellSize = this.collectionView.delegate.cellSizeForCollectionViewInSection(this.collectionView, sectionIndex);
|
|
255
|
+
}
|
|
256
|
+
if (sectionHeaderHeight > 0){
|
|
257
|
+
sectionHeaderAndSpacingHeight = sectionHeaderHeight + this._sectionHeaderSpacing;
|
|
258
|
+
}
|
|
259
|
+
if (sectionFooterHeight > 0){
|
|
260
|
+
sectionFooterAndSpacingHeight= sectionFooterHeight + this._sectionFooterSpacing;
|
|
261
|
+
}
|
|
262
|
+
if (sectionCellSize.width != this._cellSize.width){
|
|
263
|
+
columnCount = Math.max(1, Math.floor((availableWidth + this._columnSpacing) / (sectionCellSize.width + this._columnSpacing)));
|
|
264
|
+
x = this._collectionInsets.left + this._sectionInsets.left;
|
|
265
|
+
sectionColumns = [];
|
|
266
|
+
for (columnIndex = 0; columnIndex < columnCount; ++columnIndex){
|
|
267
|
+
sectionColumns.push({x: x});
|
|
268
|
+
x += sectionCellSize.width + this._columnSpacing;
|
|
269
|
+
}
|
|
270
|
+
}else{
|
|
271
|
+
columnCount = this._cachedLayout.columns.length;
|
|
272
|
+
sectionColumns = this._cachedLayout.columns;
|
|
273
|
+
}
|
|
238
274
|
cellCount = this.collectionView.dataSource.numberOfCellsInCollectionViewSection(this.collectionView, sectionIndex);
|
|
239
275
|
rowCount = Math.ceil(cellCount / columnCount);
|
|
240
276
|
size.height = this._sectionInsets.height + sectionHeaderAndSpacingHeight + sectionFooterAndSpacingHeight;
|
|
241
|
-
size.height += rowCount *
|
|
277
|
+
size.height += rowCount * sectionCellSize.height + (rowCount - 1) * this._rowSpacing;
|
|
242
278
|
this._cachedLayout.sections.push({
|
|
243
279
|
rowOffset: rowOffset,
|
|
244
280
|
cellCount: cellCount,
|
|
245
281
|
rowCount: rowCount,
|
|
246
282
|
frame: JSRect(origin, size),
|
|
283
|
+
columns: sectionColumns,
|
|
284
|
+
cellSize: sectionCellSize,
|
|
247
285
|
headerFrame: JSRect(
|
|
248
286
|
origin.x + this._sectionInsets.left,
|
|
249
287
|
origin.y + this._sectionInsets.top,
|
|
250
288
|
availableWidth,
|
|
251
|
-
|
|
289
|
+
sectionHeaderHeight
|
|
252
290
|
),
|
|
253
291
|
footerFrame: JSRect(
|
|
254
292
|
origin.x + this._sectionInsets.left,
|
|
255
|
-
origin.y + size.height - this._sectionInsets.bottom -
|
|
293
|
+
origin.y + size.height - this._sectionInsets.bottom - sectionFooterHeight,
|
|
256
294
|
availableWidth,
|
|
257
|
-
|
|
295
|
+
sectionFooterHeight
|
|
258
296
|
),
|
|
259
297
|
cellsFrame: JSRect(
|
|
260
298
|
origin.x + this._sectionInsets.left,
|
|
@@ -295,7 +333,7 @@ JSClass("UICollectionViewGridLayout", UICollectionViewLayout, {
|
|
|
295
333
|
if (this._cachedLayout.headerFrame.size.height > 0 && (this._headersStickToTop || rect.intersectsRect(this._cachedLayout.headerFrame))){
|
|
296
334
|
attributes.push(this.layoutAttributesForSupplimentaryViewAtIndexPath(JSIndexPath([]), UICollectionViewGridLayout.SupplimentaryKind.header));
|
|
297
335
|
}
|
|
298
|
-
var columnCount
|
|
336
|
+
var columnCount;
|
|
299
337
|
var columnIndex;
|
|
300
338
|
var sectionIndex;
|
|
301
339
|
var sectionCount = this._cachedLayout.sections.length;
|
|
@@ -304,12 +342,14 @@ JSClass("UICollectionViewGridLayout", UICollectionViewLayout, {
|
|
|
304
342
|
var y;
|
|
305
343
|
var y0 = rect.origin.y;
|
|
306
344
|
var y1 = rect.origin.y + rect.size.height;
|
|
307
|
-
var rowHeight
|
|
345
|
+
var rowHeight;
|
|
308
346
|
var rowIndex;
|
|
309
347
|
var attrs;
|
|
310
348
|
// FIXME: can do a more efficient search of sections
|
|
311
349
|
for (sectionIndex = 0; sectionIndex < sectionCount; ++sectionIndex){
|
|
312
350
|
sectionLayout = this._cachedLayout.sections[sectionIndex];
|
|
351
|
+
columnCount = sectionLayout.columns.length;
|
|
352
|
+
rowHeight = sectionLayout.cellSize.height + this._rowSpacing;
|
|
313
353
|
if (sectionLayout.frame.size.height > 0 && rect.intersectsRect(sectionLayout.frame)){
|
|
314
354
|
if (this._showsSectionBackgroundViews){
|
|
315
355
|
attributes.push(this.layoutAttributesForSupplimentaryViewAtIndexPath(JSIndexPath([sectionIndex]), UICollectionViewGridLayout.SupplimentaryKind.background));
|
|
@@ -326,10 +366,10 @@ JSClass("UICollectionViewGridLayout", UICollectionViewLayout, {
|
|
|
326
366
|
for (; rowIndex < sectionLayout.rowCount && y < y1; ++rowIndex, y += rowHeight){
|
|
327
367
|
for (columnIndex = 0; columnIndex < columnCount && indexPath.row < sectionLayout.cellCount; ++columnIndex, ++indexPath.row){
|
|
328
368
|
attrs = UICollectionViewLayoutAttributes.initCellAtIndexPath(indexPath, JSRect(
|
|
329
|
-
|
|
369
|
+
sectionLayout.columns[columnIndex].x,
|
|
330
370
|
y,
|
|
331
|
-
|
|
332
|
-
|
|
371
|
+
sectionLayout.cellSize.width,
|
|
372
|
+
sectionLayout.cellSize.height
|
|
333
373
|
));
|
|
334
374
|
attrs.rowIndex = sectionLayout.rowOffset + rowIndex;
|
|
335
375
|
attrs.columnIndex = columnIndex;
|
|
@@ -350,16 +390,16 @@ JSClass("UICollectionViewGridLayout", UICollectionViewLayout, {
|
|
|
350
390
|
|
|
351
391
|
layoutAttributesForCellAtIndexPath: function(indexPath){
|
|
352
392
|
var sectionLayout = this._cachedLayout.sections[indexPath.section];
|
|
353
|
-
var columnCount =
|
|
393
|
+
var columnCount = sectionLayout.columns.length;
|
|
354
394
|
var rowIndex = Math.floor(indexPath.row / columnCount);
|
|
355
395
|
var columnIndex = indexPath.row % columnCount;
|
|
356
396
|
var origin = JSPoint(
|
|
357
|
-
|
|
358
|
-
sectionLayout.cellsFrame.origin.y + rowIndex * (
|
|
397
|
+
sectionLayout.columns[columnIndex].x,
|
|
398
|
+
sectionLayout.cellsFrame.origin.y + rowIndex * (sectionLayout.cellSize.height + this._rowSpacing)
|
|
359
399
|
);
|
|
360
400
|
var frame = JSRect(
|
|
361
401
|
origin,
|
|
362
|
-
|
|
402
|
+
sectionLayout.cellSize
|
|
363
403
|
);
|
|
364
404
|
var attributes = UICollectionViewLayoutAttributes.initCellAtIndexPath(indexPath, frame);
|
|
365
405
|
attributes.rowIndex = sectionLayout.rowOffset + rowIndex;
|
|
@@ -169,6 +169,7 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
169
169
|
this[methodName](layer);
|
|
170
170
|
}
|
|
171
171
|
this.propertiesNeedingUpdate = {};
|
|
172
|
+
this.renderScale = layer._renderScale;
|
|
172
173
|
|
|
173
174
|
if (this.needsCustomDisplay){
|
|
174
175
|
layer._drawInContext(this);
|
|
@@ -412,13 +413,14 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
412
413
|
return this.element.ownerDocument.defaultView.devicePixelRatio || 1;
|
|
413
414
|
},
|
|
414
415
|
|
|
416
|
+
renderScale: 1,
|
|
417
|
+
|
|
415
418
|
getCanvasContext: function(){
|
|
416
419
|
if (!this._canvasContext){
|
|
417
|
-
var scale = this.deviceScale;
|
|
418
|
-
// FIXME: scale should account for any transform ancestor layers
|
|
420
|
+
var scale = this.deviceScale * this.renderScale;
|
|
419
421
|
var canvas = this._dequeueReusableCanvasElement();
|
|
420
|
-
canvas.width = this.bounds.size.width * scale;
|
|
421
|
-
canvas.height = this.bounds.size.height * scale;
|
|
422
|
+
canvas.width = Math.ceil(this.bounds.size.width * scale);
|
|
423
|
+
canvas.height = Math.ceil(this.bounds.size.height * scale);
|
|
422
424
|
this._insertChildElement(canvas);
|
|
423
425
|
this._canvasContext = canvas.getContext('2d');
|
|
424
426
|
this._canvasContext.save();
|
|
@@ -685,32 +687,104 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
685
687
|
|
|
686
688
|
drawLinearGradient: function(gradient, rect){
|
|
687
689
|
this.canvasContext.save();
|
|
688
|
-
this.canvasContext.
|
|
689
|
-
|
|
690
|
-
|
|
690
|
+
var canvasGradient = this.canvasContext.createLinearGradient(
|
|
691
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
692
|
+
rect.origin.y + gradient.start.y * rect.size.height,
|
|
693
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
694
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
695
|
+
);
|
|
691
696
|
var stop;
|
|
692
697
|
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
693
698
|
stop = gradient.stops[i];
|
|
694
699
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
695
700
|
}
|
|
696
701
|
this.canvasContext.fillStyle = canvasGradient;
|
|
697
|
-
this.canvasContext.fillRect(
|
|
702
|
+
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
698
703
|
this.canvasContext.restore();
|
|
699
704
|
},
|
|
700
705
|
|
|
701
|
-
drawRadialGradient: function(gradient, rect
|
|
706
|
+
drawRadialGradient: function(gradient, rect){
|
|
707
|
+
var r0 = 0;
|
|
708
|
+
var start = JSPoint(
|
|
709
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
710
|
+
rect.origin.y + gradient.start.y * rect.size.height
|
|
711
|
+
);
|
|
712
|
+
var end = JSPoint(
|
|
713
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
714
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
715
|
+
);
|
|
716
|
+
var r1 = start.distanceToPoint(end);
|
|
702
717
|
this.canvasContext.save();
|
|
703
|
-
this.canvasContext.
|
|
704
|
-
|
|
705
|
-
|
|
718
|
+
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
719
|
+
start.x,
|
|
720
|
+
start.y,
|
|
721
|
+
r0,
|
|
722
|
+
start.x,
|
|
723
|
+
start.y,
|
|
724
|
+
r1
|
|
725
|
+
);
|
|
706
726
|
var stop;
|
|
707
727
|
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
708
728
|
stop = gradient.stops[i];
|
|
709
729
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
710
730
|
}
|
|
711
731
|
this.canvasContext.fillStyle = canvasGradient;
|
|
712
|
-
this.canvasContext.fillRect(
|
|
732
|
+
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
733
|
+
this.canvasContext.restore();
|
|
734
|
+
},
|
|
735
|
+
|
|
736
|
+
drawLinearGradientStroke: function(gradient, path){
|
|
737
|
+
var rect = path.boundingRect;
|
|
738
|
+
this.canvasContext.save();
|
|
739
|
+
this.addPath(path);
|
|
740
|
+
var canvasGradient = this.canvasContext.createLinearGradient(
|
|
741
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
742
|
+
rect.origin.y + gradient.start.y * rect.size.height,
|
|
743
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
744
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
745
|
+
);
|
|
746
|
+
var stop;
|
|
747
|
+
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
748
|
+
stop = gradient.stops[i];
|
|
749
|
+
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
750
|
+
}
|
|
751
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
752
|
+
this.canvasContext.stroke();
|
|
713
753
|
this.canvasContext.restore();
|
|
754
|
+
this.beginPath();
|
|
755
|
+
},
|
|
756
|
+
|
|
757
|
+
drawRadialGradientStroke: function(gradient, path){
|
|
758
|
+
var rect = path.boundingRect;
|
|
759
|
+
var r0 = 0;
|
|
760
|
+
var start = JSPoint(
|
|
761
|
+
rect.origin.x + gradient.start.x * rect.size.width,
|
|
762
|
+
rect.origin.y + gradient.start.y * rect.size.height
|
|
763
|
+
);
|
|
764
|
+
var end = JSPoint(
|
|
765
|
+
rect.origin.x + gradient.end.x * rect.size.width,
|
|
766
|
+
rect.origin.y + gradient.end.y * rect.size.height
|
|
767
|
+
);
|
|
768
|
+
var r1 = start.distanceToPoint(end);
|
|
769
|
+
this.canvasContext.save();
|
|
770
|
+
this.addPath(path);
|
|
771
|
+
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
772
|
+
start.x,
|
|
773
|
+
start.y,
|
|
774
|
+
r0,
|
|
775
|
+
start.x,
|
|
776
|
+
start.y,
|
|
777
|
+
r1
|
|
778
|
+
);
|
|
779
|
+
var stop;
|
|
780
|
+
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
781
|
+
stop = gradient.stops[i];
|
|
782
|
+
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
783
|
+
}
|
|
784
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
785
|
+
this.canvasContext.stroke();
|
|
786
|
+
this.canvasContext.restore();
|
|
787
|
+
this.beginPath();
|
|
714
788
|
},
|
|
715
789
|
|
|
716
790
|
// ----------------------------------------------------------------------
|
|
@@ -769,6 +769,12 @@ JSClass("UILayer", JSObject, {
|
|
|
769
769
|
// MARK: - Display
|
|
770
770
|
|
|
771
771
|
_needsDisplay: false,
|
|
772
|
+
renderScale: JSDynamicProperty("_renderScale", 1),
|
|
773
|
+
|
|
774
|
+
setRenderScale: function(renderScale){
|
|
775
|
+
this._renderScale = renderScale;
|
|
776
|
+
this.setNeedsDisplay();
|
|
777
|
+
},
|
|
772
778
|
|
|
773
779
|
setNeedsDisplay: function(){
|
|
774
780
|
if (this._displayServer !== null){
|