@breakside/jskit 2026.11.0 → 2026.27.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 +56 -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/JSNumberFormatter.js +23 -1
- package/Frameworks/Foundation.jsframework/JS/JSPath.js +194 -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/JSXMLParser.js +1 -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/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/CSSTokenizer.js +633 -470
- 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 +56 -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/JSNumberFormatter.js +23 -1
- package/Root/Frameworks/Foundation/JSPath.js +194 -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/JSXMLParser.js +1 -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 +31 -7
- package/Root/Frameworks/UIKit/UITextField.js +7 -0
- 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
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
|
|
16
16
|
// #import Foundation
|
|
17
|
-
/* global FNTOpenTypeConstructor */
|
|
17
|
+
/* global FNTOpenTypeConstructor, DataView */
|
|
18
18
|
'use strict';
|
|
19
19
|
|
|
20
20
|
(function(){
|
|
@@ -496,6 +496,10 @@ JSClass("FNTOpenTypeFont", JSObject, {
|
|
|
496
496
|
return completion.promise;
|
|
497
497
|
},
|
|
498
498
|
|
|
499
|
+
pathForGlyph: function(glyphIndex, transform){
|
|
500
|
+
return this.tables.glyf.pathForGlyph(glyphIndex, this.tables.loca, this.tables.head.indexToLocFormat, transform);
|
|
501
|
+
},
|
|
502
|
+
|
|
499
503
|
});
|
|
500
504
|
|
|
501
505
|
var tableChecksum = function(data){
|
|
@@ -1183,7 +1187,25 @@ JSClass("FNTOpenTypeFontTableCFF", FNTOpenTypeFontTable, {
|
|
|
1183
1187
|
});
|
|
1184
1188
|
|
|
1185
1189
|
JSClass("FNTOpenTypeFontTableGlyf", FNTOpenTypeFontTable, {
|
|
1186
|
-
tag: 'glyf'
|
|
1190
|
+
tag: 'glyf',
|
|
1191
|
+
|
|
1192
|
+
glyph: function(glyphIndex, loca, format){
|
|
1193
|
+
var range = loca.rangeForGlyph(glyphIndex, format);
|
|
1194
|
+
var data = this.data.subdataInRange(range);
|
|
1195
|
+
var glyph = FNTOpenTypeGlyph.initWithData(data);
|
|
1196
|
+
if (glyph.isKindOfClass(FNTOpenTypeCompoundGlyph)){
|
|
1197
|
+
glyph.glyf = this;
|
|
1198
|
+
glyph.loca = loca;
|
|
1199
|
+
glyph.locaFormat = format;
|
|
1200
|
+
}
|
|
1201
|
+
return glyph;
|
|
1202
|
+
},
|
|
1203
|
+
|
|
1204
|
+
pathForGlyph: function(glyphIndex, loca, format, transform){
|
|
1205
|
+
var glyph = this.glyph(glyphIndex, loca, format);
|
|
1206
|
+
return glyph.getPath(transform);
|
|
1207
|
+
},
|
|
1208
|
+
|
|
1187
1209
|
});
|
|
1188
1210
|
|
|
1189
1211
|
JSClass("FNTOpenTypeFontTableLoca", FNTOpenTypeFontTable, {
|
|
@@ -1790,10 +1812,14 @@ JSClass("FNTOpenTypeFontCmap13", FNTOpenTypeFontCmap, {
|
|
|
1790
1812
|
JSClass("FNTOpenTypeGlyph", JSObject, {
|
|
1791
1813
|
|
|
1792
1814
|
initWithData: function(data){
|
|
1793
|
-
if (
|
|
1794
|
-
|
|
1815
|
+
if (this.$class === FNTOpenTypeGlyph){
|
|
1816
|
+
if (data.length >= 2 && data.dataView().getInt16(0) < 0){
|
|
1817
|
+
return FNTOpenTypeCompoundGlyph.initWithData(data);
|
|
1818
|
+
}
|
|
1819
|
+
return FNTOpenTypeSimpleGlyph.initWithData(data);
|
|
1795
1820
|
}
|
|
1796
|
-
|
|
1821
|
+
this.data = data;
|
|
1822
|
+
this.dataView = data.dataView();
|
|
1797
1823
|
},
|
|
1798
1824
|
|
|
1799
1825
|
data: null,
|
|
@@ -1802,27 +1828,184 @@ JSClass("FNTOpenTypeGlyph", JSObject, {
|
|
|
1802
1828
|
xMin: DataBackedProperty(2, "int16"),
|
|
1803
1829
|
yMin: DataBackedProperty(4, "int16"),
|
|
1804
1830
|
xMax: DataBackedProperty(6, "int16"),
|
|
1805
|
-
yMax: DataBackedProperty(8, "int16")
|
|
1831
|
+
yMax: DataBackedProperty(8, "int16"),
|
|
1832
|
+
|
|
1833
|
+
getPath: function(){
|
|
1834
|
+
return null;
|
|
1835
|
+
},
|
|
1806
1836
|
|
|
1807
1837
|
});
|
|
1808
1838
|
|
|
1809
|
-
JSClass("FNTOpenTypeSimpleGlyph",
|
|
1839
|
+
JSClass("FNTOpenTypeSimpleGlyph", FNTOpenTypeGlyph, {
|
|
1810
1840
|
|
|
1811
|
-
|
|
1812
|
-
this.data = data;
|
|
1813
|
-
this.dataView = data.dataView();
|
|
1814
|
-
},
|
|
1841
|
+
numberOfCountours: DataBackedProperty(0, "int16"),
|
|
1815
1842
|
|
|
1816
|
-
|
|
1843
|
+
endPointIndexes: null,
|
|
1844
|
+
flags: null,
|
|
1845
|
+
|
|
1846
|
+
points: JSLazyInitProperty(function(){
|
|
1847
|
+
var points = [];
|
|
1848
|
+
var offset = 10;
|
|
1849
|
+
var end = this.data.length;
|
|
1850
|
+
var i, l;
|
|
1851
|
+
if (offset + this.numberOfCountours * 2 > end){
|
|
1852
|
+
throw new Error("not enough data for glyph end point indexes");
|
|
1853
|
+
}
|
|
1854
|
+
this.endPointIndexes = [];
|
|
1855
|
+
for (i = 0; i < this.numberOfCountours; ++i){
|
|
1856
|
+
this.endPointIndexes.push(this.dataView.getUint16(offset));
|
|
1857
|
+
offset += 2;
|
|
1858
|
+
}
|
|
1859
|
+
if (offset + 2 > end){
|
|
1860
|
+
throw new Error("not enough data for glyph instructions");
|
|
1861
|
+
}
|
|
1862
|
+
var instructionLength = this.dataView.getUint16(offset);
|
|
1863
|
+
offset += 2;
|
|
1864
|
+
if (offset + instructionLength > end){
|
|
1865
|
+
throw new Error("not enough data for glyph instructions");
|
|
1866
|
+
}
|
|
1867
|
+
offset += instructionLength;
|
|
1868
|
+
var numberOfPoints = this.endPointIndexes[this.endPointIndexes.length - 1] + 1;
|
|
1869
|
+
var repeatCount;
|
|
1870
|
+
var j, k;
|
|
1871
|
+
var flags;
|
|
1872
|
+
i = 0;
|
|
1873
|
+
this.flags = [];
|
|
1874
|
+
while (i < numberOfPoints){
|
|
1875
|
+
if (offset >= end){
|
|
1876
|
+
return null;
|
|
1877
|
+
}
|
|
1878
|
+
flags = this.data[offset];
|
|
1879
|
+
++offset;
|
|
1880
|
+
this.flags.push(flags);
|
|
1881
|
+
++i;
|
|
1882
|
+
if ((flags & 0x08) !== 0){
|
|
1883
|
+
if (offset >= end){
|
|
1884
|
+
return null;
|
|
1885
|
+
}
|
|
1886
|
+
repeatCount = this.data[offset];
|
|
1887
|
+
++offset;
|
|
1888
|
+
for (j = 0; j < repeatCount; ++j){
|
|
1889
|
+
this.flags.push(flags);
|
|
1890
|
+
++i;
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
i = 0;
|
|
1895
|
+
var point = JSPoint.Zero;
|
|
1896
|
+
var dx, dy;
|
|
1897
|
+
while (i < numberOfPoints){
|
|
1898
|
+
point = JSPoint(point);
|
|
1899
|
+
flags = this.flags[i];
|
|
1900
|
+
if ((flags & 0x02) === 0){
|
|
1901
|
+
if ((flags & 0x10) === 0){
|
|
1902
|
+
if (offset + 2 > end){
|
|
1903
|
+
throw new Error("not enough data for x delta");
|
|
1904
|
+
}
|
|
1905
|
+
dx = this.dataView.getInt16(offset);
|
|
1906
|
+
offset += 2;
|
|
1907
|
+
}else{
|
|
1908
|
+
dx = 0;
|
|
1909
|
+
}
|
|
1910
|
+
}else{
|
|
1911
|
+
if (offset >= end){
|
|
1912
|
+
throw new Error("not enough data for x delta");
|
|
1913
|
+
}
|
|
1914
|
+
dx = this.data[offset];
|
|
1915
|
+
++offset;
|
|
1916
|
+
if ((flags & 0x10) === 0){
|
|
1917
|
+
dx = -dx;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
point.x += dx;
|
|
1921
|
+
points.push(point);
|
|
1922
|
+
++i;
|
|
1923
|
+
}
|
|
1924
|
+
i = 0;
|
|
1925
|
+
while (i < numberOfPoints){
|
|
1926
|
+
points[i].y = point.y;
|
|
1927
|
+
point = points[i];
|
|
1928
|
+
flags = this.flags[i];
|
|
1929
|
+
if ((flags & 0x04) === 0){
|
|
1930
|
+
if ((flags & 0x20) === 0){
|
|
1931
|
+
if (offset + 2 > end){
|
|
1932
|
+
throw new Error("not enough data for y delta");
|
|
1933
|
+
}
|
|
1934
|
+
dy = this.dataView.getInt16(offset);
|
|
1935
|
+
offset += 2;
|
|
1936
|
+
}else{
|
|
1937
|
+
dy = 0;
|
|
1938
|
+
}
|
|
1939
|
+
}else{
|
|
1940
|
+
if (offset >= end){
|
|
1941
|
+
throw new Error("not enough data for y delta");
|
|
1942
|
+
}
|
|
1943
|
+
dy = this.data[offset];
|
|
1944
|
+
++offset;
|
|
1945
|
+
if ((flags & 0x20) === 0){
|
|
1946
|
+
dy = -dy;
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
point.y += dy;
|
|
1950
|
+
++i;
|
|
1951
|
+
}
|
|
1952
|
+
return points;
|
|
1953
|
+
}),
|
|
1954
|
+
|
|
1955
|
+
getPath: function(transform){
|
|
1956
|
+
if (this.data.length < 2 || this.numberOfCountours === 0){
|
|
1957
|
+
return JSPath.init();
|
|
1958
|
+
}
|
|
1959
|
+
var flags;
|
|
1960
|
+
var point;
|
|
1961
|
+
var i, j, k;
|
|
1962
|
+
var p0;
|
|
1963
|
+
var path = JSPath.init();
|
|
1964
|
+
var cp = null;
|
|
1965
|
+
j = 0;
|
|
1966
|
+
var points = this.points;
|
|
1967
|
+
for (i = 0; i < this.numberOfCountours; ++i){
|
|
1968
|
+
flags = this.flags[j];
|
|
1969
|
+
point = points[j];
|
|
1970
|
+
p0 = point;
|
|
1971
|
+
if ((flags & 0x01) === 0){
|
|
1972
|
+
throw new Error("first point is off-curve");
|
|
1973
|
+
}
|
|
1974
|
+
path.moveToPoint(point, transform);
|
|
1975
|
+
++j;
|
|
1976
|
+
for (k = this.endPointIndexes[i]; j <= k; ++j){
|
|
1977
|
+
flags = this.flags[j];
|
|
1978
|
+
point = points[j];
|
|
1979
|
+
if ((flags & 0x01) === 0){
|
|
1980
|
+
if (cp !== null){
|
|
1981
|
+
path.addQuadraticCurveToPoint(cp.interpolation(point, 0.5), cp, transform);
|
|
1982
|
+
}
|
|
1983
|
+
cp = point;
|
|
1984
|
+
}else{
|
|
1985
|
+
if (cp !== null){
|
|
1986
|
+
path.addQuadraticCurveToPoint(point, cp, transform);
|
|
1987
|
+
}else{
|
|
1988
|
+
path.addLineToPoint(point, transform);
|
|
1989
|
+
}
|
|
1990
|
+
cp = null;
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
if (cp !== null){
|
|
1994
|
+
path.addQuadraticCurveToPoint(p0, cp, transform);
|
|
1995
|
+
cp = null;
|
|
1996
|
+
}
|
|
1997
|
+
path.closeSubpath();
|
|
1998
|
+
}
|
|
1999
|
+
return path;
|
|
2000
|
+
},
|
|
1817
2001
|
|
|
1818
2002
|
});
|
|
1819
2003
|
|
|
1820
|
-
JSClass("FNTOpenTypeCompoundGlyph",
|
|
2004
|
+
JSClass("FNTOpenTypeCompoundGlyph", FNTOpenTypeGlyph, {
|
|
1821
2005
|
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
},
|
|
2006
|
+
glyf: null,
|
|
2007
|
+
loca: null,
|
|
2008
|
+
locaFormat: null,
|
|
1826
2009
|
|
|
1827
2010
|
updateReferencedGlyphs: function(glyphIndexByOriginalIndex, nextGlyphIndex){
|
|
1828
2011
|
this.data = JSData.initWithCopyOfData(this.data);
|
|
@@ -1859,16 +2042,142 @@ JSClass("FNTOpenTypeCompoundGlyph", JSObject, {
|
|
|
1859
2042
|
}
|
|
1860
2043
|
}while ((flags & 0x20) == 0x20);
|
|
1861
2044
|
return newGlyphs;
|
|
1862
|
-
}
|
|
2045
|
+
},
|
|
2046
|
+
|
|
2047
|
+
getPath: function(transform){
|
|
2048
|
+
if (!transform){
|
|
2049
|
+
transform = JSAffineTransform.Identity;
|
|
2050
|
+
}
|
|
2051
|
+
var points = [];
|
|
2052
|
+
var path = JSPath.init();
|
|
2053
|
+
var offset = 10;
|
|
2054
|
+
var end = this.data.length;
|
|
2055
|
+
var flags;
|
|
2056
|
+
var glyphIndex;
|
|
2057
|
+
var arg1;
|
|
2058
|
+
var arg2;
|
|
2059
|
+
var glyph;
|
|
2060
|
+
var glyphTransform;
|
|
2061
|
+
var glyphPath;
|
|
2062
|
+
var hasMore = true;
|
|
2063
|
+
var p1;
|
|
2064
|
+
var p2;
|
|
2065
|
+
while (hasMore && offset < end){
|
|
2066
|
+
if (offset + 4 > end){
|
|
2067
|
+
throw new Error("not enough data for compound glyph");
|
|
2068
|
+
}
|
|
2069
|
+
flags = this.dataView.getUint16(offset);
|
|
2070
|
+
hasMore = (flags & 0x20) !== 0;
|
|
2071
|
+
offset += 2;
|
|
2072
|
+
glyphIndex = this.dataView.getUint16(offset);
|
|
2073
|
+
offset += 2;
|
|
2074
|
+
glyph = this.glyf.glyph(glyphIndex, this.loca, this.locaFormat);
|
|
2075
|
+
glyphPath = glyph.getPath();
|
|
2076
|
+
glyphTransform = JSAffineTransform.Identity;
|
|
2077
|
+
points = points.concat(glyph.points);
|
|
2078
|
+
if ((flags & 0x01) !== 0){
|
|
2079
|
+
if (offset + 4 > end){
|
|
2080
|
+
throw new Error("not enough data for compound glyph args");
|
|
2081
|
+
}
|
|
2082
|
+
if ((flags & 0x02) !== 0){
|
|
2083
|
+
// x-y values
|
|
2084
|
+
arg1 = this.dataView.getInt16(offset);
|
|
2085
|
+
offset += 2;
|
|
2086
|
+
arg2 = this.dataView.getInt16(offset);
|
|
2087
|
+
offset += 2;
|
|
2088
|
+
}else{
|
|
2089
|
+
// point indexes
|
|
2090
|
+
arg1 = this.dataView.getUint16(offset);
|
|
2091
|
+
offset += 2;
|
|
2092
|
+
arg2 = this.dataView.getUint16(offset);
|
|
2093
|
+
offset += 2;
|
|
2094
|
+
}
|
|
2095
|
+
}else{
|
|
2096
|
+
if (offset + 2 > end){
|
|
2097
|
+
throw new Error("not enough data for compound glyph args");
|
|
2098
|
+
}
|
|
2099
|
+
if ((flags & 0x02) !== 0){
|
|
2100
|
+
// x-y values
|
|
2101
|
+
arg1 = this.dataView.getInt8(offset);
|
|
2102
|
+
++offset;
|
|
2103
|
+
arg2 = this.dataView.getInt8(offset);
|
|
2104
|
+
++offset;
|
|
2105
|
+
}else{
|
|
2106
|
+
// point indexes
|
|
2107
|
+
arg1 = this.data[offset];
|
|
2108
|
+
++offset;
|
|
2109
|
+
arg2 = this.data[offset];
|
|
2110
|
+
++offset;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
if ((flags & 0x08) !== 0){
|
|
2114
|
+
if (offset + 2 > end){
|
|
2115
|
+
throw new Error("not enough data for compound glyph scale");
|
|
2116
|
+
}
|
|
2117
|
+
glyphTransform.a = this.dataView.getOTFFixedGlyphTranform(offset);
|
|
2118
|
+
glyphTransform.d = glyphTransform.a;
|
|
2119
|
+
offset += 2;
|
|
2120
|
+
}
|
|
2121
|
+
if ((flags & 0x40) !== 0){
|
|
2122
|
+
if (offset + 4 > end){
|
|
2123
|
+
throw new Error("not enough data for compound glyph scales");
|
|
2124
|
+
}
|
|
2125
|
+
glyphTransform.a = this.dataView.getOTFFixedGlyphTranform(offset);
|
|
2126
|
+
offset += 2;
|
|
2127
|
+
glyphTransform.d = this.dataView.getOTFFixedGlyphTranform(offset + 2);
|
|
2128
|
+
offset += 2;
|
|
2129
|
+
}
|
|
2130
|
+
if ((flags & 0x80) !== 0){
|
|
2131
|
+
if (offset + 8 > end){
|
|
2132
|
+
throw new Error("not enough data for compound glyph scale 2x2");
|
|
2133
|
+
}
|
|
2134
|
+
glyphTransform.a = this.dataView.getOTFFixedGlyphTranform(offset);
|
|
2135
|
+
offset += 2;
|
|
2136
|
+
glyphTransform.b = this.dataView.getOTFFixedGlyphTranform(offset);
|
|
2137
|
+
offset += 2;
|
|
2138
|
+
glyphTransform.c = this.dataView.getOTFFixedGlyphTranform(offset);
|
|
2139
|
+
offset += 2;
|
|
2140
|
+
glyphTransform.d = this.dataView.getOTFFixedGlyphTranform(offset);
|
|
2141
|
+
offset += 2;
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
if ((flags & 0x02) !== 0){
|
|
2145
|
+
// x-y values
|
|
2146
|
+
glyphTransform = glyphTransform.translatedBy(arg1, arg2);
|
|
2147
|
+
}else{
|
|
2148
|
+
// point indexes
|
|
2149
|
+
p1 = points[arg1];
|
|
2150
|
+
p2 = glyph.points[arg2];
|
|
2151
|
+
glyphTransform.tx = p1.x - p2.x;
|
|
2152
|
+
glyphTransform.ty = p1.y - p2.y;
|
|
2153
|
+
}
|
|
2154
|
+
path.addPath(glyphPath, glyphTransform.concatenatedWith(transform));
|
|
2155
|
+
}
|
|
2156
|
+
return path;
|
|
2157
|
+
},
|
|
1863
2158
|
|
|
1864
2159
|
});
|
|
1865
2160
|
|
|
1866
2161
|
Object.defineProperties(DataView.prototype, {
|
|
1867
2162
|
|
|
1868
|
-
getOTFFixed:
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
2163
|
+
getOTFFixed: {
|
|
2164
|
+
value: function DataView_getOTFFixed(offset){
|
|
2165
|
+
var whole = this.getUint16(offset);
|
|
2166
|
+
var frac = this.getUint16(offset + 2);
|
|
2167
|
+
return whole + frac / 0x10000;
|
|
2168
|
+
}
|
|
2169
|
+
},
|
|
2170
|
+
|
|
2171
|
+
getOTFFixedGlyphTranform: {
|
|
2172
|
+
value: function DataView_getOTFFixedGlyphTransform(offset){
|
|
2173
|
+
var n = this.getUint16(offset);
|
|
2174
|
+
var whole = ((n & 0x4000) !== 0) ? 1 : 0;
|
|
2175
|
+
if ((n & 0x8000) !== 0){
|
|
2176
|
+
whole = -whole;
|
|
2177
|
+
}
|
|
2178
|
+
var frac = n & 0x3FFF;
|
|
2179
|
+
return whole + frac / 0x4000;
|
|
2180
|
+
}
|
|
1872
2181
|
}
|
|
1873
2182
|
|
|
1874
2183
|
});
|
|
@@ -65,6 +65,7 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
65
65
|
case JSAttributedString.Attribute.font:
|
|
66
66
|
return JSAttributedString.AttributeDecoder.font(value);
|
|
67
67
|
case JSAttributedString.Attribute.textColor:
|
|
68
|
+
case JSAttributedString.Attribute.strokeColor:
|
|
68
69
|
case JSAttributedString.Attribute.backgroundColor:
|
|
69
70
|
return JSAttributedString.AttributeDecoder.color(value);
|
|
70
71
|
case JSAttributedString.Attribute.link:
|
|
@@ -90,6 +91,7 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
90
91
|
case JSAttributedString.Attribute.headIndent:
|
|
91
92
|
case JSAttributedString.Attribute.tailIndent:
|
|
92
93
|
case JSAttributedString.Attribute.minimumLineHeight:
|
|
94
|
+
case JSAttributedString.Attribute.strokeWidth:
|
|
93
95
|
return JSAttributedString.AttributeDecoder.number(value);
|
|
94
96
|
case JSAttributedString.Attribute.textAlignment:
|
|
95
97
|
return JSAttributedString.AttributeDecoder.enumValue(JSTextAlignment)(value);
|
|
@@ -137,6 +139,7 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
137
139
|
case JSAttributedString.Attribute.font:
|
|
138
140
|
return JSAttributedString.AttributeEncoder.font(value);
|
|
139
141
|
case JSAttributedString.Attribute.textColor:
|
|
142
|
+
case JSAttributedString.Attribute.strokeColor:
|
|
140
143
|
case JSAttributedString.Attribute.backgroundColor:
|
|
141
144
|
return JSAttributedString.AttributeEncoder.color(value);
|
|
142
145
|
case JSAttributedString.Attribute.link:
|
|
@@ -162,6 +165,7 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
162
165
|
case JSAttributedString.Attribute.lineBreakMode:
|
|
163
166
|
case JSAttributedString.Attribute.maskCharacter:
|
|
164
167
|
case JSAttributedString.Attribute.paragraphStyleName:
|
|
168
|
+
case JSAttributedString.Attribute.strokeWidth:
|
|
165
169
|
default:
|
|
166
170
|
return value;
|
|
167
171
|
}
|
|
@@ -391,6 +395,49 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
391
395
|
this._fixParagraphAttributesAtIndex(range.location + attributedString.string.length);
|
|
392
396
|
},
|
|
393
397
|
|
|
398
|
+
stringWithFallbackFonts: function(fallbackFontDescriptors, defaultFont, usedDescriptors){
|
|
399
|
+
var attributedString = this;
|
|
400
|
+
var runIterator = attributedString.runIterator();
|
|
401
|
+
var unicodeIterator;
|
|
402
|
+
var end = attributedString.string.length;
|
|
403
|
+
var font;
|
|
404
|
+
var glyph;
|
|
405
|
+
var descriptor;
|
|
406
|
+
var i, l;
|
|
407
|
+
var descriptorFonts = [];
|
|
408
|
+
for (i = 0, l = fallbackFontDescriptors.length; i < l; ++i){
|
|
409
|
+
descriptorFonts.push({});
|
|
410
|
+
}
|
|
411
|
+
for (; runIterator.range.location < end; runIterator.increment()){
|
|
412
|
+
font = runIterator.attributes.font || defaultFont;
|
|
413
|
+
unicodeIterator = attributedString.string.unicodeIterator(0);
|
|
414
|
+
for (; unicodeIterator.character !== null; unicodeIterator.increment()){
|
|
415
|
+
glyph = font.glyphForCharacter(unicodeIterator.character);
|
|
416
|
+
if (glyph === 0){
|
|
417
|
+
for (i = 0, l = fallbackFontDescriptors.length && glyph === 0; i < l; ++i){
|
|
418
|
+
descriptor = fallbackFontDescriptors[i];
|
|
419
|
+
glyph = descriptor.glyphForCharacter(unicodeIterator.character);
|
|
420
|
+
if (glyph !== 0){
|
|
421
|
+
if (usedDescriptors !== undefined){
|
|
422
|
+
if (usedDescriptors.indexOf(descriptor) < 0){
|
|
423
|
+
usedDescriptors.push(descriptor);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (attributedString === this){
|
|
427
|
+
attributedString = JSAttributedString.initWithAttributedString(attributedString);
|
|
428
|
+
}
|
|
429
|
+
if (descriptorFonts[i][font.pointSize] === undefined){
|
|
430
|
+
descriptorFonts[i][font.pointSize] = JSFont.initWithDescriptor(descriptor, font.pointSize);
|
|
431
|
+
}
|
|
432
|
+
attributedString.addAttributeInRange("font", descriptorFonts[i][font.pointSize], JSRange(unicodeIterator.index, unicodeIterator.nextIndex - unicodeIterator.index));
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return attributedString;
|
|
439
|
+
},
|
|
440
|
+
|
|
394
441
|
// MARK: - Attribute mutations
|
|
395
442
|
|
|
396
443
|
setAttributesInRange: function(attributes, range){
|
|
@@ -680,6 +727,7 @@ JSClass("JSAttributedString", JSObject, {
|
|
|
680
727
|
JSAttributedString.Attribute = {
|
|
681
728
|
font: "font",
|
|
682
729
|
textColor: "textColor",
|
|
730
|
+
strokeColor: "strokeColor",
|
|
683
731
|
backgroundColor: "backgroundColor",
|
|
684
732
|
bold: "bold",
|
|
685
733
|
italic: "italic",
|
|
@@ -689,6 +737,7 @@ JSAttributedString.Attribute = {
|
|
|
689
737
|
maskCharacter: "maskCharacter",
|
|
690
738
|
cursor: "cursor",
|
|
691
739
|
link: "link",
|
|
740
|
+
strokeWidth: "strokeWidth",
|
|
692
741
|
|
|
693
742
|
// Paragraph
|
|
694
743
|
paragraphStyleName: "paragraphStyleName",
|
|
@@ -745,7 +794,13 @@ JSAttributedString.AttributeDecoder = {
|
|
|
745
794
|
dataBase64URL: function(value){ return value.dataByDecodingBase64URL(); },
|
|
746
795
|
dataHex: function(value){ return value.dataByDecodingHex(); },
|
|
747
796
|
url: function(value){ return JSURL.initWithString(value); },
|
|
748
|
-
font: function(value){
|
|
797
|
+
font: function(value){
|
|
798
|
+
var font = JSFont.initFromDictionary(value);
|
|
799
|
+
if (font === null){
|
|
800
|
+
font = JSFont.initWithDescriptor(JSFontDescriptor.system, value.size);
|
|
801
|
+
}
|
|
802
|
+
return font;
|
|
803
|
+
},
|
|
749
804
|
color: function(value){ return JSColor.initFromDictionary(value); },
|
|
750
805
|
boolean: function(value){ return typeof(value) === "boolean" ? value : undefined; },
|
|
751
806
|
number: function(value){ return typeof(value) === "number" ? value : undefined; },
|
|
@@ -88,8 +88,7 @@ JSClass("JSContext", JSObject, {
|
|
|
88
88
|
|
|
89
89
|
addQuadraticCurveToPoint: function(point, control){
|
|
90
90
|
this.beginPathIfNeeded();
|
|
91
|
-
|
|
92
|
-
this.path.addCurveToPoint(point, control, point, this.state.transform);
|
|
91
|
+
this.path.addQuadraticCurveToPoint(point, control, this.state.transform);
|
|
93
92
|
},
|
|
94
93
|
|
|
95
94
|
addEllipseInRect: function(rect){
|
|
@@ -100,21 +99,17 @@ JSClass("JSContext", JSObject, {
|
|
|
100
99
|
addPath: function(path){
|
|
101
100
|
this.beginPathIfNeeded();
|
|
102
101
|
var i, l;
|
|
103
|
-
var
|
|
104
|
-
var
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
this.addCurveToPoint(segment.curve.p2, segment.curve.cp1, segment.curve.cp2);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
if (subpath.closed){
|
|
102
|
+
var elements = path.elements;
|
|
103
|
+
var element;
|
|
104
|
+
for (i = 0, l = elements.length; i < l; ++i){
|
|
105
|
+
element = elements[i];
|
|
106
|
+
if (element.type === JSPathElement.Type.move){
|
|
107
|
+
this.moveToPoint(element.point.x, element.point.y);
|
|
108
|
+
}else if (element.type === JSPathElement.Type.line){
|
|
109
|
+
this.addLineToPoint(element.point.x, element.point.y);
|
|
110
|
+
}else if (element.type === JSPathElement.Type.cubicCurve){
|
|
111
|
+
this.addCurveToPoint(element.curve.p2, element.curve.cp1, element.curve.cp2);
|
|
112
|
+
}else if (element.type === JSPathElement.Type.close){
|
|
118
113
|
this.closePath();
|
|
119
114
|
}
|
|
120
115
|
}
|
|
@@ -212,6 +207,12 @@ JSClass("JSContext", JSObject, {
|
|
|
212
207
|
drawRadialGradient: function(gradient, rect){
|
|
213
208
|
},
|
|
214
209
|
|
|
210
|
+
drawMaskedLinearGradient: function(gradient, rect, maskImage){
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
drawMaskedRadialGradient: function(gradient, rect, maskImage){
|
|
214
|
+
},
|
|
215
|
+
|
|
215
216
|
drawLinearGradientStroke: function(gradient, path){
|
|
216
217
|
// FIXME: gradient should be aligned to original path rect
|
|
217
218
|
var strokePath = path.pathThatFillsStroke(this.state.lineWidth, this.state.lineCap, this.state.lineJoin, this.state.miterLimit);
|
|
@@ -282,6 +283,30 @@ JSClass("JSContext", JSObject, {
|
|
|
282
283
|
this.state.shadowColor = color;
|
|
283
284
|
},
|
|
284
285
|
|
|
286
|
+
// ----------------------------------------------------------------------
|
|
287
|
+
// MARK: - Transparency Layers
|
|
288
|
+
|
|
289
|
+
beginTransparencyLayer: function(){
|
|
290
|
+
this.save();
|
|
291
|
+
this.state.transparencyLayer = this.createTransparencyLayer();
|
|
292
|
+
this.setAlpha(1);
|
|
293
|
+
this.setShadow(JSPoint.Zero, 0, null);
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
endTransparencyLayer: function(){
|
|
297
|
+
if (this.state.transparencyLayer === null){
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
this.drawTransparencyLayer(this.state.transparencyLayer);
|
|
301
|
+
this.restore();
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
createTransparencyLayer: function(){
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
drawTransparencyLayer: function(transparencyLayer){
|
|
308
|
+
},
|
|
309
|
+
|
|
285
310
|
// ----------------------------------------------------------------------
|
|
286
311
|
// MARK: - Clipping
|
|
287
312
|
|
|
@@ -411,6 +436,8 @@ JSContext.State = {
|
|
|
411
436
|
characterSpacing: 0,
|
|
412
437
|
textDrawingMode: JSContext.TextDrawingMode.fill,
|
|
413
438
|
|
|
439
|
+
transparencyLayer: null
|
|
440
|
+
|
|
414
441
|
};
|
|
415
442
|
|
|
416
443
|
})();
|