@loaders.gl/textures 3.1.8 → 3.2.0-alpha.1
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/dist/basis-worker.js +57 -26
- package/dist/compressed-texture-loader.d.ts +1 -1
- package/dist/compressed-texture-loader.js +1 -1
- package/dist/compressed-texture-worker.js +58 -27
- package/dist/crunch-worker.js +61 -29
- package/dist/dist.min.js +13 -13
- package/dist/es5/compressed-texture-loader.js +1 -1
- package/dist/es5/compressed-texture-loader.js.map +1 -1
- package/dist/es5/index.js.map +1 -1
- package/dist/es5/lib/parsers/basis-module-loader.js +1 -1
- package/dist/es5/lib/parsers/basis-module-loader.js.map +1 -1
- package/dist/es5/lib/parsers/parse-basis.js +8 -8
- package/dist/es5/lib/parsers/parse-basis.js.map +1 -1
- package/dist/es5/lib/parsers/parse-compressed-texture.js.map +1 -1
- package/dist/es5/lib/parsers/parse-crunch.js +8 -7
- package/dist/es5/lib/parsers/parse-crunch.js.map +1 -1
- package/dist/es5/lib/parsers/parse-dds.js.map +1 -1
- package/dist/es5/lib/parsers/parse-ktx.js.map +1 -1
- package/dist/es5/lib/parsers/parse-npy.js.map +1 -1
- package/dist/es5/lib/parsers/parse-pvr.js.map +1 -1
- package/dist/es5/lib/utils/extract-mipmap-images.js.map +1 -1
- package/dist/es5/lib/utils/texture-formats.js.map +1 -1
- package/dist/es5/lib/utils/version.js +1 -1
- package/dist/es5/lib/utils/version.js.map +1 -1
- package/dist/esm/compressed-texture-loader.js +1 -1
- package/dist/esm/compressed-texture-loader.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/parsers/basis-module-loader.js +1 -1
- package/dist/esm/lib/parsers/basis-module-loader.js.map +1 -1
- package/dist/esm/lib/parsers/parse-basis.js +8 -8
- package/dist/esm/lib/parsers/parse-basis.js.map +1 -1
- package/dist/esm/lib/parsers/parse-compressed-texture.js.map +1 -1
- package/dist/esm/lib/parsers/parse-crunch.js +13 -12
- package/dist/esm/lib/parsers/parse-crunch.js.map +1 -1
- package/dist/esm/lib/parsers/parse-dds.js.map +1 -1
- package/dist/esm/lib/parsers/parse-ktx.js.map +1 -1
- package/dist/esm/lib/parsers/parse-npy.js.map +1 -1
- package/dist/esm/lib/parsers/parse-pvr.js.map +1 -1
- package/dist/esm/lib/utils/extract-mipmap-images.js.map +1 -1
- package/dist/esm/lib/utils/texture-formats.js.map +1 -1
- package/dist/esm/lib/utils/version.js +1 -1
- package/dist/esm/lib/utils/version.js.map +1 -1
- package/dist/esm/types.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/parsers/basis-module-loader.js +1 -1
- package/dist/lib/parsers/parse-basis.d.ts +8 -6
- package/dist/lib/parsers/parse-basis.d.ts.map +1 -1
- package/dist/lib/parsers/parse-basis.js +25 -25
- package/dist/lib/parsers/parse-compressed-texture.d.ts +1 -1
- package/dist/lib/parsers/parse-compressed-texture.d.ts.map +1 -1
- package/dist/lib/parsers/parse-crunch.d.ts +1 -1
- package/dist/lib/parsers/parse-crunch.d.ts.map +1 -1
- package/dist/lib/parsers/parse-crunch.js +14 -13
- package/dist/lib/parsers/parse-dds.d.ts +1 -1
- package/dist/lib/parsers/parse-dds.d.ts.map +1 -1
- package/dist/lib/parsers/parse-ktx.d.ts +2 -1
- package/dist/lib/parsers/parse-ktx.d.ts.map +1 -1
- package/dist/lib/parsers/parse-npy.d.ts.map +1 -1
- package/dist/lib/parsers/parse-npy.js +1 -0
- package/dist/lib/parsers/parse-pvr.d.ts +1 -1
- package/dist/lib/parsers/parse-pvr.d.ts.map +1 -1
- package/dist/lib/parsers/parse-pvr.js +2 -2
- package/dist/lib/utils/extract-mipmap-images.d.ts +8 -1
- package/dist/lib/utils/extract-mipmap-images.d.ts.map +1 -1
- package/dist/lib/utils/version.d.ts.map +1 -1
- package/dist/lib/utils/version.js +2 -1
- package/dist/npy-worker.js +46 -15
- package/dist/types.d.ts +0 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -1
- package/package.json +6 -5
- package/src/compressed-texture-loader.ts +1 -1
- package/src/index.ts +1 -1
- package/src/lib/parsers/basis-module-loader.ts +1 -1
- package/src/lib/parsers/parse-basis.ts +68 -36
- package/src/lib/parsers/parse-compressed-texture.ts +1 -1
- package/src/lib/parsers/parse-crunch.ts +15 -14
- package/src/lib/parsers/parse-dds.ts +1 -1
- package/src/lib/parsers/parse-ktx.ts +2 -1
- package/src/lib/parsers/parse-npy.ts +2 -0
- package/src/lib/parsers/parse-pvr.ts +2 -1
- package/src/lib/utils/extract-mipmap-images.ts +9 -1
- package/src/lib/utils/texture-formats.ts +1 -1
- package/src/lib/utils/version.ts +2 -1
- package/src/types.ts +0 -30
|
@@ -1,9 +1,36 @@
|
|
|
1
|
+
/* eslint-disable indent */
|
|
2
|
+
import type {TextureLevel} from '@loaders.gl/schema';
|
|
1
3
|
import {loadBasisEncoderModule, loadBasisTrascoderModule} from './basis-module-loader';
|
|
2
4
|
import {GL_EXTENSIONS_CONSTANTS} from '../gl-extensions';
|
|
3
5
|
import {getSupportedGPUTextureFormats} from '../utils/texture-formats';
|
|
4
6
|
import {isKTX} from './parse-ktx';
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
export type BasisFormat =
|
|
9
|
+
| 'etc1'
|
|
10
|
+
| 'etc2'
|
|
11
|
+
| 'bc1'
|
|
12
|
+
| 'bc3'
|
|
13
|
+
| 'bc4'
|
|
14
|
+
| 'bc5'
|
|
15
|
+
| 'bc7-m6-opaque-only'
|
|
16
|
+
| 'bc7-m5'
|
|
17
|
+
| 'pvrtc1-4-rgb'
|
|
18
|
+
| 'pvrtc1-4-rgba'
|
|
19
|
+
| 'astc-4x4'
|
|
20
|
+
| 'atc-rgb'
|
|
21
|
+
| 'atc-rgba-interpolated-alpha'
|
|
22
|
+
| 'rgba32'
|
|
23
|
+
| 'rgb565'
|
|
24
|
+
| 'bgr565'
|
|
25
|
+
| 'rgba4444';
|
|
26
|
+
|
|
27
|
+
type BasisOutputOptions = {
|
|
28
|
+
basisFormat: number;
|
|
29
|
+
compressed: boolean;
|
|
30
|
+
format?: number;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const OutputFormat: Record<string, BasisOutputOptions> = {
|
|
7
34
|
etc1: {
|
|
8
35
|
basisFormat: 0,
|
|
9
36
|
compressed: true,
|
|
@@ -49,11 +76,11 @@ const OutputFormat = {
|
|
|
49
76
|
|
|
50
77
|
/**
|
|
51
78
|
* parse data with a Binomial Basis_Universal module
|
|
52
|
-
* @param
|
|
53
|
-
* @param
|
|
79
|
+
* @param data
|
|
80
|
+
* @param options
|
|
54
81
|
* @returns compressed texture data
|
|
55
82
|
*/
|
|
56
|
-
export default async function parseBasis(data, options) {
|
|
83
|
+
export default async function parseBasis(data: ArrayBuffer, options): Promise<TextureLevel[][]> {
|
|
57
84
|
if (options.basis.containerFormat === 'auto') {
|
|
58
85
|
if (isKTX(data)) {
|
|
59
86
|
const fileConstructors = await loadBasisEncoderModule(options);
|
|
@@ -81,25 +108,25 @@ export default async function parseBasis(data, options) {
|
|
|
81
108
|
|
|
82
109
|
/**
|
|
83
110
|
* Parse *.basis file data
|
|
84
|
-
* @param
|
|
85
|
-
* @param
|
|
86
|
-
* @param
|
|
111
|
+
* @param BasisFile - initialized transcoder module
|
|
112
|
+
* @param data
|
|
113
|
+
* @param options
|
|
87
114
|
* @returns compressed texture data
|
|
88
115
|
*/
|
|
89
|
-
function parseBasisFile(BasisFile, data, options) {
|
|
116
|
+
function parseBasisFile(BasisFile, data, options): TextureLevel[][] {
|
|
90
117
|
const basisFile = new BasisFile(new Uint8Array(data));
|
|
91
118
|
|
|
92
119
|
try {
|
|
93
120
|
if (!basisFile.startTranscoding()) {
|
|
94
|
-
|
|
121
|
+
throw new Error('Failed to start basis transcoding');
|
|
95
122
|
}
|
|
96
123
|
|
|
97
124
|
const imageCount = basisFile.getNumImages();
|
|
98
|
-
const images:
|
|
125
|
+
const images: TextureLevel[][] = [];
|
|
99
126
|
|
|
100
127
|
for (let imageIndex = 0; imageIndex < imageCount; imageIndex++) {
|
|
101
128
|
const levelsCount = basisFile.getNumLevels(imageIndex);
|
|
102
|
-
const levels:
|
|
129
|
+
const levels: TextureLevel[] = [];
|
|
103
130
|
|
|
104
131
|
for (let levelIndex = 0; levelIndex < levelsCount; levelIndex++) {
|
|
105
132
|
levels.push(transcodeImage(basisFile, imageIndex, levelIndex, options));
|
|
@@ -117,13 +144,13 @@ function parseBasisFile(BasisFile, data, options) {
|
|
|
117
144
|
|
|
118
145
|
/**
|
|
119
146
|
* Parse the particular level image of a basis file
|
|
120
|
-
* @param
|
|
121
|
-
* @param
|
|
122
|
-
* @param
|
|
123
|
-
* @param
|
|
147
|
+
* @param basisFile
|
|
148
|
+
* @param imageIndex
|
|
149
|
+
* @param levelIndex
|
|
150
|
+
* @param options
|
|
124
151
|
* @returns compressed texture data
|
|
125
152
|
*/
|
|
126
|
-
function transcodeImage(basisFile, imageIndex, levelIndex, options) {
|
|
153
|
+
function transcodeImage(basisFile, imageIndex, levelIndex, options): TextureLevel {
|
|
127
154
|
const width = basisFile.getImageWidth(imageIndex, levelIndex);
|
|
128
155
|
const height = basisFile.getImageHeight(imageIndex, levelIndex);
|
|
129
156
|
|
|
@@ -137,7 +164,7 @@ function transcodeImage(basisFile, imageIndex, levelIndex, options) {
|
|
|
137
164
|
const decodedData = new Uint8Array(decodedSize);
|
|
138
165
|
|
|
139
166
|
if (!basisFile.transcodeImage(decodedData, imageIndex, levelIndex, basisFormat, 0, 0)) {
|
|
140
|
-
|
|
167
|
+
throw new Error('failed to start Basis transcoding');
|
|
141
168
|
}
|
|
142
169
|
|
|
143
170
|
return {
|
|
@@ -146,37 +173,37 @@ function transcodeImage(basisFile, imageIndex, levelIndex, options) {
|
|
|
146
173
|
height,
|
|
147
174
|
data: decodedData,
|
|
148
175
|
compressed,
|
|
176
|
+
format,
|
|
149
177
|
|
|
150
178
|
// Additional fields
|
|
151
179
|
// Add levelSize field.
|
|
152
|
-
hasAlpha
|
|
153
|
-
format
|
|
180
|
+
hasAlpha
|
|
154
181
|
};
|
|
155
182
|
}
|
|
156
183
|
|
|
157
184
|
/**
|
|
158
185
|
* Parse *.ktx2 file data
|
|
159
|
-
* @param
|
|
160
|
-
* @param
|
|
161
|
-
* @param
|
|
186
|
+
* @param KTX2File
|
|
187
|
+
* @param data
|
|
188
|
+
* @param options
|
|
162
189
|
* @returns compressed texture data
|
|
163
190
|
*/
|
|
164
|
-
function parseKTX2File(KTX2File, data, options) {
|
|
191
|
+
function parseKTX2File(KTX2File, data: ArrayBuffer, options): TextureLevel[][] {
|
|
165
192
|
const ktx2File = new KTX2File(new Uint8Array(data));
|
|
166
193
|
|
|
167
194
|
try {
|
|
168
195
|
if (!ktx2File.startTranscoding()) {
|
|
169
|
-
|
|
196
|
+
throw new Error('failed to start KTX2 transcoding');
|
|
170
197
|
}
|
|
171
198
|
const levelsCount = ktx2File.getLevels();
|
|
172
|
-
const levels:
|
|
199
|
+
const levels: TextureLevel[] = [];
|
|
173
200
|
|
|
174
201
|
for (let levelIndex = 0; levelIndex < levelsCount; levelIndex++) {
|
|
175
202
|
levels.push(transcodeKTX2Image(ktx2File, levelIndex, options));
|
|
176
203
|
break; // texture app can only show one level for some reason
|
|
177
204
|
}
|
|
178
205
|
|
|
179
|
-
return levels;
|
|
206
|
+
return [levels];
|
|
180
207
|
} finally {
|
|
181
208
|
ktx2File.close();
|
|
182
209
|
ktx2File.delete();
|
|
@@ -185,12 +212,12 @@ function parseKTX2File(KTX2File, data, options) {
|
|
|
185
212
|
|
|
186
213
|
/**
|
|
187
214
|
* Parse the particular level image of a ktx2 file
|
|
188
|
-
* @param
|
|
189
|
-
* @param
|
|
190
|
-
* @param
|
|
215
|
+
* @param ktx2File
|
|
216
|
+
* @param levelIndex
|
|
217
|
+
* @param options
|
|
191
218
|
* @returns
|
|
192
219
|
*/
|
|
193
|
-
function transcodeKTX2Image(ktx2File, levelIndex, options) {
|
|
220
|
+
function transcodeKTX2Image(ktx2File, levelIndex: number, options): TextureLevel {
|
|
194
221
|
const {alphaFlag, height, width} = ktx2File.getImageLevelInfo(levelIndex, 0, 0);
|
|
195
222
|
|
|
196
223
|
// Check options for output format etc
|
|
@@ -216,7 +243,7 @@ function transcodeKTX2Image(ktx2File, levelIndex, options) {
|
|
|
216
243
|
-1 /* channel1 */
|
|
217
244
|
)
|
|
218
245
|
) {
|
|
219
|
-
|
|
246
|
+
throw new Error('Failed to transcode KTX2 image');
|
|
220
247
|
}
|
|
221
248
|
|
|
222
249
|
return {
|
|
@@ -228,18 +255,18 @@ function transcodeKTX2Image(ktx2File, levelIndex, options) {
|
|
|
228
255
|
|
|
229
256
|
// Additional fields
|
|
230
257
|
// Add levelSize field.
|
|
231
|
-
alphaFlag,
|
|
258
|
+
hasAlpha: alphaFlag,
|
|
232
259
|
format
|
|
233
260
|
};
|
|
234
261
|
}
|
|
235
262
|
|
|
236
263
|
/**
|
|
237
264
|
* Get BasisFormat by loader format option
|
|
238
|
-
* @param
|
|
239
|
-
* @param
|
|
265
|
+
* @param options
|
|
266
|
+
* @param hasAlpha
|
|
240
267
|
* @returns BasisFormat data
|
|
241
268
|
*/
|
|
242
|
-
function getBasisOptions(options, hasAlpha) {
|
|
269
|
+
function getBasisOptions(options, hasAlpha: boolean): BasisOutputOptions {
|
|
243
270
|
let format = options && options.basis && options.basis.format;
|
|
244
271
|
if (format === 'auto') {
|
|
245
272
|
format = selectSupportedBasisFormat();
|
|
@@ -255,7 +282,12 @@ function getBasisOptions(options, hasAlpha) {
|
|
|
255
282
|
* Select transcode format from the list of supported formats
|
|
256
283
|
* @returns key for OutputFormat map
|
|
257
284
|
*/
|
|
258
|
-
export function selectSupportedBasisFormat()
|
|
285
|
+
export function selectSupportedBasisFormat():
|
|
286
|
+
| BasisFormat
|
|
287
|
+
| {
|
|
288
|
+
alpha: BasisFormat;
|
|
289
|
+
noAlpha: BasisFormat;
|
|
290
|
+
} {
|
|
259
291
|
const supportedFormats = getSupportedGPUTextureFormats();
|
|
260
292
|
if (supportedFormats.has('astc')) {
|
|
261
293
|
return 'astc-4x4';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {TextureLevel} from '
|
|
1
|
+
import type {TextureLevel} from '@loaders.gl/schema';
|
|
2
2
|
import {loadCrunchModule} from './crunch-module-loader';
|
|
3
3
|
import {GL_EXTENSIONS_CONSTANTS} from '../gl-extensions';
|
|
4
4
|
import {assert} from '@loaders.gl/loader-utils';
|
|
@@ -17,19 +17,20 @@ const CRN_FORMAT = {
|
|
|
17
17
|
// Crunch supports more formats than this.
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
const DXT_FORMAT_MAP = {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
/** Mapping of Crunch formats to DXT formats. */
|
|
21
|
+
const DXT_FORMAT_MAP = {
|
|
22
|
+
[CRN_FORMAT.cCRNFmtDXT1]: {
|
|
23
|
+
pixelFormat: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGB_S3TC_DXT1_EXT,
|
|
24
|
+
sizeFunction: getDxt1LevelSize
|
|
25
|
+
},
|
|
26
|
+
[CRN_FORMAT.cCRNFmtDXT3]: {
|
|
27
|
+
pixelFormat: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT3_EXT,
|
|
28
|
+
sizeFunction: getDxtXLevelSize
|
|
29
|
+
},
|
|
30
|
+
[CRN_FORMAT.cCRNFmtDXT5]: {
|
|
31
|
+
pixelFormat: GL_EXTENSIONS_CONSTANTS.COMPRESSED_RGBA_S3TC_DXT5_EXT,
|
|
32
|
+
sizeFunction: getDxtXLevelSize
|
|
33
|
+
}
|
|
33
34
|
};
|
|
34
35
|
|
|
35
36
|
let cachedDstSize = 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {TextureLevel} from '
|
|
1
|
+
import type {TextureLevel} from '@loaders.gl/schema';
|
|
2
2
|
import {assert} from '@loaders.gl/loader-utils';
|
|
3
3
|
import {GL_EXTENSIONS_CONSTANTS} from '../gl-extensions';
|
|
4
4
|
import {extractMipmapImages} from '../utils/extract-mipmap-images';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type {TextureLevel} from '@loaders.gl/schema';
|
|
1
2
|
import {read} from 'ktx-parse';
|
|
2
3
|
import {extractMipmapImages} from '../utils/extract-mipmap-images';
|
|
3
4
|
import {mapVkFormatToWebGL} from '../utils/ktx-format-helper';
|
|
@@ -29,7 +30,7 @@ export function isKTX(data: ArrayBuffer) {
|
|
|
29
30
|
return !notKTX;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
export function parseKTX(arrayBuffer: ArrayBuffer) {
|
|
33
|
+
export function parseKTX(arrayBuffer: ArrayBuffer): TextureLevel[] {
|
|
33
34
|
const uint8Array = new Uint8Array(arrayBuffer);
|
|
34
35
|
const ktx = read(uint8Array);
|
|
35
36
|
const mipMapLevels = Math.max(1, ktx.levels.length);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {TextureLevel} from '../../types';
|
|
2
1
|
/* eslint-disable camelcase */
|
|
3
2
|
// Forked from PicoGL: https://github.com/tsherif/picogl.js/blob/master/examples/utils/utils.js
|
|
4
3
|
// Copyright (c) 2017 Tarek Sherif, The MIT License (MIT)
|
|
4
|
+
|
|
5
|
+
import type {TextureLevel} from '@loaders.gl/schema';
|
|
5
6
|
import {GL_EXTENSIONS_CONSTANTS} from '../gl-extensions';
|
|
6
7
|
import {extractMipmapImages} from '../utils/extract-mipmap-images';
|
|
7
8
|
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {TextureLevel} from '@loaders.gl/schema';
|
|
2
|
+
|
|
3
|
+
export type CompressedTextureExtractOptions = {
|
|
4
|
+
mipMapLevels: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
sizeFunction: Function;
|
|
8
|
+
internalFormat: number;
|
|
9
|
+
};
|
|
2
10
|
|
|
3
11
|
/**
|
|
4
12
|
* Extract mipmap images from compressed texture buffer
|
package/src/lib/utils/version.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Version constant cannot be imported, it needs to correspond to the build version of **this** module.
|
|
2
2
|
// __VERSION__ is injected by babel-plugin-version-inline
|
|
3
|
+
// TODO: use 'latest' instead of 'beta' when 3.0.0 version is released as 'latest'
|
|
3
4
|
// @ts-ignore TS2304: Cannot find name '__VERSION__'.
|
|
4
|
-
export const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '
|
|
5
|
+
export const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'beta';
|
package/src/types.ts
CHANGED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* These represent the main compressed texture formats
|
|
3
|
-
* Each format typically has a number of more specific subformats
|
|
4
|
-
*/
|
|
5
|
-
export type GPUTextureFormat =
|
|
6
|
-
| 'dxt'
|
|
7
|
-
| 'dxt-srgb'
|
|
8
|
-
| 'etc1'
|
|
9
|
-
| 'etc2'
|
|
10
|
-
| 'pvrtc'
|
|
11
|
-
| 'atc'
|
|
12
|
-
| 'astc'
|
|
13
|
-
| 'rgtc';
|
|
14
|
-
|
|
15
|
-
export interface TextureLevel {
|
|
16
|
-
compressed: boolean;
|
|
17
|
-
format: number;
|
|
18
|
-
data: Uint8Array;
|
|
19
|
-
witdh: number;
|
|
20
|
-
height: number;
|
|
21
|
-
levelSize?: number;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface CompressedTextureExtractOptions {
|
|
25
|
-
mipMapLevels: number;
|
|
26
|
-
width: number;
|
|
27
|
-
height: number;
|
|
28
|
-
sizeFunction: Function;
|
|
29
|
-
internalFormat: number;
|
|
30
|
-
}
|