@qooxdoo/framework 7.5.0 → 7.6.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/Manifest.json +169 -44
- package/bin/deploy/qx +7 -5
- package/lib/compiler/compile-info.json +70 -62
- package/lib/compiler/index.js +3809 -2695
- package/lib/resource/qx/tool/cli/templates/skeleton/desktop/source/class/custom/Application.tmpl.js +7 -7
- package/lib/resource/qx/tool/cli/templates/skeleton/desktop/source/class/custom/test/DemoTest.tmpl.js +10 -10
- package/lib/resource/qx/tool/cli/templates/skeleton/mobile/source/class/custom/Application.tmpl.js +6 -6
- package/lib/resource/qx/tool/cli/templates/skeleton/mobile/source/class/custom/page/Login.tmpl.js +9 -9
- package/lib/resource/qx/tool/cli/templates/skeleton/mobile/source/class/custom/page/Overview.tmpl.js +5 -5
- package/lib/resource/qx/tool/cli/templates/skeleton/package/source/class/custom/demo/Application.tmpl.js +7 -7
- package/lib/resource/qx/tool/cli/templates/skeleton/package/source/class/custom/test/DemoTest.tmpl.js +10 -10
- package/lib/resource/qx/tool/cli/templates/skeleton/server/source/class/custom/Application.tmpl.js +6 -6
- package/lib/resource/qx/tool/cli/templates/skeleton/server/source/class/custom/test/DemoTest.tmpl.js +12 -12
- package/lib/resource/qx/tool/schema/Manifest-1-0-0.json +79 -26
- package/lib/resource/qx/tool/schema/Manifest-2-0-0.json +17 -26
- package/lib/resource/qx/tool/schema/compile-1-0-0.json +40 -53
- package/lib/resource/qx/tool/website/src/about.md +1 -1
- package/package.json +3 -3
- package/source/class/qx/bom/Font.js +36 -0
- package/source/class/qx/bom/webfonts/Validator.js +31 -6
- package/source/class/qx/bom/webfonts/WebFont.js +60 -64
- package/source/class/qx/bom/webfonts/WebFontLoader.js +461 -0
- package/source/class/qx/core/Object.js +1 -1
- package/source/class/qx/data/Array.js +27 -0
- package/source/class/qx/dev/FakeServer.js +1 -1
- package/source/class/qx/event/handler/Focus.js +2 -1
- package/source/class/qx/event/handler/GestureCore.js +1 -1
- package/source/class/qx/test/bom/webfonts/Validator.js +0 -6
- package/source/class/qx/test/core/Environment.js +8 -8
- package/source/class/qx/test/core/Validation.js +2 -2
- package/source/class/qx/test/dev/unit/Requirements.js +6 -6
- package/source/class/qx/test/io/transport/Websocket.js +1 -1
- package/source/class/qx/test/ui/basic/Image.js +3 -3
- package/source/class/qx/test/ui/basic/Label.js +0 -65
- package/source/class/qx/test/ui/form/Field.js +56 -52
- package/source/class/qx/theme/IndigoDark.js +1 -1
- package/source/class/qx/theme/classic/Font.js +7 -23
- package/source/class/qx/theme/iconfont/LoadMaterialIcons.js +2 -4
- package/source/class/qx/theme/iconfont/LoadMaterialIconsOutlined.js +2 -4
- package/source/class/qx/theme/iconfont/LoadMaterialIconsRound.js +2 -4
- package/source/class/qx/theme/iconfont/LoadMaterialIconsSharp.js +2 -4
- package/source/class/qx/theme/iconfont/LoadMaterialIconsTwoTone.js +2 -4
- package/source/class/qx/theme/indigo/DecorationDark.js +30 -0
- package/source/class/qx/theme/indigo/Font.js +8 -15
- package/source/class/qx/theme/manager/Font.js +151 -38
- package/source/class/qx/theme/modern/Font.js +1 -0
- package/source/class/qx/theme/simple/Font.js +3 -1
- package/source/class/qx/theme/tangible/Appearance.js +1 -0
- package/source/class/qx/theme/tangible/Font.js +9 -62
- package/source/class/qx/theme/tangible/Image.js +1 -4
- package/source/class/qx/tool/cli/Application.js +4 -1
- package/source/class/qx/tool/cli/Cli.js +34 -23
- package/source/class/qx/tool/cli/Watch.js +8 -6
- package/source/class/qx/tool/cli/api/CompilerApi.js +8 -0
- package/source/class/qx/tool/cli/commands/Add.js +1 -1
- package/source/class/qx/tool/cli/commands/Compile.js +24 -1
- package/source/class/qx/tool/cli/commands/Config.js +16 -141
- package/source/class/qx/tool/cli/commands/ExportGlyphs.js +134 -0
- package/source/class/qx/tool/cli/commands/Lint.js +1 -1
- package/source/class/qx/tool/cli/commands/Package.js +3 -0
- package/source/class/qx/tool/cli/commands/Pkg.js +1 -1
- package/source/class/qx/tool/cli/commands/Run.js +6 -7
- package/source/class/qx/tool/cli/commands/Serve.js +29 -36
- package/source/class/qx/tool/cli/commands/Test.js +3 -2
- package/source/class/qx/tool/cli/commands/add/Script.js +3 -1
- package/source/class/qx/tool/cli/commands/config/Delete.js +47 -0
- package/source/class/qx/tool/cli/commands/config/Get.js +52 -0
- package/source/class/qx/tool/cli/commands/config/List.js +81 -0
- package/source/class/qx/tool/cli/commands/config/Set.js +61 -0
- package/source/class/qx/tool/cli/commands/package/Install.js +3 -0
- package/source/class/qx/tool/cli/commands/package/Update.js +3 -3
- package/source/class/qx/tool/compiler/Analyser.js +45 -0
- package/source/class/qx/tool/compiler/ClassFile.js +43 -1
- package/source/class/qx/tool/compiler/Console.js +6 -1
- package/source/class/qx/tool/compiler/app/Application.js +19 -0
- package/source/class/qx/tool/compiler/app/Cldr.js +63 -26
- package/source/class/qx/tool/compiler/app/Library.js +51 -2
- package/source/class/qx/tool/compiler/app/ManifestFont.js +181 -0
- package/source/class/qx/tool/compiler/app/WebFont.js +144 -234
- package/source/class/qx/tool/compiler/makers/AppMaker.js +13 -0
- package/source/class/qx/tool/compiler/resources/ImageLoader.js +22 -12
- package/source/class/qx/tool/compiler/resources/Manager.js +2 -2
- package/source/class/qx/tool/compiler/resources/MetaLoader.js +7 -2
- package/source/class/qx/tool/compiler/resources/ResourceLoader.js +21 -0
- package/source/class/qx/tool/compiler/targets/Target.js +186 -67
- package/source/class/qx/tool/migration/M7_5_6.js +75 -0
- package/source/class/qx/tool/utils/Http.js +69 -0
- package/source/class/qx/ui/basic/Image.js +6 -2
- package/source/class/qx/ui/basic/Label.js +20 -38
- package/source/class/qx/ui/core/Widget.js +13 -42
- package/source/class/qx/ui/form/AbstractField.js +8 -2
- package/source/class/qx/ui/form/FileSelectorButton.js +5 -0
- package/source/class/qx/ui/table/pane/FocusIndicator.js +5 -4
- package/source/class/qx/ui/table/pane/Pane.js +14 -0
- package/source/class/qx/ui/table/pane/Scroller.js +3 -3
- package/source/class/qx/ui/virtual/core/Scroller.js +8 -2
- package/source/class/qx/ui/window/Window.js +9 -8
- package/source/resource/qx/iconfont/MaterialIcons/materialicons.json +10912 -0
- package/source/resource/qx/iconfont/MaterialIcons/materialiconsoutlined.json +10967 -0
- package/source/resource/qx/iconfont/MaterialIcons/materialiconsround.json +10992 -0
- package/source/resource/qx/iconfont/MaterialIcons/materialiconssharp.json +10992 -0
- package/source/resource/qx/iconfont/MaterialIcons/materialiconstwotone.json +9947 -0
- package/source/resource/qx/iconfont/MaterialIcons/x.json +10967 -0
- package/source/resource/qx/iconfont/export-glyphs.sh +22 -0
- package/source/resource/qx/mobile/scss/common/_gradients.scss +1 -1
- package/source/resource/qx/tool/cli/templates/skeleton/desktop/source/class/custom/Application.tmpl.js +7 -7
- package/source/resource/qx/tool/cli/templates/skeleton/desktop/source/class/custom/test/DemoTest.tmpl.js +10 -10
- package/source/resource/qx/tool/cli/templates/skeleton/mobile/source/class/custom/Application.tmpl.js +6 -6
- package/source/resource/qx/tool/cli/templates/skeleton/mobile/source/class/custom/page/Login.tmpl.js +9 -9
- package/source/resource/qx/tool/cli/templates/skeleton/mobile/source/class/custom/page/Overview.tmpl.js +5 -5
- package/source/resource/qx/tool/cli/templates/skeleton/package/source/class/custom/demo/Application.tmpl.js +7 -7
- package/source/resource/qx/tool/cli/templates/skeleton/package/source/class/custom/test/DemoTest.tmpl.js +10 -10
- package/source/resource/qx/tool/cli/templates/skeleton/server/source/class/custom/Application.tmpl.js +6 -6
- package/source/resource/qx/tool/cli/templates/skeleton/server/source/class/custom/test/DemoTest.tmpl.js +12 -12
- package/source/resource/qx/tool/schema/Manifest-1-0-0.json +79 -26
- package/source/resource/qx/tool/schema/Manifest-2-0-0.json +17 -26
- package/source/resource/qx/tool/schema/compile-1-0-0.json +40 -53
- package/source/resource/qx/tool/website/src/about.md +1 -1
- package/source/class/qx/bom/webfonts/Manager.js +0 -652
- package/source/class/qx/test/bom/webfonts/Manager.js +0 -238
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/* ************************************************************************
|
|
2
|
+
|
|
3
|
+
qooxdoo - the new era of web development
|
|
4
|
+
|
|
5
|
+
http://qooxdoo.org
|
|
6
|
+
|
|
7
|
+
Copyright:
|
|
8
|
+
2023 Zenesis Limited https://www.zenesis.com
|
|
9
|
+
|
|
10
|
+
License:
|
|
11
|
+
MIT: https://opensource.org/licenses/MIT
|
|
12
|
+
See the LICENSE file in the project's top-level directory for details.
|
|
13
|
+
|
|
14
|
+
Authors:
|
|
15
|
+
* John Spackman (@johnspackman)
|
|
16
|
+
|
|
17
|
+
************************************************************************ */
|
|
18
|
+
|
|
19
|
+
const fs = require("fs");
|
|
20
|
+
const path = require("path");
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Represents a font as defined in the Manifest.json's
|
|
24
|
+
*
|
|
25
|
+
* @typedef Sources
|
|
26
|
+
* @param {String?} family the family name that is in the font files (defaults to the name of the font)
|
|
27
|
+
* @param {String[]?} paths the filenames of font files inside the resources dircetory
|
|
28
|
+
* @param {String[]?} urls the urls of font files in a CDN
|
|
29
|
+
*
|
|
30
|
+
*/
|
|
31
|
+
qx.Class.define("qx.tool.compiler.app.ManifestFont", {
|
|
32
|
+
extend: qx.core.Object,
|
|
33
|
+
|
|
34
|
+
construct(name) {
|
|
35
|
+
super();
|
|
36
|
+
this.setName(name);
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
properties: {
|
|
40
|
+
/** The name of the font - this is the key in Manifest.json provides.fonts */
|
|
41
|
+
name: {
|
|
42
|
+
check: "String"
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
/** Default size of the font */
|
|
46
|
+
defaultSize: {
|
|
47
|
+
init: null,
|
|
48
|
+
nullable: true,
|
|
49
|
+
check: "Integer"
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/** Comparison string to be used */
|
|
53
|
+
comparisonString: {
|
|
54
|
+
init: null,
|
|
55
|
+
nullable: true,
|
|
56
|
+
check: "String"
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
/** CSS filenames or URLs to be loaded (indicating that font-face will be defined outside of Qooxdoo) */
|
|
60
|
+
css: {
|
|
61
|
+
init: null,
|
|
62
|
+
check: "Array",
|
|
63
|
+
nullable: true
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
/** Font faces that have to be defined, including the resource paths or urls */
|
|
67
|
+
fontFaces: {
|
|
68
|
+
init: null,
|
|
69
|
+
check: "Array",
|
|
70
|
+
nullable: true
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
/** Glyphs filename (relative to resources of the library that defines it) */
|
|
74
|
+
glyphs: {
|
|
75
|
+
init: null,
|
|
76
|
+
nullable: true,
|
|
77
|
+
check: "String"
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/** Family names for the browser to search for */
|
|
81
|
+
family: {
|
|
82
|
+
init: null,
|
|
83
|
+
nullable: true,
|
|
84
|
+
check: "Array"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
members: {
|
|
89
|
+
/** @type{Map<String,Object>} font data required by the Qooxdoo app at runtime */
|
|
90
|
+
__fontData: null,
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Updates this from the data in the Manifest.json
|
|
94
|
+
*
|
|
95
|
+
* @param {Object} data the data from Manifest
|
|
96
|
+
* @param {qx.tool.compiler.app.Library} library the library
|
|
97
|
+
*/
|
|
98
|
+
async updateFromManifest(data, library) {
|
|
99
|
+
let toSet = {};
|
|
100
|
+
[
|
|
101
|
+
"defaultSize",
|
|
102
|
+
"comparisonString",
|
|
103
|
+
"css",
|
|
104
|
+
"fontFaces",
|
|
105
|
+
"glyphs",
|
|
106
|
+
"family"
|
|
107
|
+
].forEach(name => {
|
|
108
|
+
if (data.hasOwnProperty(name)) {
|
|
109
|
+
toSet[name] = data[name];
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
this.set(toSet);
|
|
113
|
+
if (data.glyphs !== undefined) {
|
|
114
|
+
let glyphsFilename = library.getResourceFilename(data.glyphs);
|
|
115
|
+
let glyphsData = await fs.promises.readFile(glyphsFilename, "utf8");
|
|
116
|
+
glyphsData = JSON.parse(glyphsData);
|
|
117
|
+
this.__fontData = {};
|
|
118
|
+
let name = this.getName();
|
|
119
|
+
let defaultSize = this.getDefaultSize();
|
|
120
|
+
|
|
121
|
+
for (let key in glyphsData) {
|
|
122
|
+
let glyph = glyphsData[key];
|
|
123
|
+
this.__fontData["@" + name + "/" + key] = [
|
|
124
|
+
// width
|
|
125
|
+
Math.ceil((defaultSize * glyph.advanceWidth) / glyph.advanceHeight),
|
|
126
|
+
|
|
127
|
+
// height
|
|
128
|
+
defaultSize,
|
|
129
|
+
glyph.codePoint
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Generates the font data used by the application; loads the data if not already loaded
|
|
137
|
+
*
|
|
138
|
+
* @returns {Map<String,Object>}
|
|
139
|
+
*/
|
|
140
|
+
getApplicationFontData() {
|
|
141
|
+
return this.__fontData;
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Return bootstrap code that is executed before the Application starts.
|
|
146
|
+
*
|
|
147
|
+
* @param {qx.tool.compiler.targets.Target} target the target
|
|
148
|
+
* @param {qx.tool.compiler.app.Application} application the application being built
|
|
149
|
+
* @param {Boolean} useLocalFonts whether to use local fonts or use CSS
|
|
150
|
+
* @return {String} code to include in the output
|
|
151
|
+
*/
|
|
152
|
+
getBootstrapCode(target, application, useLocalFonts) {
|
|
153
|
+
let res = "";
|
|
154
|
+
let font = {
|
|
155
|
+
family: this.getFamily() || [this.getName()]
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
if (!useLocalFonts) {
|
|
159
|
+
if (this.getCss()) {
|
|
160
|
+
font.css = this.getCss();
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
font.fontFaces = this.getFontFaces();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (this.getDefaultSize() !== null) {
|
|
167
|
+
font.defaultSize = this.getDefaultSize();
|
|
168
|
+
}
|
|
169
|
+
if (this.getComparisonString() !== null) {
|
|
170
|
+
font.comparisonString = this.getComparisonString();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return (res +=
|
|
174
|
+
"qx.$$fontBootstrap['" +
|
|
175
|
+
this.getName() +
|
|
176
|
+
"']=" +
|
|
177
|
+
JSON.stringify(font, null, 2) +
|
|
178
|
+
";");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
@@ -88,236 +88,166 @@ qx.Class.define("qx.tool.compiler.app.WebFont", {
|
|
|
88
88
|
* Helper which triggers a local font analyze run.
|
|
89
89
|
*
|
|
90
90
|
* @param filename {String} Filename for the local font
|
|
91
|
-
* @return {
|
|
91
|
+
* @return {Map<String,String>} mapping of glyphs to codepoints
|
|
92
92
|
*/
|
|
93
|
-
_loadLocalFont(filename) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
);
|
|
93
|
+
async _loadLocalFont(filename) {
|
|
94
|
+
let fontpath = path.join(
|
|
95
|
+
this.__library.getRootDir(),
|
|
96
|
+
path.join(this.__library.getResourcePath(), filename)
|
|
97
|
+
);
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
});
|
|
99
|
+
return await this.__processFontFile(fontpath);
|
|
102
100
|
},
|
|
103
101
|
|
|
104
102
|
/**
|
|
105
103
|
* Helper which loads a remote font to analyze the result.
|
|
106
104
|
*
|
|
107
105
|
* @param url {String} URL for the font download
|
|
108
|
-
* @return {
|
|
106
|
+
* @return {Map<String,String>} mapping of glyphs to codepoints
|
|
109
107
|
*/
|
|
110
|
-
_loadRemoteFont(url) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
.get(
|
|
115
|
-
url,
|
|
116
|
-
function (res) {
|
|
117
|
-
let error;
|
|
118
|
-
const { statusCode } = res;
|
|
119
|
-
const contentType = res.headers["content-type"];
|
|
120
|
-
|
|
121
|
-
if (statusCode !== 200) {
|
|
122
|
-
error = new Error(
|
|
123
|
-
`Request Failed.\nStatus Code: ${statusCode}`
|
|
124
|
-
);
|
|
125
|
-
} else if (
|
|
126
|
-
!/^font\/(ttf|svg|eot|woff|woff2)$/.test(contentType)
|
|
127
|
-
) {
|
|
128
|
-
error = new Error(
|
|
129
|
-
"Invalid content-type.\n" +
|
|
130
|
-
`Expected font/ttf, font/svg, font/eot, font/woff or font/woff2 but received ${contentType}`
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (error) {
|
|
135
|
-
res.resume();
|
|
136
|
-
reject(error);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
tmp.tmpName(
|
|
141
|
-
function _tempNameGenerated(err, tmpFilename) {
|
|
142
|
-
if (err) {
|
|
143
|
-
reject(err);
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
let outFile = fs.createWriteStream(tmpFilename);
|
|
148
|
-
outFile.on(
|
|
149
|
-
"close",
|
|
150
|
-
function () {
|
|
151
|
-
this.__processFontFile(tmpFilename, resolve, reject);
|
|
152
|
-
fs.unlink(tmpFilename);
|
|
153
|
-
}.bind(this)
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
res.on("data", chunk => {
|
|
157
|
-
outFile.write(chunk);
|
|
158
|
-
});
|
|
159
|
-
res.on("end", function () {
|
|
160
|
-
outFile.end();
|
|
161
|
-
});
|
|
162
|
-
}.bind(this)
|
|
163
|
-
);
|
|
164
|
-
}.bind(this)
|
|
165
|
-
)
|
|
166
|
-
.on("error", e => {
|
|
167
|
-
reject(e);
|
|
168
|
-
});
|
|
169
|
-
}.bind(this)
|
|
108
|
+
async _loadRemoteFont(url) {
|
|
109
|
+
let tmpFilename = await qx.tool.utils.Http.downloadToTempFile(
|
|
110
|
+
url,
|
|
111
|
+
/^font\/(ttf|svg|eot|woff|woff2)$/
|
|
170
112
|
);
|
|
113
|
+
|
|
114
|
+
let result = await this.__processFontFile(tmpFilename);
|
|
115
|
+
fs.unlink(tmpFilename);
|
|
116
|
+
return result;
|
|
171
117
|
},
|
|
172
118
|
|
|
173
119
|
/**
|
|
174
120
|
* Common code to extract the desired font information from a font file
|
|
175
|
-
* on disk.
|
|
176
|
-
* local font retrieval).
|
|
121
|
+
* on disk.
|
|
177
122
|
*
|
|
178
123
|
* @param filename {String} Path to font file
|
|
179
|
-
* @
|
|
180
|
-
* @param reject {Function} External promise reject
|
|
124
|
+
* @return {Map<String,String>} mapping of glyphs to codepoints
|
|
181
125
|
*/
|
|
182
|
-
__processFontFile(filename
|
|
183
|
-
|
|
184
|
-
filename,
|
|
185
|
-
|
|
186
|
-
function (err, font) {
|
|
187
|
-
if (err) {
|
|
188
|
-
reject(err);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
let resources = {};
|
|
126
|
+
async __processFontFile(filename) {
|
|
127
|
+
let fn = qx.tool.utils.Promisify.promisify(cb =>
|
|
128
|
+
fontkit.open(filename, null, cb)
|
|
129
|
+
);
|
|
193
130
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (this.getMapping()) {
|
|
197
|
-
let mapPath = path.join(
|
|
198
|
-
this.__library.getRootDir(),
|
|
199
|
-
path.join(this.__library.getResourcePath(), this.getMapping())
|
|
200
|
-
);
|
|
131
|
+
let font = await fn();
|
|
132
|
+
let resources = {};
|
|
201
133
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
let map = JSON.parse(data);
|
|
210
|
-
Object.keys(map).forEach(key => {
|
|
211
|
-
let codePoint = parseInt(map[key], 16);
|
|
212
|
-
let glyph = font.glyphForCodePoint(codePoint);
|
|
213
|
-
if (!glyph.id) {
|
|
214
|
-
qx.tool.compiler.Console.trace(
|
|
215
|
-
`WARN: no glyph found in ${filename} ${key}: ${codePoint}`
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
resources["@" + this.getName() + "/" + key] = [
|
|
221
|
-
Math.ceil(
|
|
222
|
-
(this.getDefaultSize() * glyph.advanceWidth) /
|
|
223
|
-
glyph.advanceHeight
|
|
224
|
-
),
|
|
225
|
-
|
|
226
|
-
// width
|
|
227
|
-
this.getDefaultSize(), // height
|
|
228
|
-
codePoint
|
|
229
|
-
];
|
|
230
|
-
}, this);
|
|
231
|
-
|
|
232
|
-
resolve(resources);
|
|
233
|
-
return;
|
|
234
|
-
});
|
|
134
|
+
// If we have a mapping file, take qx.tool.compiler.Console.information instead
|
|
135
|
+
// of anaylzing the font.
|
|
136
|
+
if (this.getMapping()) {
|
|
137
|
+
let mapPath = path.join(
|
|
138
|
+
this.__library.getRootDir(),
|
|
139
|
+
path.join(this.__library.getResourcePath(), this.getMapping())
|
|
140
|
+
);
|
|
235
141
|
|
|
236
|
-
|
|
237
|
-
|
|
142
|
+
let data;
|
|
143
|
+
try {
|
|
144
|
+
data = await fs.promises.readFile(mapPath, { encoding: "utf-8" });
|
|
145
|
+
} catch (err) {
|
|
146
|
+
log.error(`Cannot read mapping file '${mapPath}': ${err.code}`);
|
|
147
|
+
throw err;
|
|
148
|
+
}
|
|
238
149
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
150
|
+
let map = JSON.parse(data);
|
|
151
|
+
Object.keys(map).forEach(key => {
|
|
152
|
+
let codePoint = parseInt(map[key], 16);
|
|
153
|
+
let glyph = font.glyphForCodePoint(codePoint);
|
|
154
|
+
if (!glyph.id) {
|
|
155
|
+
qx.tool.compiler.Console.trace(
|
|
156
|
+
`WARN: no glyph found in ${filename} ${key}: ${codePoint}`
|
|
242
157
|
);
|
|
243
158
|
|
|
244
|
-
resolve(resources);
|
|
245
159
|
return;
|
|
246
160
|
}
|
|
161
|
+
resources["@" + this.getName() + "/" + key] = [
|
|
162
|
+
Math.ceil(
|
|
163
|
+
(this.getDefaultSize() * glyph.advanceWidth) / glyph.advanceHeight
|
|
164
|
+
),
|
|
165
|
+
|
|
166
|
+
// width
|
|
167
|
+
this.getDefaultSize(), // height
|
|
168
|
+
codePoint
|
|
169
|
+
];
|
|
170
|
+
}, this);
|
|
171
|
+
|
|
172
|
+
return resources;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (!font.GSUB) {
|
|
176
|
+
qx.tool.compiler.Console.error(
|
|
177
|
+
`The webfont in ${filename} does not have any ligatures`
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
return resources;
|
|
181
|
+
}
|
|
247
182
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
});
|
|
183
|
+
// some IconFonts (MaterialIcons for example) use ligatures
|
|
184
|
+
// to name their icons. This code extracts the ligatures
|
|
185
|
+
// hat tip to Jossef Harush https://stackoverflow.com/questions/54721774/extracting-ttf-font-ligature-mappings/54728584
|
|
186
|
+
let ligatureName = {};
|
|
187
|
+
let lookupList = font.GSUB.lookupList.toArray();
|
|
188
|
+
let lookupListIndexes =
|
|
189
|
+
font.GSUB.featureList[0].feature.lookupListIndexes;
|
|
190
|
+
lookupListIndexes.forEach(index => {
|
|
191
|
+
let subTable = lookupList[index].subTables[0];
|
|
192
|
+
let leadingCharacters = [];
|
|
193
|
+
if (subTable.coverage.rangeRecords) {
|
|
194
|
+
subTable.coverage.rangeRecords.forEach(coverage => {
|
|
195
|
+
for (let i = coverage.start; i <= coverage.end; i++) {
|
|
196
|
+
let character = font.stringsForGlyph(i)[0];
|
|
197
|
+
leadingCharacters.push(character);
|
|
265
198
|
}
|
|
266
|
-
let ligatureSets = subTable.ligatureSets.toArray();
|
|
267
|
-
ligatureSets.forEach((ligatureSet, ligatureSetIndex) => {
|
|
268
|
-
let leadingCharacter = leadingCharacters[ligatureSetIndex];
|
|
269
|
-
ligatureSet.forEach(ligature => {
|
|
270
|
-
let character = font.stringsForGlyph(ligature.glyph)[0];
|
|
271
|
-
if (!character) {
|
|
272
|
-
// qx.tool.compiler.Console.log(`WARN: ${this.getName()} no character ${ligature}`);
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
let ligatureText =
|
|
276
|
-
leadingCharacter +
|
|
277
|
-
ligature.components
|
|
278
|
-
.map(x => font.stringsForGlyph(x)[0])
|
|
279
|
-
.join("");
|
|
280
|
-
var hexId = character.charCodeAt(0).toString(16);
|
|
281
|
-
if (ligatureName[hexId] == undefined) {
|
|
282
|
-
ligatureName[hexId] = [ligatureText];
|
|
283
|
-
} else {
|
|
284
|
-
ligatureName[hexId].push(ligatureText);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
199
|
});
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
200
|
+
}
|
|
201
|
+
let ligatureSets = subTable.ligatureSets.toArray();
|
|
202
|
+
ligatureSets.forEach((ligatureSet, ligatureSetIndex) => {
|
|
203
|
+
let leadingCharacter = leadingCharacters[ligatureSetIndex];
|
|
204
|
+
ligatureSet.forEach(ligature => {
|
|
205
|
+
let character = font.stringsForGlyph(ligature.glyph)[0];
|
|
206
|
+
if (!character) {
|
|
207
|
+
// qx.tool.compiler.Console.log(`WARN: ${this.getName()} no character ${ligature}`);
|
|
294
208
|
return;
|
|
295
209
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
// width
|
|
305
|
-
defaultSize, // height
|
|
306
|
-
codePoint
|
|
307
|
-
];
|
|
308
|
-
};
|
|
309
|
-
if (glyph.name) {
|
|
310
|
-
found(glyph.name);
|
|
311
|
-
}
|
|
312
|
-
var names = ligatureName[codePoint.toString(16)];
|
|
313
|
-
if (names) {
|
|
314
|
-
names.forEach(found);
|
|
210
|
+
let ligatureText =
|
|
211
|
+
leadingCharacter +
|
|
212
|
+
ligature.components.map(x => font.stringsForGlyph(x)[0]).join("");
|
|
213
|
+
var hexId = character.charCodeAt(0).toString(16);
|
|
214
|
+
if (ligatureName[hexId] == undefined) {
|
|
215
|
+
ligatureName[hexId] = [ligatureText];
|
|
216
|
+
} else {
|
|
217
|
+
ligatureName[hexId].push(ligatureText);
|
|
315
218
|
}
|
|
316
|
-
}
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
});
|
|
317
222
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
223
|
+
let defaultSize = this.getDefaultSize();
|
|
224
|
+
font.characterSet.forEach(codePoint => {
|
|
225
|
+
let glyph = font.glyphForCodePoint(codePoint);
|
|
226
|
+
if (glyph.path.commands.length < 1 && !glyph.layers) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const found = gName => {
|
|
231
|
+
resources["@" + this.getName() + "/" + gName] = [
|
|
232
|
+
Math.ceil(
|
|
233
|
+
(this.getDefaultSize() * glyph.advanceWidth) / glyph.advanceHeight
|
|
234
|
+
),
|
|
235
|
+
|
|
236
|
+
// width
|
|
237
|
+
defaultSize, // height
|
|
238
|
+
codePoint
|
|
239
|
+
];
|
|
240
|
+
};
|
|
241
|
+
if (glyph.name) {
|
|
242
|
+
found(glyph.name);
|
|
243
|
+
}
|
|
244
|
+
var names = ligatureName[codePoint.toString(16)];
|
|
245
|
+
if (names) {
|
|
246
|
+
names.forEach(found);
|
|
247
|
+
}
|
|
248
|
+
}, this);
|
|
249
|
+
|
|
250
|
+
return resources;
|
|
321
251
|
},
|
|
322
252
|
|
|
323
253
|
/**
|
|
@@ -325,24 +255,17 @@ qx.Class.define("qx.tool.compiler.app.WebFont", {
|
|
|
325
255
|
*
|
|
326
256
|
* @param target {qx.tool.compiler.targets.Target} the target
|
|
327
257
|
* @param application {qx.tool.compiler.app.Application} the application being built
|
|
328
|
-
* @param initial {Boolean} true if this is the first pass
|
|
329
258
|
* @return {String}
|
|
330
259
|
*/
|
|
331
|
-
getBootstrapCode(target, application
|
|
260
|
+
getBootstrapCode(target, application) {
|
|
332
261
|
let res = "";
|
|
333
|
-
|
|
334
|
-
if (initial) {
|
|
335
|
-
res = "qx.$$fontBootstrap={};\n";
|
|
336
|
-
}
|
|
337
|
-
|
|
338
262
|
let font = {
|
|
339
|
-
|
|
263
|
+
defaultSize: this.getDefaultSize(),
|
|
340
264
|
lineHeight: 1,
|
|
341
265
|
family: [this.getName()],
|
|
342
|
-
|
|
266
|
+
fontFaces: [
|
|
343
267
|
{
|
|
344
|
-
|
|
345
|
-
source: this.getResources()
|
|
268
|
+
paths: this.getResources()
|
|
346
269
|
}
|
|
347
270
|
]
|
|
348
271
|
};
|
|
@@ -355,7 +278,7 @@ qx.Class.define("qx.tool.compiler.app.WebFont", {
|
|
|
355
278
|
"qx.$$fontBootstrap['" +
|
|
356
279
|
this.getName() +
|
|
357
280
|
"']=" +
|
|
358
|
-
JSON.stringify(font) +
|
|
281
|
+
JSON.stringify(font, null, 2) +
|
|
359
282
|
";");
|
|
360
283
|
},
|
|
361
284
|
|
|
@@ -371,7 +294,7 @@ qx.Class.define("qx.tool.compiler.app.WebFont", {
|
|
|
371
294
|
return this.__generateForTargetPromise;
|
|
372
295
|
}
|
|
373
296
|
|
|
374
|
-
|
|
297
|
+
const generate = async () => {
|
|
375
298
|
for (let resource of this.getResources()) {
|
|
376
299
|
// Search for the first supported extension
|
|
377
300
|
let basename = resource.match(/^.*[/\\]([^/\\\?#]+).*$/)[1];
|
|
@@ -379,35 +302,22 @@ qx.Class.define("qx.tool.compiler.app.WebFont", {
|
|
|
379
302
|
if (!basename.match(/\.(ttf|otf|woff|woff2)$/)) {
|
|
380
303
|
continue;
|
|
381
304
|
}
|
|
382
|
-
|
|
383
|
-
// first.
|
|
305
|
+
|
|
384
306
|
if (resource.match(/^https?:\/\//)) {
|
|
385
|
-
this._loadRemoteFont(resource)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
resolve();
|
|
389
|
-
})
|
|
390
|
-
.catch(err => {
|
|
391
|
-
reject(err);
|
|
392
|
-
});
|
|
393
|
-
return;
|
|
307
|
+
this.__fontData = await this._loadRemoteFont(resource);
|
|
308
|
+
} else {
|
|
309
|
+
this.__fontData = await this._loadLocalFont(resource);
|
|
394
310
|
}
|
|
395
|
-
|
|
396
|
-
this.
|
|
397
|
-
.then(data => {
|
|
398
|
-
this.__fontData = data;
|
|
399
|
-
resolve();
|
|
400
|
-
})
|
|
401
|
-
.catch(err => {
|
|
402
|
-
reject(err);
|
|
403
|
-
});
|
|
404
|
-
return;
|
|
311
|
+
|
|
312
|
+
return this.__fontData;
|
|
405
313
|
}
|
|
406
|
-
|
|
314
|
+
|
|
315
|
+
throw new Error(
|
|
407
316
|
`Failed to load/validate FontMap for webfont (expected ttf, otf, woff or woff2) ${this.getName()}`
|
|
408
317
|
);
|
|
409
|
-
}
|
|
318
|
+
};
|
|
410
319
|
|
|
320
|
+
this.__generateForTargetPromise = generate();
|
|
411
321
|
return this.__generateForTargetPromise;
|
|
412
322
|
},
|
|
413
323
|
|
|
@@ -165,6 +165,18 @@ qx.Class.define("qx.tool.compiler.makers.AppMaker", {
|
|
|
165
165
|
this.__applications.forEach(app => app.setAnalyser(analyser));
|
|
166
166
|
await target.open();
|
|
167
167
|
|
|
168
|
+
for (let library of analyser.getLibraries()) {
|
|
169
|
+
let fontsData = library.getFontsData();
|
|
170
|
+
for (let fontName in fontsData) {
|
|
171
|
+
let fontData = fontsData[fontName];
|
|
172
|
+
let font = analyser.getFont(fontName);
|
|
173
|
+
if (!font) {
|
|
174
|
+
font = analyser.getFont(fontName, true);
|
|
175
|
+
await font.updateFromManifest(fontData, library);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
168
180
|
if (this.isOutputTypescript()) {
|
|
169
181
|
analyser.getLibraries().forEach(library => {
|
|
170
182
|
var symbols = library.getKnownSymbols();
|
|
@@ -208,6 +220,7 @@ qx.Class.define("qx.tool.compiler.makers.AppMaker", {
|
|
|
208
220
|
let stat = await qx.tool.utils.files.Utils.safeStat(
|
|
209
221
|
localModules[requireName]
|
|
210
222
|
);
|
|
223
|
+
|
|
211
224
|
res ||=
|
|
212
225
|
stat.mtime.getTime() >
|
|
213
226
|
(db?.modulesInfo?.localModules[requireName] || 0);
|