@breakside/jskit 2026.8.0 → 2026.10.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/JSColor.js +5 -0
- package/Frameworks/Foundation.jsframework/JS/JSPath.js +482 -49
- package/Frameworks/Foundation.jsframework/JS/JSRect.js +12 -0
- package/Frameworks/Foundation.jsframework/JS/JSSpec.js +5 -1
- package/Frameworks/Foundation.jsframework/JS/String+JS.js +78 -2
- 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/DocCommand.js +5 -2
- package/Node/Docs/DocClass.js +2 -2
- package/Node/Docs/DocComponent.js +6 -4
- package/Node/Docs/DocDictionaryProperty.js +2 -2
- package/Node/Docs/DocEnumOption.js +2 -2
- package/Node/Docs/DocFunction.js +2 -2
- package/Node/Docs/DocProperty.js +2 -2
- package/Node/Docs/DocProtocol.js +1 -1
- package/Node/Docs/DocSpec.js +1 -1
- package/Node/Docs/DocSpecProperty.js +2 -2
- package/Node/Docs/DocTopicBasedComponent.js +2 -2
- package/Node/Documentation.js +10 -2
- package/Node/HTMLBuilder.js +3 -1
- package/Node/HTMLProjectServer.js +39 -1
- package/Node/io.breakside.jskit-bundle.js +4 -4
- package/Resources/doc-default.css +4 -4
- 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/JSColor.js +5 -0
- package/Root/Frameworks/Foundation/JSPath.js +482 -49
- package/Root/Frameworks/Foundation/JSRect.js +12 -0
- package/Root/Frameworks/Foundation/JSSpec.js +5 -1
- package/Root/Frameworks/Foundation/String+JS.js +78 -2
- 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/UIApplication.js +5 -1
- package/Root/Frameworks/UIKit/UIHTMLApplication.js +24 -0
- package/Root/Frameworks/UIKit/UIHTMLWindowServer.js +17 -3
- package/Root/Frameworks/UIKit/UIKit.js +2 -0
- package/Root/Frameworks/UIKit/UIListView.js +11 -3
- package/Root/Frameworks/UIKit/UIOutlineView.js +65 -5
- package/Root/Frameworks/UIKit/UIPopupWindow.js +15 -5
- package/Root/Frameworks/UIKit/UITextAction.js +16 -0
- package/Root/Frameworks/UIKit/UITextActionsMenu.js +95 -0
- package/Root/Frameworks/UIKit/UITextEditor.js +57 -7
- package/Root/Frameworks/UIKit/UITextField.js +102 -0
- package/Root/Frameworks/UIKit/en.lproj/Localizable.strings.yaml +4 -1
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
|
@@ -838,81 +838,514 @@ JSClass("JSPath", JSObject, {
|
|
|
838
838
|
return JSRect(min, JSSize(max.x - min.x, max.y - min.y));
|
|
839
839
|
},
|
|
840
840
|
|
|
841
|
+
intersectsPath: function(other, fillRule){
|
|
842
|
+
var boundingRect = this.boundingRect;
|
|
843
|
+
// no need to check if bounding rect don't intersect
|
|
844
|
+
if (!boundingRect.intersectsRect(other.boundingRect)){
|
|
845
|
+
return false;
|
|
846
|
+
}
|
|
847
|
+
// are any of our points inside other?
|
|
848
|
+
var subpath;
|
|
849
|
+
var segment;
|
|
850
|
+
var i, l;
|
|
851
|
+
var j, k;
|
|
852
|
+
var point;
|
|
853
|
+
for (i = 0, l = this.subpaths.length; i < l; ++i){
|
|
854
|
+
subpath = this.subpaths[i];
|
|
855
|
+
if (subpath.segments.length > 0){
|
|
856
|
+
if (other.containsPoint(subpath.firstPoint, fillRule)){
|
|
857
|
+
return true;
|
|
858
|
+
}
|
|
859
|
+
for (j = 0, k = subpath.segments.length; j < k; ++j){
|
|
860
|
+
segment = subpath.segments[j];
|
|
861
|
+
if (segment.type == JSPath.SegmentType.line){
|
|
862
|
+
if (other.containsPoint(segment.end, fillRule)){
|
|
863
|
+
return true;
|
|
864
|
+
}
|
|
865
|
+
}else if (segment.type == JSPath.SegmentType.curve){
|
|
866
|
+
if (other.containsPoint(segment.curve.p2, fillRule)){
|
|
867
|
+
return true;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
// are any of other's points iside us?
|
|
874
|
+
for (i = 0, l = other.subpaths.length; i < l; ++i){
|
|
875
|
+
subpath = other.subpaths[i];
|
|
876
|
+
if (subpath.segments.length > 0){
|
|
877
|
+
if (this.containsPoint(subpath.firstPoint, fillRule)){
|
|
878
|
+
return true;
|
|
879
|
+
}
|
|
880
|
+
for (j = 0, k = subpath.segments.length; j < k; ++j){
|
|
881
|
+
segment = subpath.segments[j];
|
|
882
|
+
if (segment.type == JSPath.SegmentType.line){
|
|
883
|
+
if (this.containsPoint(segment.end, fillRule)){
|
|
884
|
+
return true;
|
|
885
|
+
}
|
|
886
|
+
}else if (segment.type == JSPath.SegmentType.curve){
|
|
887
|
+
if (this.containsPoint(segment.curve.p2, fillRule)){
|
|
888
|
+
return true;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
// Could still have situations where curves intersect without
|
|
895
|
+
// points contained within each other, but not significant enough
|
|
896
|
+
// to worry about for most shapes. Will refined if needed.
|
|
897
|
+
return false;
|
|
898
|
+
},
|
|
899
|
+
|
|
900
|
+
pathConvertedToTransform: function(transform){
|
|
901
|
+
var path = JSPath.init();
|
|
902
|
+
var subpath0;
|
|
903
|
+
var segment0;
|
|
904
|
+
var subpath1;
|
|
905
|
+
var segment1;
|
|
906
|
+
var point0;
|
|
907
|
+
var point1;
|
|
908
|
+
var i, l;
|
|
909
|
+
var j, k;
|
|
910
|
+
for (i = 0, l = this.subpaths.length; i < l; ++i){
|
|
911
|
+
subpath0 = this.subpaths[i];
|
|
912
|
+
if (subpath0.segments.length > 0){
|
|
913
|
+
point0 = subpath0.firstPoint;
|
|
914
|
+
point1 = transform.convertPointToTransform(point0);
|
|
915
|
+
subpath1 = Subpath(point1);
|
|
916
|
+
path.subpaths.push(subpath1);
|
|
917
|
+
for (j = 0, k = subpath0.segments.length; j < k; ++j){
|
|
918
|
+
segment0 = subpath0.segments[j];
|
|
919
|
+
if (segment0.type == JSPath.SegmentType.line){
|
|
920
|
+
segment1 = {
|
|
921
|
+
type: JSPath.SegmentType.line,
|
|
922
|
+
end: transform.convertPointToTransform(segment0.end)
|
|
923
|
+
};
|
|
924
|
+
subpath1.segments.push(segment1);
|
|
925
|
+
point1 = segment1.end;
|
|
926
|
+
}else if (segment0.type == JSPath.SegmentType.curve){
|
|
927
|
+
segment1 = {
|
|
928
|
+
type: JSPath.SegmentType.curve,
|
|
929
|
+
curve: JSCubicBezier(
|
|
930
|
+
point1,
|
|
931
|
+
transform.convertPointToTransform(segment0.curve.cp1),
|
|
932
|
+
transform.convertPointToTransform(segment0.curve.cp2),
|
|
933
|
+
transform.convertPointToTransform(segment0.curve.p2)
|
|
934
|
+
)
|
|
935
|
+
};
|
|
936
|
+
subpath1.segments.push(segment1);
|
|
937
|
+
point1 = segment1.curve.p2;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
subpath1.closed = subpath0.closed;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return path;
|
|
944
|
+
},
|
|
945
|
+
|
|
946
|
+
pathConvertedFromTransform: function(transform){
|
|
947
|
+
var path = JSPath.init();
|
|
948
|
+
var subpath0;
|
|
949
|
+
var segment0;
|
|
950
|
+
var subpath1;
|
|
951
|
+
var segment1;
|
|
952
|
+
var point0;
|
|
953
|
+
var point1;
|
|
954
|
+
var i, l;
|
|
955
|
+
var j, k;
|
|
956
|
+
for (i = 0, l = this.subpaths.length; i < l; ++i){
|
|
957
|
+
subpath0 = this.subpaths[i];
|
|
958
|
+
if (subpath0.segments.length > 0){
|
|
959
|
+
point0 = subpath0.firstPoint;
|
|
960
|
+
point1 = transform.convertPointFromTransform(point0);
|
|
961
|
+
subpath1 = Subpath(point1);
|
|
962
|
+
path.subpaths.push(subpath1);
|
|
963
|
+
for (j = 0, k = subpath0.segments.length; j < k; ++j){
|
|
964
|
+
segment0 = subpath0.segments[j];
|
|
965
|
+
if (segment0.type == JSPath.SegmentType.line){
|
|
966
|
+
segment1 = {
|
|
967
|
+
type: JSPath.SegmentType.line,
|
|
968
|
+
end: transform.convertPointFromTransform(segment0.end)
|
|
969
|
+
};
|
|
970
|
+
subpath1.segments.push(segment1);
|
|
971
|
+
point1 = segment1.end;
|
|
972
|
+
}else if (segment0.type == JSPath.SegmentType.curve){
|
|
973
|
+
segment1 = {
|
|
974
|
+
type: JSPath.SegmentType.curve,
|
|
975
|
+
curve: JSCubicBezier(
|
|
976
|
+
point1,
|
|
977
|
+
transform.convertPointFromTransform(segment0.curve.cp1),
|
|
978
|
+
transform.convertPointFromTransform(segment0.curve.cp2),
|
|
979
|
+
transform.convertPointFromTransform(segment0.curve.p2)
|
|
980
|
+
)
|
|
981
|
+
};
|
|
982
|
+
subpath1.segments.push(segment1);
|
|
983
|
+
point1 = segment1.curve.p2;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
subpath1.closed = subpath0.closed;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
return path;
|
|
990
|
+
},
|
|
991
|
+
|
|
841
992
|
initWithSVGPathData: function(svgPathData){
|
|
993
|
+
// TODO: Q, q, T, t, A, a
|
|
994
|
+
//
|
|
995
|
+
// - All instructions are expressed as one character (e.g., a moveto
|
|
996
|
+
// is expressed as an M).
|
|
997
|
+
// - Superfluous white space and separators such as commas can be
|
|
998
|
+
// eliminated (e.g., "M 100 100 L 200 200" contains unnecessary spaces
|
|
999
|
+
// and could be expressed more compactly as "M100 100L200 200").
|
|
1000
|
+
// - The command letter can be eliminated on subsequent commands if the
|
|
1001
|
+
// same command is used multiple times in a row (e.g., you can drop
|
|
1002
|
+
// the second "L" in "M 100 200 L 200 100 L -100 -200" and use
|
|
1003
|
+
// "M 100 200 L 200 100 -100 -200" instead).
|
|
1004
|
+
// - Relative versions of all commands are available (uppercase means
|
|
1005
|
+
// absolute coordinates, lowercase means relative coordinates).
|
|
1006
|
+
// - Alternate forms of lineto are available to optimize the special
|
|
1007
|
+
// cases of horizontal and vertical lines (absolute and relative).
|
|
1008
|
+
// - Alternate forms of curve are available to optimize the special
|
|
1009
|
+
// cases where some of the control points on the current segment can
|
|
1010
|
+
// be determined automatically from the control points on the previous
|
|
1011
|
+
// segment.
|
|
1012
|
+
// - The processing of the BNF must consume as much of a given BNF
|
|
1013
|
+
// production as possible, stopping at the point when a character is
|
|
1014
|
+
// encountered which no longer satisfies the production. Thus, in the
|
|
1015
|
+
// string "M 100-200", the first coordinate for the "moveto" consumes
|
|
1016
|
+
// the characters "100" and stops upon encountering the minus sign
|
|
1017
|
+
// because the minus sign cannot follow a digit in the production of
|
|
1018
|
+
// a "coordinate". The result is that the first coordinate will be
|
|
1019
|
+
// "100" and the second coordinate will be "-200".
|
|
1020
|
+
// - Similarly, for the string "M 0.6.5", the first coordinate of the
|
|
1021
|
+
// "moveto" consumes the characters "0.6" and stops upon encountering
|
|
1022
|
+
// the second decimal point because the production of a "coordinate"
|
|
1023
|
+
// only allows one decimal point. The result is that the first
|
|
1024
|
+
// coordinate will be "0.6" and the second coordinate will be ".5".
|
|
1025
|
+
// - The general rule for error handling in path data is that the SVG
|
|
1026
|
+
// user agent shall render a 'path' element up to (but not including)
|
|
1027
|
+
// the path command containing the first error...
|
|
1028
|
+
// - If a path data command contains an incorrect set of parameters,
|
|
1029
|
+
// then the given path data command is rendered up to and including
|
|
1030
|
+
// the last correctly defined path segment...
|
|
842
1031
|
if (svgPathData === null || svgPathData === undefined){
|
|
843
1032
|
return null;
|
|
844
1033
|
}
|
|
845
|
-
var
|
|
846
|
-
|
|
847
|
-
});
|
|
1034
|
+
var i = 0;
|
|
1035
|
+
var l = svgPathData.length;
|
|
848
1036
|
this.subpaths = [];
|
|
849
|
-
var part;
|
|
850
1037
|
var subpath = null;
|
|
851
|
-
var
|
|
852
|
-
var
|
|
853
|
-
var cp2;
|
|
1038
|
+
var segment = null;
|
|
1039
|
+
var point = this._currentPoint;
|
|
854
1040
|
var curve;
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
1041
|
+
var previousCommand = null;
|
|
1042
|
+
var command = null;
|
|
1043
|
+
var token = null;
|
|
1044
|
+
var isWhitespace = function(c){
|
|
1045
|
+
return c === " " || c === "\t" || c === "\r" || c === "\n";
|
|
1046
|
+
};
|
|
1047
|
+
var isDigit = function(c){
|
|
1048
|
+
return c >= "0" && c <= "9";
|
|
1049
|
+
};
|
|
1050
|
+
var parseToken = function(){
|
|
1051
|
+
var c;
|
|
1052
|
+
var str;
|
|
1053
|
+
var signAllowed;
|
|
1054
|
+
var decimalAllowed;
|
|
1055
|
+
var exponentAllowed;
|
|
1056
|
+
if (i < l){
|
|
1057
|
+
c = svgPathData[i];
|
|
1058
|
+
while (i < l && isWhitespace(c)){
|
|
1059
|
+
++i;
|
|
1060
|
+
if (i < l){
|
|
1061
|
+
c = svgPathData[i];
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
if (i < l){
|
|
1066
|
+
if (
|
|
1067
|
+
c === "M" || c === "m" ||
|
|
1068
|
+
c === "L" || c === "l" ||
|
|
1069
|
+
c === "C" || c === "c" ||
|
|
1070
|
+
c === "S" || c === "s" ||
|
|
1071
|
+
c === "Z" || c === "z" ||
|
|
1072
|
+
c === "Q" || c === "q" ||
|
|
1073
|
+
c === "T" || c === "t" ||
|
|
1074
|
+
c === "A" || c === "a"
|
|
1075
|
+
){
|
|
1076
|
+
++i;
|
|
1077
|
+
return c;
|
|
1078
|
+
}
|
|
1079
|
+
str = "";
|
|
1080
|
+
signAllowed = true;
|
|
1081
|
+
decimalAllowed = true;
|
|
1082
|
+
exponentAllowed = true;
|
|
1083
|
+
while (i < l){
|
|
1084
|
+
c = svgPathData[i];
|
|
1085
|
+
if ((c === "-" || c === "+") && signAllowed){
|
|
1086
|
+
signAllowed = false;
|
|
1087
|
+
}else if (c === "." && decimalAllowed){
|
|
1088
|
+
decimalAllowed = false;
|
|
1089
|
+
signAllowed = false;
|
|
1090
|
+
}else if ((c === "e" || c === "E") && exponentAllowed && str !== ""){
|
|
1091
|
+
exponentAllowed = false;
|
|
1092
|
+
signAllowed = true;
|
|
1093
|
+
decimalAllowed = true;
|
|
1094
|
+
}else if (isDigit(c)){
|
|
1095
|
+
signAllowed = false;
|
|
1096
|
+
}else{
|
|
1097
|
+
break;
|
|
1098
|
+
}
|
|
1099
|
+
str += c;
|
|
1100
|
+
++i;
|
|
1101
|
+
}
|
|
1102
|
+
if (str === ""){
|
|
1103
|
+
++i;
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
while (i < l && (isWhitespace(c) || c === ",")){
|
|
1107
|
+
++i;
|
|
1108
|
+
if (i < l){
|
|
1109
|
+
c = svgPathData[i];
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
try{
|
|
1113
|
+
return parseFloat(str);
|
|
1114
|
+
}catch (e){
|
|
1115
|
+
return null;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return null;
|
|
1119
|
+
};
|
|
1120
|
+
var tokenBuffer = null;
|
|
1121
|
+
var parseCommand = function(){
|
|
1122
|
+
var command = null;
|
|
1123
|
+
var token = tokenBuffer;
|
|
1124
|
+
tokenBuffer = null;
|
|
1125
|
+
if (token === null){
|
|
1126
|
+
token = parseToken();
|
|
1127
|
+
}
|
|
1128
|
+
if (token !== null){
|
|
1129
|
+
if (typeof(token) === "string"){
|
|
1130
|
+
command = {name: token, values: []};
|
|
1131
|
+
token = parseToken();
|
|
1132
|
+
while (typeof(token) === "number"){
|
|
1133
|
+
command.values.push(token);
|
|
1134
|
+
token = parseToken();
|
|
1135
|
+
}
|
|
1136
|
+
tokenBuffer = token;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
return command;
|
|
1140
|
+
};
|
|
1141
|
+
command = parseCommand();
|
|
1142
|
+
var v;
|
|
1143
|
+
while (command !== null){
|
|
1144
|
+
if (command.name === "M"){
|
|
1145
|
+
if (command.values.length < 2){
|
|
859
1146
|
break;
|
|
860
1147
|
}
|
|
861
|
-
point = JSPoint.
|
|
862
|
-
part = parts.shift();
|
|
863
|
-
point.x = parseFloat(part);
|
|
864
|
-
part = parts.shift();
|
|
865
|
-
point.y = parseFloat(part);
|
|
1148
|
+
point = JSPoint(command.values[0], command.values[1]);
|
|
866
1149
|
subpath = Subpath(point);
|
|
867
1150
|
this.subpaths.push(subpath);
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
1151
|
+
segment = null;
|
|
1152
|
+
// If a moveto is followed by multiple pairs of coordinates,
|
|
1153
|
+
// the subsequent pairs are treated as implicit lineto commands.
|
|
1154
|
+
for (v = 2; v < command.values.length - 1; v += 2){
|
|
1155
|
+
point = JSPoint(command.values[v], command.values[v + 1]);
|
|
1156
|
+
segment = {type: JSPath.SegmentType.line, end: point};
|
|
1157
|
+
subpath.segments.push(segment);
|
|
1158
|
+
}
|
|
1159
|
+
}else if (command.name === "m"){
|
|
1160
|
+
if (command.values.length < 2){
|
|
1161
|
+
break;
|
|
1162
|
+
}
|
|
1163
|
+
if (point !== null){
|
|
1164
|
+
point = point.adding(JSPoint(command.values[0], command.values[1]))
|
|
1165
|
+
}else{
|
|
1166
|
+
point = JSPoint(command.values[0], command.values[1]);
|
|
1167
|
+
}
|
|
1168
|
+
subpath = Subpath(point);
|
|
1169
|
+
this.subpaths.push(subpath);
|
|
1170
|
+
segment = null;
|
|
1171
|
+
// If a moveto is followed by multiple pairs of coordinates,
|
|
1172
|
+
// the subsequent pairs are treated as implicit lineto commands.
|
|
1173
|
+
for (v = 2; v < command.values.length - 1; v += 2){
|
|
1174
|
+
point = point.adding(JSPoint(command.values[v], command.values[v + 1]));
|
|
1175
|
+
segment = {type: JSPath.SegmentType.line, end: point};
|
|
1176
|
+
subpath.segments.push(segment);
|
|
1177
|
+
}
|
|
1178
|
+
}else if (command.name === "L"){
|
|
1179
|
+
if (command.values.length < 2){
|
|
1180
|
+
break;
|
|
1181
|
+
}
|
|
1182
|
+
if (subpath === null){
|
|
1183
|
+
subpath = Subpath(point);
|
|
1184
|
+
this.subpaths.push(subpath);
|
|
1185
|
+
}
|
|
1186
|
+
for (v = 0; v < command.values.length - 1; v += 2){
|
|
1187
|
+
point = JSPoint(command.values[v], command.values[v + 1]);
|
|
1188
|
+
segment = {type: JSPath.SegmentType.line, end: point};
|
|
1189
|
+
subpath.segments.push(segment);
|
|
1190
|
+
}
|
|
1191
|
+
}else if (command.name === "l"){
|
|
1192
|
+
if (command.values.length < 2){
|
|
1193
|
+
break;
|
|
1194
|
+
}
|
|
1195
|
+
if (subpath === null){
|
|
1196
|
+
subpath = Subpath(point);
|
|
1197
|
+
this.subpaths.push(subpath);
|
|
1198
|
+
}
|
|
1199
|
+
for (v = 0; v < command.values.length - 1; v += 2){
|
|
1200
|
+
point = point.adding(JSPoint(command.values[v], command.values[v + 1]));
|
|
1201
|
+
segment = {type: JSPath.SegmentType.line, end: point};
|
|
1202
|
+
subpath.segments.push(segment);
|
|
1203
|
+
}
|
|
1204
|
+
}else if (command.name === "H"){
|
|
1205
|
+
if (command.values.length < 1){
|
|
1206
|
+
break;
|
|
1207
|
+
}
|
|
1208
|
+
if (subpath === null){
|
|
1209
|
+
subpath = Subpath(point);
|
|
1210
|
+
this.subpaths.push(subpath);
|
|
1211
|
+
}
|
|
1212
|
+
for (v = 0; v < command.values.length; v += 1){
|
|
1213
|
+
point = JSPoint(command.values[v], point.y);
|
|
1214
|
+
segment = {type: JSPath.SegmentType.line, end: point};
|
|
1215
|
+
subpath.segments.push(segment);
|
|
1216
|
+
}
|
|
1217
|
+
}else if (command.name === "h"){
|
|
1218
|
+
if (command.values.length < 1){
|
|
1219
|
+
break;
|
|
1220
|
+
}
|
|
1221
|
+
if (subpath === null){
|
|
1222
|
+
subpath = Subpath(point);
|
|
1223
|
+
this.subpaths.push(subpath);
|
|
1224
|
+
}
|
|
1225
|
+
for (v = 0; v < command.values.length; v += 1){
|
|
1226
|
+
point = point.adding(JSPoint(command.values[v], 0));
|
|
1227
|
+
segment = {type: JSPath.SegmentType.line, end: point};
|
|
1228
|
+
subpath.segments.push(segment);
|
|
1229
|
+
}
|
|
1230
|
+
}else if (command.name === "V"){
|
|
1231
|
+
if (command.values.length < 1){
|
|
1232
|
+
break;
|
|
1233
|
+
}
|
|
1234
|
+
if (subpath === null){
|
|
1235
|
+
subpath = Subpath(point);
|
|
1236
|
+
this.subpaths.push(subpath);
|
|
1237
|
+
}
|
|
1238
|
+
for (v = 0; v < command.values.length; v += 1){
|
|
1239
|
+
point = JSPoint(point.x, command.values[v]);
|
|
1240
|
+
segment = {type: JSPath.SegmentType.line, end: point};
|
|
1241
|
+
subpath.segments.push(segment);
|
|
1242
|
+
}
|
|
1243
|
+
}else if (command.name === "v"){
|
|
1244
|
+
if (command.values.length < 1){
|
|
1245
|
+
break;
|
|
1246
|
+
}
|
|
1247
|
+
if (subpath === null){
|
|
1248
|
+
subpath = Subpath(point);
|
|
1249
|
+
this.subpaths.push(subpath);
|
|
1250
|
+
}
|
|
1251
|
+
for (v = 0; v < command.values.length; v += 1){
|
|
1252
|
+
point = point.adding(JSPoint(0, command.values[v]));
|
|
1253
|
+
segment = {type: JSPath.SegmentType.line, end: point};
|
|
1254
|
+
subpath.segments.push(segment);
|
|
1255
|
+
}
|
|
1256
|
+
}else if (command.name === "C"){
|
|
1257
|
+
if (command.values.length < 6){
|
|
1258
|
+
break;
|
|
1259
|
+
}
|
|
1260
|
+
if (subpath === null){
|
|
1261
|
+
subpath = Subpath(point);
|
|
1262
|
+
this.subpaths.push(subpath);
|
|
1263
|
+
}
|
|
1264
|
+
for (v = 0; v < command.values.length - 5; v += 6){
|
|
1265
|
+
curve = JSCubicBezier(
|
|
1266
|
+
point,
|
|
1267
|
+
JSPoint(command.values[v], command.values[v + 1]),
|
|
1268
|
+
JSPoint(command.values[v + 2], command.values[v + 3]),
|
|
1269
|
+
JSPoint(command.values[v + 4], command.values[v + 5])
|
|
1270
|
+
);
|
|
1271
|
+
segment = {type: JSPath.SegmentType.curve, curve: curve};
|
|
1272
|
+
subpath.segments.push(segment);
|
|
1273
|
+
point = curve.p2;
|
|
1274
|
+
}
|
|
1275
|
+
}else if (command.name === "c"){
|
|
1276
|
+
if (command.values.length < 6){
|
|
1277
|
+
break;
|
|
1278
|
+
}
|
|
1279
|
+
if (subpath === null){
|
|
1280
|
+
subpath = Subpath(point);
|
|
1281
|
+
this.subpaths.push(subpath);
|
|
1282
|
+
}
|
|
1283
|
+
for (v = 0; v < command.values.length - 5; v += 6){
|
|
1284
|
+
curve = JSCubicBezier(
|
|
1285
|
+
point,
|
|
1286
|
+
point.adding(JSPoint(command.values[v], command.values[v + 1])),
|
|
1287
|
+
point.adding(JSPoint(command.values[v + 2], command.values[v + 3])),
|
|
1288
|
+
point.adding(JSPoint(command.values[v + 4], command.values[v + 5]))
|
|
1289
|
+
);
|
|
1290
|
+
segment = {type: JSPath.SegmentType.curve, curve: curve};
|
|
1291
|
+
subpath.segments.push(segment);
|
|
1292
|
+
point = curve.p2;
|
|
1293
|
+
}
|
|
1294
|
+
}else if (command.name === "S"){
|
|
1295
|
+
if (command.values.length < 4){
|
|
871
1296
|
break;
|
|
872
1297
|
}
|
|
873
1298
|
if (subpath === null){
|
|
874
1299
|
subpath = Subpath(point);
|
|
875
1300
|
this.subpaths.push(subpath);
|
|
876
1301
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
1302
|
+
for (v = 0; v < command.values.length - 3; v += 4){
|
|
1303
|
+
curve = JSCubicBezier(
|
|
1304
|
+
point,
|
|
1305
|
+
point,
|
|
1306
|
+
JSPoint(command.values[v + 1], command.values[v + 2]),
|
|
1307
|
+
JSPoint(command.values[v + 3], command.values[v + 4])
|
|
1308
|
+
);
|
|
1309
|
+
if (previousCommand !== null && (previousCommand.name === "C" || previousCommand.name === "c" || previousCommand.name === "S" || previousCommand.name === "s")){
|
|
1310
|
+
curve.cp1 = point.adding(segment.curve.p2.subtracting(segment.curve.cp2));
|
|
1311
|
+
}
|
|
1312
|
+
segment = {type: JSPath.SegmentType.curve, curve: curve};
|
|
1313
|
+
subpath.segments.push(segment);
|
|
1314
|
+
point = curve.p2;
|
|
1315
|
+
}
|
|
1316
|
+
}else if (command.name === "s"){
|
|
1317
|
+
if (command.values.length < 4){
|
|
886
1318
|
break;
|
|
887
1319
|
}
|
|
888
1320
|
if (subpath === null){
|
|
889
1321
|
subpath = Subpath(point);
|
|
890
1322
|
this.subpaths.push(subpath);
|
|
891
1323
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
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"){
|
|
1324
|
+
for (v = 0; v < command.values.length - 3; v += 4){
|
|
1325
|
+
curve = JSCubicBezier(
|
|
1326
|
+
point,
|
|
1327
|
+
point,
|
|
1328
|
+
point.adding(JSPoint(command.values[v + 1], command.values[v + 2])),
|
|
1329
|
+
point.adding(JSPoint(command.values[v + 3], command.values[v + 4]))
|
|
1330
|
+
);
|
|
1331
|
+
if (previousCommand !== null && (previousCommand.name === "C" || previousCommand.name === "c" || previousCommand.name === "S" || previousCommand.name === "s")){
|
|
1332
|
+
curve.cp1 = point.adding(segment.curve.p2.subtracting(segment.curve.cp2));
|
|
1333
|
+
}
|
|
1334
|
+
subpath.segments.push({type: JSPath.SegmentType.curve, curve: curve});
|
|
1335
|
+
point = curve.p2;
|
|
1336
|
+
}
|
|
1337
|
+
}else if (command.name === "Z" || command.name === "z"){
|
|
910
1338
|
if (subpath !== null){
|
|
911
1339
|
subpath.closed = true;
|
|
912
1340
|
subpath = null;
|
|
913
1341
|
}
|
|
1342
|
+
}else{
|
|
1343
|
+
break;
|
|
914
1344
|
}
|
|
1345
|
+
previousCommand = command;
|
|
1346
|
+
command = parseCommand();
|
|
915
1347
|
}
|
|
1348
|
+
this._currentPoint = point;
|
|
916
1349
|
},
|
|
917
1350
|
|
|
918
1351
|
svgPathData: function(){
|
|
@@ -923,14 +1356,14 @@ JSClass("JSPath", JSObject, {
|
|
|
923
1356
|
var data = "";
|
|
924
1357
|
for (i = 0, l = this.subpaths.length; i < l; ++i){
|
|
925
1358
|
subpath = this.subpaths[i];
|
|
1359
|
+
data += "M %0.f %0.f ".sprintf(subpath.firstPoint.x, subpath.firstPoint.y);
|
|
926
1360
|
if (subpath.segments.length > 0){
|
|
927
|
-
data += "M %f %f ".sprintf(subpath.firstPoint.x, subpath.firstPoint.y);
|
|
928
1361
|
for (j = 0, k = subpath.segments.length; j < k; ++j){
|
|
929
1362
|
segment = subpath.segments[j];
|
|
930
1363
|
if (segment.type == JSPath.SegmentType.line){
|
|
931
|
-
data += "L %f %f ".sprintf(segment.end.x, segment.end.y);
|
|
1364
|
+
data += "L %0.f %0.f ".sprintf(segment.end.x, segment.end.y);
|
|
932
1365
|
}else if (segment.type == JSPath.SegmentType.curve){
|
|
933
|
-
data += "C %f %f %f %f %f %f ".sprintf(
|
|
1366
|
+
data += "C %0.f %0.f %0.f %0.f %0.f %0.f ".sprintf(
|
|
934
1367
|
segment.curve.cp1.x,
|
|
935
1368
|
segment.curve.cp1.y,
|
|
936
1369
|
segment.curve.cp2.x,
|
|
@@ -77,6 +77,18 @@ JSRect.prototype = {
|
|
|
77
77
|
return JSRect(origin, size);
|
|
78
78
|
},
|
|
79
79
|
|
|
80
|
+
unioningRect: function(other){
|
|
81
|
+
var origin = JSPoint(
|
|
82
|
+
Math.min(this.origin.x, other.origin.x),
|
|
83
|
+
Math.min(this.origin.y, other.origin.y)
|
|
84
|
+
);
|
|
85
|
+
var size = JSSize(
|
|
86
|
+
Math.max(0, Math.max(this.origin.x + this.size.width, other.origin.x + other.size.width) - origin.x),
|
|
87
|
+
Math.max(0, Math.max(this.origin.y + this.size.height, other.origin.y + other.size.height) - origin.y)
|
|
88
|
+
);
|
|
89
|
+
return JSRect(origin, size);
|
|
90
|
+
},
|
|
91
|
+
|
|
80
92
|
isEqual: function(other){
|
|
81
93
|
return this.origin.isEqual(other.origin) && this.size.isEqual(other.size);
|
|
82
94
|
},
|
|
@@ -177,7 +177,11 @@ JSClass("JSSpec", JSObject, {
|
|
|
177
177
|
return this._root.valueForKey(value.substr(1), type, allocatedObject);
|
|
178
178
|
}
|
|
179
179
|
if (prefix == '@'){
|
|
180
|
-
|
|
180
|
+
value = JSSpec.initWithResource(value.substr(1), this._root._bundle);
|
|
181
|
+
if (value === null){
|
|
182
|
+
throw new Error("Spec not found: %s".sprintf(value.substr(1)));
|
|
183
|
+
}
|
|
184
|
+
return value.filesOwner;
|
|
181
185
|
}
|
|
182
186
|
if (type !== null){
|
|
183
187
|
if (value in type){
|