@ni/nimble-components 29.1.7 → 29.1.8
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/all-components-bundle.js +393 -340
- package/dist/all-components-bundle.js.map +1 -1
- package/dist/all-components-bundle.min.js +1377 -1377
- package/dist/all-components-bundle.min.js.map +1 -1
- package/dist/esm/wafer-map/{modules/experimental → experimental}/computations.d.ts +25 -8
- package/dist/esm/wafer-map/{modules/experimental → experimental}/computations.js +87 -8
- package/dist/esm/wafer-map/experimental/computations.js.map +1 -0
- package/dist/esm/wafer-map/{modules/experimental → experimental}/hover-handler.d.ts +1 -1
- package/dist/esm/wafer-map/{modules/experimental → experimental}/hover-handler.js +3 -5
- package/dist/esm/wafer-map/experimental/hover-handler.js.map +1 -0
- package/dist/esm/wafer-map/experimental/worker-renderer.d.ts +24 -0
- package/dist/esm/wafer-map/experimental/worker-renderer.js +75 -0
- package/dist/esm/wafer-map/experimental/worker-renderer.js.map +1 -0
- package/dist/esm/wafer-map/index.d.ts +4 -3
- package/dist/esm/wafer-map/index.js +54 -18
- package/dist/esm/wafer-map/index.js.map +1 -1
- package/dist/esm/wafer-map/modules/computations.d.ts +1 -1
- package/dist/esm/wafer-map/modules/computations.js.map +1 -1
- package/dist/esm/wafer-map/modules/data-manager.d.ts +2 -1
- package/dist/esm/wafer-map/modules/data-manager.js.map +1 -1
- package/dist/esm/wafer-map/modules/prerendering.js.map +1 -1
- package/dist/esm/wafer-map/modules/wafer-map-update-tracker.d.ts +4 -0
- package/dist/esm/wafer-map/modules/wafer-map-update-tracker.js +37 -2
- package/dist/esm/wafer-map/modules/wafer-map-update-tracker.js.map +1 -1
- package/dist/esm/wafer-map/types.d.ts +0 -16
- package/dist/esm/wafer-map/types.js.map +1 -1
- package/dist/esm/wafer-map/workers/matrix-renderer.d.ts +1 -1
- package/dist/esm/wafer-map/workers/matrix-renderer.js +1 -1
- package/dist/esm/wafer-map/workers/matrix-renderer.js.map +1 -1
- package/dist/esm/wafer-map/workers/types.d.ts +39 -0
- package/dist/esm/wafer-map/workers/types.js +2 -0
- package/dist/esm/wafer-map/workers/types.js.map +1 -0
- package/package.json +1 -1
- package/dist/esm/wafer-map/modules/experimental/computations.js.map +0 -1
- package/dist/esm/wafer-map/modules/experimental/data-manager.d.ts +0 -21
- package/dist/esm/wafer-map/modules/experimental/data-manager.js +0 -41
- package/dist/esm/wafer-map/modules/experimental/data-manager.js.map +0 -1
- package/dist/esm/wafer-map/modules/experimental/hover-handler.js.map +0 -1
- package/dist/esm/wafer-map/modules/experimental/prerendering.d.ts +0 -18
- package/dist/esm/wafer-map/modules/experimental/prerendering.js +0 -63
- package/dist/esm/wafer-map/modules/experimental/prerendering.js.map +0 -1
- package/dist/esm/wafer-map/modules/experimental/worker-renderer.d.ts +0 -13
- package/dist/esm/wafer-map/modules/experimental/worker-renderer.js +0 -96
- package/dist/esm/wafer-map/modules/experimental/worker-renderer.js.map +0 -1
|
@@ -16278,7 +16278,7 @@
|
|
|
16278
16278
|
|
|
16279
16279
|
/**
|
|
16280
16280
|
* Do not edit directly
|
|
16281
|
-
* Generated on
|
|
16281
|
+
* Generated on Mon, 03 Jun 2024 22:13:03 GMT
|
|
16282
16282
|
*/
|
|
16283
16283
|
|
|
16284
16284
|
const Information100DarkUi = "#a46eff";
|
|
@@ -52912,9 +52912,9 @@ img.ProseMirror-separator {
|
|
|
52912
52912
|
strong: {
|
|
52913
52913
|
parseDOM: [
|
|
52914
52914
|
{ tag: "strong" },
|
|
52915
|
-
{ tag: "b", getAttrs:
|
|
52915
|
+
{ tag: "b", getAttrs: node => node.style.fontWeight != "normal" && null },
|
|
52916
52916
|
{ style: "font-weight=400", clearMark: m => m.type.name == "strong" },
|
|
52917
|
-
{ style: "font-weight", getAttrs:
|
|
52917
|
+
{ style: "font-weight", getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null }
|
|
52918
52918
|
],
|
|
52919
52919
|
toDOM() { return ["strong"]; }
|
|
52920
52920
|
},
|
|
@@ -53168,6 +53168,7 @@ img.ProseMirror-separator {
|
|
|
53168
53168
|
code_inline: { mark: "code", noCloseToken: true }
|
|
53169
53169
|
});
|
|
53170
53170
|
|
|
53171
|
+
const blankMark = { open: "", close: "", mixable: true };
|
|
53171
53172
|
/**
|
|
53172
53173
|
A specification for serializing a ProseMirror document as
|
|
53173
53174
|
Markdown/CommonMark text.
|
|
@@ -53375,6 +53376,18 @@ img.ProseMirror-separator {
|
|
|
53375
53376
|
}
|
|
53376
53377
|
}
|
|
53377
53378
|
/**
|
|
53379
|
+
@internal
|
|
53380
|
+
*/
|
|
53381
|
+
getMark(name) {
|
|
53382
|
+
let info = this.marks[name];
|
|
53383
|
+
if (!info) {
|
|
53384
|
+
if (this.options.strict !== false)
|
|
53385
|
+
throw new Error(`Mark type \`${name}\` not supported by Markdown renderer`);
|
|
53386
|
+
info = blankMark;
|
|
53387
|
+
}
|
|
53388
|
+
return info;
|
|
53389
|
+
}
|
|
53390
|
+
/**
|
|
53378
53391
|
Render a block, prefixing each line with `delim`, and the first
|
|
53379
53392
|
line in `firstDelim`. `node` should be the node that is closed at
|
|
53380
53393
|
the end of the block, and `f` is a function that renders the
|
|
@@ -53439,9 +53452,22 @@ img.ProseMirror-separator {
|
|
|
53439
53452
|
Render the given node as a block.
|
|
53440
53453
|
*/
|
|
53441
53454
|
render(node, parent, index) {
|
|
53442
|
-
if (
|
|
53443
|
-
|
|
53444
|
-
|
|
53455
|
+
if (this.nodes[node.type.name]) {
|
|
53456
|
+
this.nodes[node.type.name](this, node, parent, index);
|
|
53457
|
+
}
|
|
53458
|
+
else {
|
|
53459
|
+
if (this.options.strict !== false) {
|
|
53460
|
+
throw new Error("Token type `" + node.type.name + "` not supported by Markdown renderer");
|
|
53461
|
+
}
|
|
53462
|
+
else if (!node.type.isLeaf) {
|
|
53463
|
+
if (node.type.inlineContent)
|
|
53464
|
+
this.renderInline(node);
|
|
53465
|
+
else
|
|
53466
|
+
this.renderContent(node);
|
|
53467
|
+
if (node.isBlock)
|
|
53468
|
+
this.closeBlock(node);
|
|
53469
|
+
}
|
|
53470
|
+
}
|
|
53445
53471
|
}
|
|
53446
53472
|
/**
|
|
53447
53473
|
Render the contents of `parent` as block nodes.
|
|
@@ -53472,7 +53498,7 @@ img.ProseMirror-separator {
|
|
|
53472
53498
|
// If whitespace has to be expelled from the node, adjust
|
|
53473
53499
|
// leading and trailing accordingly.
|
|
53474
53500
|
if (node && node.isText && marks.some(mark => {
|
|
53475
|
-
let info = this.
|
|
53501
|
+
let info = this.getMark(mark.type.name);
|
|
53476
53502
|
return info && info.expelEnclosingWhitespace && !mark.isInSet(active);
|
|
53477
53503
|
})) {
|
|
53478
53504
|
let [_, lead, rest] = /^(\s*)(.*)$/m.exec(node.text);
|
|
@@ -53484,7 +53510,7 @@ img.ProseMirror-separator {
|
|
|
53484
53510
|
}
|
|
53485
53511
|
}
|
|
53486
53512
|
if (node && node.isText && marks.some(mark => {
|
|
53487
|
-
let info = this.
|
|
53513
|
+
let info = this.getMark(mark.type.name);
|
|
53488
53514
|
return info && info.expelEnclosingWhitespace &&
|
|
53489
53515
|
(index == parent.childCount - 1 || !mark.isInSet(parent.child(index + 1).marks));
|
|
53490
53516
|
})) {
|
|
@@ -53497,7 +53523,7 @@ img.ProseMirror-separator {
|
|
|
53497
53523
|
}
|
|
53498
53524
|
}
|
|
53499
53525
|
let inner = marks.length ? marks[marks.length - 1] : null;
|
|
53500
|
-
let noEsc = inner && this.
|
|
53526
|
+
let noEsc = inner && this.getMark(inner.type.name).escape === false;
|
|
53501
53527
|
let len = marks.length - (noEsc ? 1 : 0);
|
|
53502
53528
|
// Try to reorder 'mixable' marks, such as em and strong, which
|
|
53503
53529
|
// in Markdown may be opened and closed in different order, so
|
|
@@ -53505,11 +53531,11 @@ img.ProseMirror-separator {
|
|
|
53505
53531
|
// active.
|
|
53506
53532
|
outer: for (let i = 0; i < len; i++) {
|
|
53507
53533
|
let mark = marks[i];
|
|
53508
|
-
if (!this.
|
|
53534
|
+
if (!this.getMark(mark.type.name).mixable)
|
|
53509
53535
|
break;
|
|
53510
53536
|
for (let j = 0; j < active.length; j++) {
|
|
53511
53537
|
let other = active[j];
|
|
53512
|
-
if (!this.
|
|
53538
|
+
if (!this.getMark(other.type.name).mixable)
|
|
53513
53539
|
break;
|
|
53514
53540
|
if (mark.eq(other)) {
|
|
53515
53541
|
if (i > j)
|
|
@@ -53615,7 +53641,7 @@ img.ProseMirror-separator {
|
|
|
53615
53641
|
Get the markdown string for a given opening or closing mark.
|
|
53616
53642
|
*/
|
|
53617
53643
|
markString(mark, open, parent, index) {
|
|
53618
|
-
let info = this.
|
|
53644
|
+
let info = this.getMark(mark.type.name);
|
|
53619
53645
|
let value = open ? info.open : info.close;
|
|
53620
53646
|
return typeof value == "string" ? value : value(this, mark, parent, index);
|
|
53621
53647
|
}
|
|
@@ -76724,7 +76750,7 @@ img.ProseMirror-separator {
|
|
|
76724
76750
|
/**
|
|
76725
76751
|
* Prerendering prepares render-ready dies data to be used by the rendering module
|
|
76726
76752
|
*/
|
|
76727
|
-
|
|
76753
|
+
class Prerendering {
|
|
76728
76754
|
get labelsFontSize() {
|
|
76729
76755
|
return this._labelsFontSize;
|
|
76730
76756
|
}
|
|
@@ -76831,12 +76857,12 @@ img.ProseMirror-separator {
|
|
|
76831
76857
|
rgbColor = new ColorRGBA64(rgbColor.r, rgbColor.g, rgbColor.b, this.calculateOpacity(dieTags, highlightedTags));
|
|
76832
76858
|
return rgbColor.toStringWebRGBA();
|
|
76833
76859
|
}
|
|
76834
|
-
}
|
|
76860
|
+
}
|
|
76835
76861
|
|
|
76836
76862
|
/**
|
|
76837
76863
|
* Data Manager uses Computations and Prerendering modules in order and exposes the results
|
|
76838
76864
|
*/
|
|
76839
|
-
|
|
76865
|
+
class DataManager {
|
|
76840
76866
|
get containerDimensions() {
|
|
76841
76867
|
return this.computations.containerDimensions;
|
|
76842
76868
|
}
|
|
@@ -76873,7 +76899,7 @@ img.ProseMirror-separator {
|
|
|
76873
76899
|
constructor(wafermap) {
|
|
76874
76900
|
this.wafermap = wafermap;
|
|
76875
76901
|
this.computations = new Computations$1(wafermap);
|
|
76876
|
-
this.prerendering = new Prerendering
|
|
76902
|
+
this.prerendering = new Prerendering(wafermap);
|
|
76877
76903
|
}
|
|
76878
76904
|
updateContainerDimensions() {
|
|
76879
76905
|
this.computations.updateContainerDimensions();
|
|
@@ -76897,258 +76923,6 @@ img.ProseMirror-separator {
|
|
|
76897
76923
|
updateDataMap() {
|
|
76898
76924
|
this.dataMap = new Map(this.wafermap.dies.map(die => [`${die.x}_${die.y}`, die]));
|
|
76899
76925
|
}
|
|
76900
|
-
};
|
|
76901
|
-
|
|
76902
|
-
/**
|
|
76903
|
-
* Computations calculates and stores different measures which are used in the Wafermap
|
|
76904
|
-
*/
|
|
76905
|
-
class Computations {
|
|
76906
|
-
get containerDimensions() {
|
|
76907
|
-
return this._containerDimensions;
|
|
76908
|
-
}
|
|
76909
|
-
get dieDimensions() {
|
|
76910
|
-
return this._dieDimensions;
|
|
76911
|
-
}
|
|
76912
|
-
get margin() {
|
|
76913
|
-
return this._margin;
|
|
76914
|
-
}
|
|
76915
|
-
get horizontalScale() {
|
|
76916
|
-
return this._horizontalScale;
|
|
76917
|
-
}
|
|
76918
|
-
get verticalScale() {
|
|
76919
|
-
return this._verticalScale;
|
|
76920
|
-
}
|
|
76921
|
-
constructor(wafermap) {
|
|
76922
|
-
this.wafermap = wafermap;
|
|
76923
|
-
this.defaultPadding = 0;
|
|
76924
|
-
this.baseMarginPercentage = 0.04;
|
|
76925
|
-
}
|
|
76926
|
-
update() {
|
|
76927
|
-
const canvasDimensions = {
|
|
76928
|
-
width: this.wafermap.canvasWidth,
|
|
76929
|
-
height: this.wafermap.canvasHeight
|
|
76930
|
-
};
|
|
76931
|
-
const canvasDiameter = Math.min(canvasDimensions.width, canvasDimensions.height);
|
|
76932
|
-
const canvasMargin = {
|
|
76933
|
-
top: (canvasDimensions.height - canvasDiameter) / 2,
|
|
76934
|
-
right: (canvasDimensions.width - canvasDiameter) / 2,
|
|
76935
|
-
bottom: (canvasDimensions.height - canvasDiameter) / 2,
|
|
76936
|
-
left: (canvasDimensions.width - canvasDiameter) / 2
|
|
76937
|
-
};
|
|
76938
|
-
const baseMargin = {
|
|
76939
|
-
top: canvasDiameter * this.baseMarginPercentage,
|
|
76940
|
-
right: canvasDiameter * this.baseMarginPercentage,
|
|
76941
|
-
bottom: canvasDiameter * this.baseMarginPercentage,
|
|
76942
|
-
left: canvasDiameter * this.baseMarginPercentage
|
|
76943
|
-
};
|
|
76944
|
-
this._margin = this.calculateMarginAddition(baseMargin, canvasMargin);
|
|
76945
|
-
this._containerDimensions = this.calculateContainerDimensions(canvasDimensions, this._margin);
|
|
76946
|
-
const containerDiameter = Math.min(this._containerDimensions.width, this._containerDimensions.height);
|
|
76947
|
-
const gridDimensions = this.gridDimensionsValidAndDefined()
|
|
76948
|
-
? this.calculateGridDimensionsFromBoundingBox()
|
|
76949
|
-
: this.calculateGridDimensionsFromDies();
|
|
76950
|
-
// this scale is used for positioning the dies on the canvas
|
|
76951
|
-
const originLocation = this.wafermap.originLocation;
|
|
76952
|
-
this._horizontalScale = this.createHorizontalScale(originLocation, gridDimensions, containerDiameter);
|
|
76953
|
-
// this scale is used for positioning the dies on the canvas
|
|
76954
|
-
this._verticalScale = this.createVerticalScale(originLocation, gridDimensions, containerDiameter);
|
|
76955
|
-
this._dieDimensions = {
|
|
76956
|
-
width: Math.abs(this._horizontalScale(0) - this._horizontalScale(1)),
|
|
76957
|
-
height: Math.abs(this._verticalScale(0) - this._verticalScale(1))
|
|
76958
|
-
};
|
|
76959
|
-
}
|
|
76960
|
-
gridDimensionsValidAndDefined() {
|
|
76961
|
-
return (!this.wafermap.validity.invalidGridDimensions
|
|
76962
|
-
&& typeof this.wafermap.gridMinX === 'number'
|
|
76963
|
-
&& typeof this.wafermap.gridMinY === 'number'
|
|
76964
|
-
&& typeof this.wafermap.gridMaxX === 'number'
|
|
76965
|
-
&& typeof this.wafermap.gridMinX === 'number');
|
|
76966
|
-
}
|
|
76967
|
-
calculateGridDimensionsFromBoundingBox() {
|
|
76968
|
-
const gridDimensions = { origin: { x: 0, y: 0 }, rows: 0, cols: 0 };
|
|
76969
|
-
if (typeof this.wafermap.gridMaxY === 'number'
|
|
76970
|
-
&& typeof this.wafermap.gridMinY === 'number'
|
|
76971
|
-
&& typeof this.wafermap.gridMaxX === 'number'
|
|
76972
|
-
&& typeof this.wafermap.gridMinX === 'number') {
|
|
76973
|
-
gridDimensions.origin.x = this.wafermap.gridMinX;
|
|
76974
|
-
gridDimensions.origin.y = this.wafermap.gridMinY;
|
|
76975
|
-
gridDimensions.rows = this.wafermap.gridMaxY - this.wafermap.gridMinY + 1;
|
|
76976
|
-
gridDimensions.cols = this.wafermap.gridMaxX - this.wafermap.gridMinX + 1;
|
|
76977
|
-
}
|
|
76978
|
-
return gridDimensions;
|
|
76979
|
-
}
|
|
76980
|
-
calculateGridDimensionsFromDies() {
|
|
76981
|
-
if (this.wafermap.diesTable === undefined) {
|
|
76982
|
-
return { origin: { x: 0, y: 0 }, rows: 0, cols: 0 };
|
|
76983
|
-
}
|
|
76984
|
-
const colIndex = this.wafermap.diesTable
|
|
76985
|
-
.getChild('colIndex')
|
|
76986
|
-
.toArray();
|
|
76987
|
-
const rowIndex = this.wafermap.diesTable
|
|
76988
|
-
.getChild('rowIndex')
|
|
76989
|
-
.toArray();
|
|
76990
|
-
const minPoint = { x: colIndex[0], y: rowIndex[0] };
|
|
76991
|
-
const maxPoint = { x: colIndex[0], y: rowIndex[0] };
|
|
76992
|
-
// will replace iterating with arquero after fixing issues: https://github.com/uwdata/arquero/pull/346
|
|
76993
|
-
for (let i = 0; i < colIndex.length; i++) {
|
|
76994
|
-
if (colIndex[i] < minPoint.x) {
|
|
76995
|
-
minPoint.x = colIndex[i];
|
|
76996
|
-
}
|
|
76997
|
-
if (colIndex[i] > maxPoint.x) {
|
|
76998
|
-
maxPoint.x = colIndex[i];
|
|
76999
|
-
}
|
|
77000
|
-
if (rowIndex[i] < minPoint.y) {
|
|
77001
|
-
minPoint.y = rowIndex[i];
|
|
77002
|
-
}
|
|
77003
|
-
if (rowIndex[i] > maxPoint.y) {
|
|
77004
|
-
maxPoint.y = rowIndex[i];
|
|
77005
|
-
}
|
|
77006
|
-
}
|
|
77007
|
-
return {
|
|
77008
|
-
origin: minPoint,
|
|
77009
|
-
rows: maxPoint.y - minPoint.y + 1,
|
|
77010
|
-
cols: maxPoint.x - minPoint.x + 1
|
|
77011
|
-
};
|
|
77012
|
-
}
|
|
77013
|
-
calculateContainerDimensions(canvasDimensions, margin) {
|
|
77014
|
-
return {
|
|
77015
|
-
width: canvasDimensions.width - margin.left - margin.right,
|
|
77016
|
-
height: canvasDimensions.height - margin.top - margin.bottom
|
|
77017
|
-
};
|
|
77018
|
-
}
|
|
77019
|
-
createHorizontalScale(originLocation, grid, containerWidth) {
|
|
77020
|
-
const scale = linear();
|
|
77021
|
-
if (originLocation === WaferMapOriginLocation.bottomLeft
|
|
77022
|
-
|| originLocation === WaferMapOriginLocation.topLeft) {
|
|
77023
|
-
return scale
|
|
77024
|
-
.domain([grid.origin.x, grid.origin.x + grid.cols])
|
|
77025
|
-
.range([0, containerWidth]);
|
|
77026
|
-
}
|
|
77027
|
-
return scale
|
|
77028
|
-
.domain([grid.origin.x - 1, grid.origin.x + grid.cols - 1])
|
|
77029
|
-
.range([containerWidth, 0]);
|
|
77030
|
-
}
|
|
77031
|
-
createVerticalScale(originLocation, grid, containerHeight) {
|
|
77032
|
-
const scale = linear();
|
|
77033
|
-
// html canvas has top-left origin https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes#the_grid
|
|
77034
|
-
// we need to flip the vertical scale
|
|
77035
|
-
if (originLocation === WaferMapOriginLocation.bottomLeft
|
|
77036
|
-
|| originLocation === WaferMapOriginLocation.bottomRight) {
|
|
77037
|
-
return scale
|
|
77038
|
-
.domain([grid.origin.y - 1, grid.origin.y + grid.rows - 1])
|
|
77039
|
-
.range([containerHeight, 0]);
|
|
77040
|
-
}
|
|
77041
|
-
return scale
|
|
77042
|
-
.domain([grid.origin.y, grid.origin.y + grid.rows])
|
|
77043
|
-
.range([0, containerHeight]);
|
|
77044
|
-
}
|
|
77045
|
-
calculateMarginAddition(baseMargin, addedMargin) {
|
|
77046
|
-
return {
|
|
77047
|
-
top: baseMargin.top + addedMargin.top,
|
|
77048
|
-
right: baseMargin.right + addedMargin.right,
|
|
77049
|
-
bottom: baseMargin.bottom + addedMargin.bottom,
|
|
77050
|
-
left: baseMargin.left + addedMargin.left
|
|
77051
|
-
};
|
|
77052
|
-
}
|
|
77053
|
-
}
|
|
77054
|
-
|
|
77055
|
-
/**
|
|
77056
|
-
* Prerendering prepares render-ready dies data to be used by the rendering module
|
|
77057
|
-
*/
|
|
77058
|
-
class Prerendering {
|
|
77059
|
-
get labelsFontSize() {
|
|
77060
|
-
return this._labelsFontSize;
|
|
77061
|
-
}
|
|
77062
|
-
get colorScale() {
|
|
77063
|
-
return this._colorScale;
|
|
77064
|
-
}
|
|
77065
|
-
constructor(wafermap) {
|
|
77066
|
-
this.wafermap = wafermap;
|
|
77067
|
-
this.fontSizeFactor = 0.8;
|
|
77068
|
-
this.colorScaleResolution = 10;
|
|
77069
|
-
}
|
|
77070
|
-
update() {
|
|
77071
|
-
this._labelsFontSize = this.calculateLabelsFontSize(this.wafermap.experimentalDataManager.dieDimensions, this.wafermap.maxCharacters);
|
|
77072
|
-
this._colorScale = this.calculateColorScale();
|
|
77073
|
-
}
|
|
77074
|
-
calculateColorScale() {
|
|
77075
|
-
if (this.wafermap.colorScaleMode === WaferMapColorScaleMode.linear) {
|
|
77076
|
-
const values = this.wafermap.colorScale.values.map(item => +item);
|
|
77077
|
-
const d3ColorScale = linear()
|
|
77078
|
-
.domain(values)
|
|
77079
|
-
.range(this.wafermap.colorScale.colors);
|
|
77080
|
-
let min = values[0];
|
|
77081
|
-
let max = values[0];
|
|
77082
|
-
values.forEach(value => {
|
|
77083
|
-
if (value < min) {
|
|
77084
|
-
min = value;
|
|
77085
|
-
}
|
|
77086
|
-
if (value > max) {
|
|
77087
|
-
max = value;
|
|
77088
|
-
}
|
|
77089
|
-
});
|
|
77090
|
-
// the linear color scale will not be infinite but will be limited by the color scale resolution
|
|
77091
|
-
const valueSamples = ticks(min, max, values.length * this.colorScaleResolution);
|
|
77092
|
-
return valueSamples.map(value => {
|
|
77093
|
-
return {
|
|
77094
|
-
color: d3ColorScale(value),
|
|
77095
|
-
value
|
|
77096
|
-
};
|
|
77097
|
-
});
|
|
77098
|
-
}
|
|
77099
|
-
// ordinal color categories have to be sorted by value
|
|
77100
|
-
return this.wafermap.colorScale.colors
|
|
77101
|
-
.map((color, index) => {
|
|
77102
|
-
return {
|
|
77103
|
-
color,
|
|
77104
|
-
value: +this.wafermap.colorScale.values[index]
|
|
77105
|
-
};
|
|
77106
|
-
})
|
|
77107
|
-
.sort((a, b) => a.value - b.value);
|
|
77108
|
-
}
|
|
77109
|
-
calculateLabelsFontSize(dieDimensions, maxCharacters) {
|
|
77110
|
-
return Math.min(dieDimensions.height, (dieDimensions.width / (Math.max(2, maxCharacters) * 0.5))
|
|
77111
|
-
* this.fontSizeFactor);
|
|
77112
|
-
}
|
|
77113
|
-
}
|
|
77114
|
-
|
|
77115
|
-
/**
|
|
77116
|
-
* Data Manager uses Computations and Prerendering modules in order and exposes the results
|
|
77117
|
-
*/
|
|
77118
|
-
class DataManager {
|
|
77119
|
-
get containerDimensions() {
|
|
77120
|
-
return this.computations.containerDimensions;
|
|
77121
|
-
}
|
|
77122
|
-
get dieDimensions() {
|
|
77123
|
-
return this.computations.dieDimensions;
|
|
77124
|
-
}
|
|
77125
|
-
get margin() {
|
|
77126
|
-
return this.computations.margin;
|
|
77127
|
-
}
|
|
77128
|
-
get horizontalScale() {
|
|
77129
|
-
return this.computations.horizontalScale;
|
|
77130
|
-
}
|
|
77131
|
-
get verticalScale() {
|
|
77132
|
-
return this.computations.verticalScale;
|
|
77133
|
-
}
|
|
77134
|
-
get labelsFontSize() {
|
|
77135
|
-
return this.prerendering.labelsFontSize;
|
|
77136
|
-
}
|
|
77137
|
-
get colorScale() {
|
|
77138
|
-
return this.prerendering.colorScale;
|
|
77139
|
-
}
|
|
77140
|
-
constructor(wafermap) {
|
|
77141
|
-
this.wafermap = wafermap;
|
|
77142
|
-
this.computations = new Computations(wafermap);
|
|
77143
|
-
this.prerendering = new Prerendering(wafermap);
|
|
77144
|
-
}
|
|
77145
|
-
updateComputations() {
|
|
77146
|
-
this.computations.update();
|
|
77147
|
-
this.prerendering.update();
|
|
77148
|
-
}
|
|
77149
|
-
updatePrerendering() {
|
|
77150
|
-
this.prerendering.update();
|
|
77151
|
-
}
|
|
77152
76926
|
}
|
|
77153
76927
|
|
|
77154
76928
|
/**
|
|
@@ -77307,8 +77081,7 @@ img.ProseMirror-separator {
|
|
|
77307
77081
|
this.updateQueued = false;
|
|
77308
77082
|
}
|
|
77309
77083
|
get requiresEventsUpdate() {
|
|
77310
|
-
return (this.isTracked('
|
|
77311
|
-
|| this.isTracked('canvasWidth')
|
|
77084
|
+
return (this.isTracked('canvasWidth')
|
|
77312
77085
|
|| this.isTracked('canvasHeight')
|
|
77313
77086
|
|| this.isTracked('originLocation')
|
|
77314
77087
|
|| this.isTracked('gridMinX')
|
|
@@ -77317,15 +77090,35 @@ img.ProseMirror-separator {
|
|
|
77317
77090
|
|| this.isTracked('gridMaxY')
|
|
77318
77091
|
|| this.isTracked('dies')
|
|
77319
77092
|
|| this.isTracked('maxCharacters')
|
|
77093
|
+
|| this.isTracked('highlightedTags')
|
|
77320
77094
|
|| this.isTracked('colorScale')
|
|
77321
77095
|
|| this.isTracked('colorScaleMode')
|
|
77322
77096
|
|| this.isTracked('dieLabelsHidden')
|
|
77323
77097
|
|| this.isTracked('dieLabelsSuffix')
|
|
77324
77098
|
|| this.isTracked('transform'));
|
|
77325
77099
|
}
|
|
77100
|
+
get requiresWorkerWaferSetup() {
|
|
77101
|
+
return (this.isTracked('canvasWidth')
|
|
77102
|
+
|| this.isTracked('canvasHeight')
|
|
77103
|
+
|| this.isTracked('originLocation')
|
|
77104
|
+
|| this.isTracked('gridMinX')
|
|
77105
|
+
|| this.isTracked('gridMaxX')
|
|
77106
|
+
|| this.isTracked('gridMinY')
|
|
77107
|
+
|| this.isTracked('gridMaxY')
|
|
77108
|
+
|| this.isTracked('dies')
|
|
77109
|
+
|| this.isTracked('maxCharacters')
|
|
77110
|
+
|| this.isTracked('highlightedTags')
|
|
77111
|
+
|| this.isTracked('colorScale')
|
|
77112
|
+
|| this.isTracked('colorScaleMode')
|
|
77113
|
+
|| this.isTracked('dieLabelsHidden')
|
|
77114
|
+
|| this.isTracked('dieLabelsSuffix'));
|
|
77115
|
+
}
|
|
77326
77116
|
get requiresContainerDimensionsUpdate() {
|
|
77327
77117
|
return this.isTracked('canvasWidth') || this.isTracked('canvasHeight');
|
|
77328
77118
|
}
|
|
77119
|
+
get requiresComponentResizeUpdate() {
|
|
77120
|
+
return this.isTracked('canvasWidth') || this.isTracked('canvasHeight');
|
|
77121
|
+
}
|
|
77329
77122
|
get requiresScalesUpdate() {
|
|
77330
77123
|
return (this.isTracked('originLocation')
|
|
77331
77124
|
|| this.isTracked('gridMinX')
|
|
@@ -77334,6 +77127,14 @@ img.ProseMirror-separator {
|
|
|
77334
77127
|
|| this.isTracked('gridMaxY')
|
|
77335
77128
|
|| this.isTracked('dies'));
|
|
77336
77129
|
}
|
|
77130
|
+
get requiresInputDataUpdate() {
|
|
77131
|
+
return (this.isTracked('originLocation')
|
|
77132
|
+
|| this.isTracked('gridMinX')
|
|
77133
|
+
|| this.isTracked('gridMaxX')
|
|
77134
|
+
|| this.isTracked('gridMinY')
|
|
77135
|
+
|| this.isTracked('gridMaxY')
|
|
77136
|
+
|| this.isTracked('dies'));
|
|
77137
|
+
}
|
|
77337
77138
|
get requiresLabelsFontSizeUpdate() {
|
|
77338
77139
|
return this.isTracked('maxCharacters');
|
|
77339
77140
|
}
|
|
@@ -77344,6 +77145,14 @@ img.ProseMirror-separator {
|
|
|
77344
77145
|
|| this.isTracked('dieLabelsHidden')
|
|
77345
77146
|
|| this.isTracked('dieLabelsSuffix'));
|
|
77346
77147
|
}
|
|
77148
|
+
get requiresColorAndTextUpdate() {
|
|
77149
|
+
return (this.isTracked('maxCharacters')
|
|
77150
|
+
|| this.isTracked('highlightedTags')
|
|
77151
|
+
|| this.isTracked('colorScale')
|
|
77152
|
+
|| this.isTracked('colorScaleMode')
|
|
77153
|
+
|| this.isTracked('dieLabelsHidden')
|
|
77154
|
+
|| this.isTracked('dieLabelsSuffix'));
|
|
77155
|
+
}
|
|
77347
77156
|
get requiresDrawnWaferUpdate() {
|
|
77348
77157
|
return this.isTracked('transform');
|
|
77349
77158
|
}
|
|
@@ -78374,7 +78183,7 @@ img.ProseMirror-separator {
|
|
|
78374
78183
|
}
|
|
78375
78184
|
|
|
78376
78185
|
// eslint-disable-next-line no-template-curly-in-string
|
|
78377
|
-
const workerCode = "var MatrixRenderer = (function (exports) {\n 'use strict';\n\n /**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n const proxyMarker = Symbol(\"Comlink.proxy\");\n const createEndpoint = Symbol(\"Comlink.endpoint\");\n const releaseProxy = Symbol(\"Comlink.releaseProxy\");\n const finalizer = Symbol(\"Comlink.finalizer\");\n const throwMarker = Symbol(\"Comlink.thrown\");\n const isObject = (val) => (typeof val === \"object\" && val !== null) || typeof val === \"function\";\n /**\n * Internal transfer handle to handle objects marked to proxy.\n */\n const proxyTransferHandler = {\n canHandle: (val) => isObject(val) && val[proxyMarker],\n serialize(obj) {\n const { port1, port2 } = new MessageChannel();\n expose(obj, port1);\n return [port2, [port2]];\n },\n deserialize(port) {\n port.start();\n return wrap(port);\n },\n };\n /**\n * Internal transfer handler to handle thrown exceptions.\n */\n const throwTransferHandler = {\n canHandle: (value) => isObject(value) && throwMarker in value,\n serialize({ value }) {\n let serialized;\n if (value instanceof Error) {\n serialized = {\n isError: true,\n value: {\n message: value.message,\n name: value.name,\n stack: value.stack,\n },\n };\n }\n else {\n serialized = { isError: false, value };\n }\n return [serialized, []];\n },\n deserialize(serialized) {\n if (serialized.isError) {\n throw Object.assign(new Error(serialized.value.message), serialized.value);\n }\n throw serialized.value;\n },\n };\n /**\n * Allows customizing the serialization of certain values.\n */\n const transferHandlers = new Map([\n [\"proxy\", proxyTransferHandler],\n [\"throw\", throwTransferHandler],\n ]);\n function isAllowedOrigin(allowedOrigins, origin) {\n for (const allowedOrigin of allowedOrigins) {\n if (origin === allowedOrigin || allowedOrigin === \"*\") {\n return true;\n }\n if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {\n return true;\n }\n }\n return false;\n }\n function expose(obj, ep = globalThis, allowedOrigins = [\"*\"]) {\n ep.addEventListener(\"message\", function callback(ev) {\n if (!ev || !ev.data) {\n return;\n }\n if (!isAllowedOrigin(allowedOrigins, ev.origin)) {\n console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);\n return;\n }\n const { id, type, path } = Object.assign({ path: [] }, ev.data);\n const argumentList = (ev.data.argumentList || []).map(fromWireValue);\n let returnValue;\n try {\n const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);\n const rawValue = path.reduce((obj, prop) => obj[prop], obj);\n switch (type) {\n case \"GET\" /* MessageType.GET */:\n {\n returnValue = rawValue;\n }\n break;\n case \"SET\" /* MessageType.SET */:\n {\n parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);\n returnValue = true;\n }\n break;\n case \"APPLY\" /* MessageType.APPLY */:\n {\n returnValue = rawValue.apply(parent, argumentList);\n }\n break;\n case \"CONSTRUCT\" /* MessageType.CONSTRUCT */:\n {\n const value = new rawValue(...argumentList);\n returnValue = proxy(value);\n }\n break;\n case \"ENDPOINT\" /* MessageType.ENDPOINT */:\n {\n const { port1, port2 } = new MessageChannel();\n expose(obj, port2);\n returnValue = transfer(port1, [port1]);\n }\n break;\n case \"RELEASE\" /* MessageType.RELEASE */:\n {\n returnValue = undefined;\n }\n break;\n default:\n return;\n }\n }\n catch (value) {\n returnValue = { value, [throwMarker]: 0 };\n }\n Promise.resolve(returnValue)\n .catch((value) => {\n return { value, [throwMarker]: 0 };\n })\n .then((returnValue) => {\n const [wireValue, transferables] = toWireValue(returnValue);\n ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);\n if (type === \"RELEASE\" /* MessageType.RELEASE */) {\n // detach and deactive after sending release response above.\n ep.removeEventListener(\"message\", callback);\n closeEndPoint(ep);\n if (finalizer in obj && typeof obj[finalizer] === \"function\") {\n obj[finalizer]();\n }\n }\n })\n .catch((error) => {\n // Send Serialization Error To Caller\n const [wireValue, transferables] = toWireValue({\n value: new TypeError(\"Unserializable return value\"),\n [throwMarker]: 0,\n });\n ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);\n });\n });\n if (ep.start) {\n ep.start();\n }\n }\n function isMessagePort(endpoint) {\n return endpoint.constructor.name === \"MessagePort\";\n }\n function closeEndPoint(endpoint) {\n if (isMessagePort(endpoint))\n endpoint.close();\n }\n function wrap(ep, target) {\n return createProxy(ep, [], target);\n }\n function throwIfProxyReleased(isReleased) {\n if (isReleased) {\n throw new Error(\"Proxy has been released and is not useable\");\n }\n }\n function releaseEndpoint(ep) {\n return requestResponseMessage(ep, {\n type: \"RELEASE\" /* MessageType.RELEASE */,\n }).then(() => {\n closeEndPoint(ep);\n });\n }\n const proxyCounter = new WeakMap();\n const proxyFinalizers = \"FinalizationRegistry\" in globalThis &&\n new FinalizationRegistry((ep) => {\n const newCount = (proxyCounter.get(ep) || 0) - 1;\n proxyCounter.set(ep, newCount);\n if (newCount === 0) {\n releaseEndpoint(ep);\n }\n });\n function registerProxy(proxy, ep) {\n const newCount = (proxyCounter.get(ep) || 0) + 1;\n proxyCounter.set(ep, newCount);\n if (proxyFinalizers) {\n proxyFinalizers.register(proxy, ep, proxy);\n }\n }\n function unregisterProxy(proxy) {\n if (proxyFinalizers) {\n proxyFinalizers.unregister(proxy);\n }\n }\n function createProxy(ep, path = [], target = function () { }) {\n let isProxyReleased = false;\n const proxy = new Proxy(target, {\n get(_target, prop) {\n throwIfProxyReleased(isProxyReleased);\n if (prop === releaseProxy) {\n return () => {\n unregisterProxy(proxy);\n releaseEndpoint(ep);\n isProxyReleased = true;\n };\n }\n if (prop === \"then\") {\n if (path.length === 0) {\n return { then: () => proxy };\n }\n const r = requestResponseMessage(ep, {\n type: \"GET\" /* MessageType.GET */,\n path: path.map((p) => p.toString()),\n }).then(fromWireValue);\n return r.then.bind(r);\n }\n return createProxy(ep, [...path, prop]);\n },\n set(_target, prop, rawValue) {\n throwIfProxyReleased(isProxyReleased);\n // FIXME: ES6 Proxy Handler `set` methods are supposed to return a\n // boolean. To show good will, we return true asynchronously ¯\\_(ツ)_/¯\n const [value, transferables] = toWireValue(rawValue);\n return requestResponseMessage(ep, {\n type: \"SET\" /* MessageType.SET */,\n path: [...path, prop].map((p) => p.toString()),\n value,\n }, transferables).then(fromWireValue);\n },\n apply(_target, _thisArg, rawArgumentList) {\n throwIfProxyReleased(isProxyReleased);\n const last = path[path.length - 1];\n if (last === createEndpoint) {\n return requestResponseMessage(ep, {\n type: \"ENDPOINT\" /* MessageType.ENDPOINT */,\n }).then(fromWireValue);\n }\n // We just pretend that `bind()` didn’t happen.\n if (last === \"bind\") {\n return createProxy(ep, path.slice(0, -1));\n }\n const [argumentList, transferables] = processArguments(rawArgumentList);\n return requestResponseMessage(ep, {\n type: \"APPLY\" /* MessageType.APPLY */,\n path: path.map((p) => p.toString()),\n argumentList,\n }, transferables).then(fromWireValue);\n },\n construct(_target, rawArgumentList) {\n throwIfProxyReleased(isProxyReleased);\n const [argumentList, transferables] = processArguments(rawArgumentList);\n return requestResponseMessage(ep, {\n type: \"CONSTRUCT\" /* MessageType.CONSTRUCT */,\n path: path.map((p) => p.toString()),\n argumentList,\n }, transferables).then(fromWireValue);\n },\n });\n registerProxy(proxy, ep);\n return proxy;\n }\n function myFlat(arr) {\n return Array.prototype.concat.apply([], arr);\n }\n function processArguments(argumentList) {\n const processed = argumentList.map(toWireValue);\n return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];\n }\n const transferCache = new WeakMap();\n function transfer(obj, transfers) {\n transferCache.set(obj, transfers);\n return obj;\n }\n function proxy(obj) {\n return Object.assign(obj, { [proxyMarker]: true });\n }\n function toWireValue(value) {\n for (const [name, handler] of transferHandlers) {\n if (handler.canHandle(value)) {\n const [serializedValue, transferables] = handler.serialize(value);\n return [\n {\n type: \"HANDLER\" /* WireValueType.HANDLER */,\n name,\n value: serializedValue,\n },\n transferables,\n ];\n }\n }\n return [\n {\n type: \"RAW\" /* WireValueType.RAW */,\n value,\n },\n transferCache.get(value) || [],\n ];\n }\n function fromWireValue(value) {\n switch (value.type) {\n case \"HANDLER\" /* WireValueType.HANDLER */:\n return transferHandlers.get(value.name).deserialize(value.value);\n case \"RAW\" /* WireValueType.RAW */:\n return value.value;\n }\n }\n function requestResponseMessage(ep, msg, transfers) {\n return new Promise((resolve) => {\n const id = generateUUID();\n ep.addEventListener(\"message\", function l(ev) {\n if (!ev.data || !ev.data.id || ev.data.id !== id) {\n return;\n }\n ep.removeEventListener(\"message\", l);\n resolve(ev.data);\n });\n if (ep.start) {\n ep.start();\n }\n ep.postMessage(Object.assign({ id }, msg), transfers);\n });\n }\n function generateUUID() {\n return new Array(4)\n .fill(0)\n .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))\n .join(\"-\");\n }\n\n /**\n * MatrixRenderer class is meant to be used within a Web Worker context,\n * using Comlink to facilitate communication between the main thread and the worker.\n * The MatrixRenderer class manages a matrix of dies, once an instance of MatrixRenderer is created,\n * it is exposed to the main thread using Comlink's `expose` method.\n * This setup is used in the wafer-map component to perform heavy computational duties\n */\n class MatrixRenderer {\n constructor() {\n this.columnIndexes = Int32Array.from([]);\n this.rowIndexes = Int32Array.from([]);\n this.values = Float64Array.from([]);\n this.scaledColumnIndex = Float64Array.from([]);\n this.scaledRowIndex = Float64Array.from([]);\n this.columnIndexPositions = Int32Array.from([]);\n this.scaleX = 1;\n this.scaleY = 1;\n this.baseX = 1;\n this.baseY = 1;\n this.dieDimensions = { width: 1, height: 1 };\n this.transform = { k: 1, x: 0, y: 0 };\n this.smallestMarginPossible = 20;\n this.margin = {\n top: this.smallestMarginPossible,\n right: this.smallestMarginPossible,\n bottom: this.smallestMarginPossible,\n left: this.smallestMarginPossible\n };\n }\n calculateXScaledIndex(columnIndex) {\n return this.scaleX * columnIndex + this.baseX + this.margin.left;\n }\n calculateYScaledIndex(rowIndex) {\n return this.scaleY * rowIndex + this.baseY + this.margin.top;\n }\n setColumnIndexes(columnIndexes) {\n this.columnIndexes = columnIndexes;\n if (columnIndexes.length === 0 || this.columnIndexes[0] === undefined) {\n return;\n }\n const scaledColumnIndex = [\n this.calculateXScaledIndex(this.columnIndexes[0])\n ];\n const columnPositions = [0];\n let prev = this.columnIndexes[0];\n for (let i = 1; i < this.columnIndexes.length; i++) {\n const xIndex = this.columnIndexes[i];\n if (xIndex && xIndex !== prev) {\n const scaledX = this.calculateXScaledIndex(this.columnIndexes[i]);\n scaledColumnIndex.push(scaledX);\n columnPositions.push(i);\n prev = xIndex;\n }\n }\n this.scaledColumnIndex = Float64Array.from(scaledColumnIndex);\n this.columnIndexPositions = Int32Array.from(columnPositions);\n }\n setRowIndexes(rowIndexesBuffer) {\n this.rowIndexes = rowIndexesBuffer;\n this.scaledRowIndex = new Float64Array(this.rowIndexes.length);\n for (let i = 0; i < this.rowIndexes.length; i++) {\n this.scaledRowIndex[i] = this.calculateYScaledIndex(this.rowIndexes[i]);\n }\n }\n setMargin(margin) {\n this.margin = margin;\n }\n setCanvasCorners(topLeft, bottomRight) {\n this.topLeftCanvasCorner = topLeft;\n this.bottomRightCanvasCorner = bottomRight;\n }\n setDiesDimensions(data) {\n this.dieDimensions = { width: data.width, height: data.height };\n }\n setScaling(scaleX, scaleY) {\n this.scaleX = scaleX;\n this.scaleY = scaleY;\n }\n setBases(baseX, baseY) {\n this.baseX = baseX;\n this.baseY = baseY;\n }\n setTransform(transform) {\n this.transform = transform;\n }\n setCanvas(canvas) {\n this.canvas = canvas;\n this.context = canvas.getContext('2d');\n }\n getMatrix() {\n return {\n columnIndexes: this.columnIndexes,\n rowIndexes: this.rowIndexes,\n values: this.values\n };\n }\n emptyMatrix() {\n this.columnIndexes = Int32Array.from([]);\n this.rowIndexes = Int32Array.from([]);\n this.values = Float64Array.from([]);\n }\n scaleCanvas() {\n this.context.translate(this.transform.x, this.transform.y);\n this.context.scale(this.transform.k, this.transform.k);\n }\n updateMatrix(data) {\n this.columnIndexes = Int32Array.from(data.columnIndexes);\n this.rowIndexes = Int32Array.from(data.rowIndexes);\n this.values = Float64Array.from(data.values);\n }\n setCanvasDimensions(data) {\n this.canvas.width = data.width;\n this.canvas.height = data.height;\n }\n getCanvasDimensions() {\n return {\n width: this.canvas.width,\n height: this.canvas.height\n };\n }\n clearCanvas() {\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n }\n drawWafer() {\n this.context.restore();\n this.context.save();\n this.clearCanvas();\n this.scaleCanvas();\n if (this.topLeftCanvasCorner === undefined\n || this.bottomRightCanvasCorner === undefined) {\n throw new Error('Canvas corners are not set');\n }\n for (let i = 0; i < this.scaledColumnIndex.length; i++) {\n const scaledX = this.scaledColumnIndex[i];\n if (!(scaledX >= this.topLeftCanvasCorner.x\n && scaledX < this.bottomRightCanvasCorner.x)) {\n continue;\n }\n // columnIndexPositions is used to get chunks to determine the start and end index of the column, it looks something like [0, 1, 4, 9, 12]\n // This means that the first column has a start index of 0 and an end index of 1, the second column has a start index of 1 and an end index of 4, and so on\n // scaledRowIndex is used when we reach the end of the columnIndexPositions, when columnIndexPositions is [0, 1, 4, 9, 12], scaledRowIndex is 13\n const columnEndIndex = this.columnIndexPositions[i + 1] !== undefined\n ? this.columnIndexPositions[i + 1]\n : this.scaledRowIndex.length;\n for (let columnStartIndex = this.columnIndexPositions[i]; columnStartIndex < columnEndIndex; columnStartIndex++) {\n const scaledY = this.scaledRowIndex[columnStartIndex];\n if (!(scaledY >= this.topLeftCanvasCorner.y\n && scaledY < this.bottomRightCanvasCorner.y)) {\n continue;\n }\n // Fill style is temporary green for all dies, will be replaced with a color based on the value of the die in a future implementation\n this.context.fillStyle = 'Green';\n this.context.fillRect(scaledX, scaledY, this.dieDimensions.width, this.dieDimensions.height);\n }\n }\n }\n }\n expose(MatrixRenderer);\n\n exports.MatrixRenderer = MatrixRenderer;\n\n return exports;\n\n})({});\n";
|
|
78186
|
+
const workerCode = "var MatrixRenderer = (function (exports) {\n 'use strict';\n\n /**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n const proxyMarker = Symbol(\"Comlink.proxy\");\n const createEndpoint = Symbol(\"Comlink.endpoint\");\n const releaseProxy = Symbol(\"Comlink.releaseProxy\");\n const finalizer = Symbol(\"Comlink.finalizer\");\n const throwMarker = Symbol(\"Comlink.thrown\");\n const isObject = (val) => (typeof val === \"object\" && val !== null) || typeof val === \"function\";\n /**\n * Internal transfer handle to handle objects marked to proxy.\n */\n const proxyTransferHandler = {\n canHandle: (val) => isObject(val) && val[proxyMarker],\n serialize(obj) {\n const { port1, port2 } = new MessageChannel();\n expose(obj, port1);\n return [port2, [port2]];\n },\n deserialize(port) {\n port.start();\n return wrap(port);\n },\n };\n /**\n * Internal transfer handler to handle thrown exceptions.\n */\n const throwTransferHandler = {\n canHandle: (value) => isObject(value) && throwMarker in value,\n serialize({ value }) {\n let serialized;\n if (value instanceof Error) {\n serialized = {\n isError: true,\n value: {\n message: value.message,\n name: value.name,\n stack: value.stack,\n },\n };\n }\n else {\n serialized = { isError: false, value };\n }\n return [serialized, []];\n },\n deserialize(serialized) {\n if (serialized.isError) {\n throw Object.assign(new Error(serialized.value.message), serialized.value);\n }\n throw serialized.value;\n },\n };\n /**\n * Allows customizing the serialization of certain values.\n */\n const transferHandlers = new Map([\n [\"proxy\", proxyTransferHandler],\n [\"throw\", throwTransferHandler],\n ]);\n function isAllowedOrigin(allowedOrigins, origin) {\n for (const allowedOrigin of allowedOrigins) {\n if (origin === allowedOrigin || allowedOrigin === \"*\") {\n return true;\n }\n if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {\n return true;\n }\n }\n return false;\n }\n function expose(obj, ep = globalThis, allowedOrigins = [\"*\"]) {\n ep.addEventListener(\"message\", function callback(ev) {\n if (!ev || !ev.data) {\n return;\n }\n if (!isAllowedOrigin(allowedOrigins, ev.origin)) {\n console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);\n return;\n }\n const { id, type, path } = Object.assign({ path: [] }, ev.data);\n const argumentList = (ev.data.argumentList || []).map(fromWireValue);\n let returnValue;\n try {\n const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);\n const rawValue = path.reduce((obj, prop) => obj[prop], obj);\n switch (type) {\n case \"GET\" /* MessageType.GET */:\n {\n returnValue = rawValue;\n }\n break;\n case \"SET\" /* MessageType.SET */:\n {\n parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);\n returnValue = true;\n }\n break;\n case \"APPLY\" /* MessageType.APPLY */:\n {\n returnValue = rawValue.apply(parent, argumentList);\n }\n break;\n case \"CONSTRUCT\" /* MessageType.CONSTRUCT */:\n {\n const value = new rawValue(...argumentList);\n returnValue = proxy(value);\n }\n break;\n case \"ENDPOINT\" /* MessageType.ENDPOINT */:\n {\n const { port1, port2 } = new MessageChannel();\n expose(obj, port2);\n returnValue = transfer(port1, [port1]);\n }\n break;\n case \"RELEASE\" /* MessageType.RELEASE */:\n {\n returnValue = undefined;\n }\n break;\n default:\n return;\n }\n }\n catch (value) {\n returnValue = { value, [throwMarker]: 0 };\n }\n Promise.resolve(returnValue)\n .catch((value) => {\n return { value, [throwMarker]: 0 };\n })\n .then((returnValue) => {\n const [wireValue, transferables] = toWireValue(returnValue);\n ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);\n if (type === \"RELEASE\" /* MessageType.RELEASE */) {\n // detach and deactive after sending release response above.\n ep.removeEventListener(\"message\", callback);\n closeEndPoint(ep);\n if (finalizer in obj && typeof obj[finalizer] === \"function\") {\n obj[finalizer]();\n }\n }\n })\n .catch((error) => {\n // Send Serialization Error To Caller\n const [wireValue, transferables] = toWireValue({\n value: new TypeError(\"Unserializable return value\"),\n [throwMarker]: 0,\n });\n ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);\n });\n });\n if (ep.start) {\n ep.start();\n }\n }\n function isMessagePort(endpoint) {\n return endpoint.constructor.name === \"MessagePort\";\n }\n function closeEndPoint(endpoint) {\n if (isMessagePort(endpoint))\n endpoint.close();\n }\n function wrap(ep, target) {\n return createProxy(ep, [], target);\n }\n function throwIfProxyReleased(isReleased) {\n if (isReleased) {\n throw new Error(\"Proxy has been released and is not useable\");\n }\n }\n function releaseEndpoint(ep) {\n return requestResponseMessage(ep, {\n type: \"RELEASE\" /* MessageType.RELEASE */,\n }).then(() => {\n closeEndPoint(ep);\n });\n }\n const proxyCounter = new WeakMap();\n const proxyFinalizers = \"FinalizationRegistry\" in globalThis &&\n new FinalizationRegistry((ep) => {\n const newCount = (proxyCounter.get(ep) || 0) - 1;\n proxyCounter.set(ep, newCount);\n if (newCount === 0) {\n releaseEndpoint(ep);\n }\n });\n function registerProxy(proxy, ep) {\n const newCount = (proxyCounter.get(ep) || 0) + 1;\n proxyCounter.set(ep, newCount);\n if (proxyFinalizers) {\n proxyFinalizers.register(proxy, ep, proxy);\n }\n }\n function unregisterProxy(proxy) {\n if (proxyFinalizers) {\n proxyFinalizers.unregister(proxy);\n }\n }\n function createProxy(ep, path = [], target = function () { }) {\n let isProxyReleased = false;\n const proxy = new Proxy(target, {\n get(_target, prop) {\n throwIfProxyReleased(isProxyReleased);\n if (prop === releaseProxy) {\n return () => {\n unregisterProxy(proxy);\n releaseEndpoint(ep);\n isProxyReleased = true;\n };\n }\n if (prop === \"then\") {\n if (path.length === 0) {\n return { then: () => proxy };\n }\n const r = requestResponseMessage(ep, {\n type: \"GET\" /* MessageType.GET */,\n path: path.map((p) => p.toString()),\n }).then(fromWireValue);\n return r.then.bind(r);\n }\n return createProxy(ep, [...path, prop]);\n },\n set(_target, prop, rawValue) {\n throwIfProxyReleased(isProxyReleased);\n // FIXME: ES6 Proxy Handler `set` methods are supposed to return a\n // boolean. To show good will, we return true asynchronously ¯\\_(ツ)_/¯\n const [value, transferables] = toWireValue(rawValue);\n return requestResponseMessage(ep, {\n type: \"SET\" /* MessageType.SET */,\n path: [...path, prop].map((p) => p.toString()),\n value,\n }, transferables).then(fromWireValue);\n },\n apply(_target, _thisArg, rawArgumentList) {\n throwIfProxyReleased(isProxyReleased);\n const last = path[path.length - 1];\n if (last === createEndpoint) {\n return requestResponseMessage(ep, {\n type: \"ENDPOINT\" /* MessageType.ENDPOINT */,\n }).then(fromWireValue);\n }\n // We just pretend that `bind()` didn’t happen.\n if (last === \"bind\") {\n return createProxy(ep, path.slice(0, -1));\n }\n const [argumentList, transferables] = processArguments(rawArgumentList);\n return requestResponseMessage(ep, {\n type: \"APPLY\" /* MessageType.APPLY */,\n path: path.map((p) => p.toString()),\n argumentList,\n }, transferables).then(fromWireValue);\n },\n construct(_target, rawArgumentList) {\n throwIfProxyReleased(isProxyReleased);\n const [argumentList, transferables] = processArguments(rawArgumentList);\n return requestResponseMessage(ep, {\n type: \"CONSTRUCT\" /* MessageType.CONSTRUCT */,\n path: path.map((p) => p.toString()),\n argumentList,\n }, transferables).then(fromWireValue);\n },\n });\n registerProxy(proxy, ep);\n return proxy;\n }\n function myFlat(arr) {\n return Array.prototype.concat.apply([], arr);\n }\n function processArguments(argumentList) {\n const processed = argumentList.map(toWireValue);\n return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];\n }\n const transferCache = new WeakMap();\n function transfer(obj, transfers) {\n transferCache.set(obj, transfers);\n return obj;\n }\n function proxy(obj) {\n return Object.assign(obj, { [proxyMarker]: true });\n }\n function toWireValue(value) {\n for (const [name, handler] of transferHandlers) {\n if (handler.canHandle(value)) {\n const [serializedValue, transferables] = handler.serialize(value);\n return [\n {\n type: \"HANDLER\" /* WireValueType.HANDLER */,\n name,\n value: serializedValue,\n },\n transferables,\n ];\n }\n }\n return [\n {\n type: \"RAW\" /* WireValueType.RAW */,\n value,\n },\n transferCache.get(value) || [],\n ];\n }\n function fromWireValue(value) {\n switch (value.type) {\n case \"HANDLER\" /* WireValueType.HANDLER */:\n return transferHandlers.get(value.name).deserialize(value.value);\n case \"RAW\" /* WireValueType.RAW */:\n return value.value;\n }\n }\n function requestResponseMessage(ep, msg, transfers) {\n return new Promise((resolve) => {\n const id = generateUUID();\n ep.addEventListener(\"message\", function l(ev) {\n if (!ev.data || !ev.data.id || ev.data.id !== id) {\n return;\n }\n ep.removeEventListener(\"message\", l);\n resolve(ev.data);\n });\n if (ep.start) {\n ep.start();\n }\n ep.postMessage(Object.assign({ id }, msg), transfers);\n });\n }\n function generateUUID() {\n return new Array(4)\n .fill(0)\n .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))\n .join(\"-\");\n }\n\n /**\n * MatrixRenderer class is meant to be used within a Web Worker context,\n * using Comlink to facilitate communication between the main thread and the worker.\n * The MatrixRenderer class manages a matrix of dies, once an instance of MatrixRenderer is created,\n * it is exposed to the main thread using Comlink's `expose` method.\n * This setup is used in the wafer-map component to perform heavy computational duties\n */\n class MatrixRenderer {\n constructor() {\n this.values = Float64Array.from([]);\n this.scaledColumnIndices = Float64Array.from([]);\n this.scaledRowIndices = Float64Array.from([]);\n this.columnIndicesPositions = Int32Array.from([]);\n this.renderConfig = {\n dieDimensions: {\n width: 0,\n height: 0\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n },\n verticalCoefficient: 1,\n horizontalCoefficient: 1,\n horizontalConstant: 0,\n verticalConstant: 0,\n labelsFontSize: 0,\n colorScale: []\n };\n this.transformConfig = {\n transform: {\n k: 1,\n x: 0,\n y: 0\n },\n topLeftCanvasCorner: {\n x: 0,\n y: 0\n },\n bottomRightCanvasCorner: {\n x: 0,\n y: 0\n }\n };\n }\n calculateHorizontalScaledIndices(columnIndex) {\n return (this.renderConfig.horizontalCoefficient * columnIndex\n + this.renderConfig.horizontalConstant\n + this.renderConfig.margin.left);\n }\n calculateVerticalScaledIndices(rowIndex) {\n return (this.renderConfig.verticalCoefficient * rowIndex\n + this.renderConfig.verticalConstant\n + this.renderConfig.margin.top);\n }\n setColumnIndices(columnIndices) {\n if (columnIndices.length === 0 || columnIndices[0] === undefined) {\n return;\n }\n const scaledColumnIndex = [\n this.calculateHorizontalScaledIndices(columnIndices[0])\n ];\n const columnPositions = [0];\n let prev = columnIndices[0];\n for (let i = 1; i < columnIndices.length; i++) {\n const xIndex = columnIndices[i];\n if (xIndex && xIndex !== prev) {\n const scaledX = this.calculateHorizontalScaledIndices(columnIndices[i]);\n scaledColumnIndex.push(scaledX);\n columnPositions.push(i);\n prev = xIndex;\n }\n }\n this.scaledColumnIndices = Float64Array.from(scaledColumnIndex);\n this.columnIndicesPositions = Int32Array.from(columnPositions);\n }\n setRowIndices(rowIndices) {\n this.scaledRowIndices = new Float64Array(rowIndices.length);\n for (let i = 0; i < rowIndices.length; i++) {\n this.scaledRowIndices[i] = this.calculateVerticalScaledIndices(rowIndices[i]);\n }\n }\n setRenderConfig(renderConfig) {\n this.renderConfig = renderConfig;\n }\n setTransformConfig(transformData) {\n this.transformConfig = transformData;\n }\n setCanvas(canvas) {\n this.canvas = canvas;\n this.context = canvas.getContext('2d');\n }\n scaleCanvas() {\n this.context.translate(this.transformConfig.transform.x, this.transformConfig.transform.y);\n this.context.scale(this.transformConfig.transform.k, this.transformConfig.transform.k);\n }\n setCanvasDimensions(data) {\n this.canvas.width = data.width;\n this.canvas.height = data.height;\n }\n getCanvasDimensions() {\n return {\n width: this.canvas.width,\n height: this.canvas.height\n };\n }\n clearCanvas() {\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n }\n drawWafer() {\n this.context.restore();\n this.context.save();\n this.clearCanvas();\n this.scaleCanvas();\n for (let i = 0; i < this.scaledColumnIndices.length; i++) {\n const scaledX = this.scaledColumnIndices[i];\n if (!(scaledX >= this.transformConfig.topLeftCanvasCorner.x\n && scaledX < this.transformConfig.bottomRightCanvasCorner.x)) {\n continue;\n }\n // columnIndexPositions is used to get chunks to determine the start and end index of the column, it looks something like [0, 1, 4, 9, 12]\n // This means that the first column has a start index of 0 and an end index of 1, the second column has a start index of 1 and an end index of 4, and so on\n // scaledRowIndices is used when we reach the end of the columnIndexPositions, when columnIndexPositions is [0, 1, 4, 9, 12], scaledRowIndices is 13\n const columnEndIndex = this.columnIndicesPositions[i + 1] !== undefined\n ? this.columnIndicesPositions[i + 1]\n : this.scaledRowIndices.length;\n for (let columnStartIndex = this.columnIndicesPositions[i]; columnStartIndex < columnEndIndex; columnStartIndex++) {\n const scaledY = this.scaledRowIndices[columnStartIndex];\n if (!(scaledY >= this.transformConfig.topLeftCanvasCorner.y\n && scaledY < this.transformConfig.bottomRightCanvasCorner.y)) {\n continue;\n }\n // Fill style is temporary green for all dies, will be replaced with a color based on the value of the die in a future implementation\n this.context.fillStyle = 'Green';\n this.context.fillRect(scaledX, scaledY, this.renderConfig.dieDimensions.width, this.renderConfig.dieDimensions.height);\n }\n }\n }\n }\n expose(MatrixRenderer);\n\n exports.MatrixRenderer = MatrixRenderer;\n\n return exports;\n\n})({});\n";
|
|
78378
78187
|
|
|
78379
78188
|
let url;
|
|
78380
78189
|
/**
|
|
@@ -78404,66 +78213,45 @@ img.ProseMirror-separator {
|
|
|
78404
78213
|
constructor(wafermap) {
|
|
78405
78214
|
this.wafermap = wafermap;
|
|
78406
78215
|
}
|
|
78407
|
-
async setupWafer() {
|
|
78216
|
+
async setupWafer(snapshot) {
|
|
78408
78217
|
if (this.matrixRenderer === undefined) {
|
|
78409
78218
|
const { matrixRenderer } = await createMatrixRenderer();
|
|
78410
78219
|
this.matrixRenderer = matrixRenderer;
|
|
78411
78220
|
const offscreenCanvas = this.wafermap.workerCanvas.transferControlToOffscreen();
|
|
78412
78221
|
await this.matrixRenderer.setCanvas(transfer(offscreenCanvas, [offscreenCanvas]));
|
|
78413
78222
|
}
|
|
78414
|
-
await this.matrixRenderer.setCanvasDimensions(
|
|
78415
|
-
|
|
78416
|
-
|
|
78417
|
-
|
|
78418
|
-
|
|
78419
|
-
|
|
78420
|
-
|
|
78421
|
-
const
|
|
78422
|
-
|
|
78423
|
-
|
|
78424
|
-
await this.matrixRenderer.setBases(this.wafermap.experimentalDataManager.horizontalScale(0), this.wafermap.experimentalDataManager.verticalScale(0));
|
|
78425
|
-
await this.matrixRenderer.setMargin(this.wafermap.experimentalDataManager.margin);
|
|
78426
|
-
if (this.wafermap.diesTable === undefined) {
|
|
78427
|
-
await this.matrixRenderer.setColumnIndexes(Int32Array.from([]));
|
|
78428
|
-
await this.matrixRenderer.setRowIndexes(Int32Array.from([]));
|
|
78429
|
-
return;
|
|
78430
|
-
}
|
|
78431
|
-
const columnIndexes = this.wafermap.diesTable
|
|
78432
|
-
.getChild('colIndex')
|
|
78433
|
-
.toArray();
|
|
78434
|
-
await this.matrixRenderer.setColumnIndexes(columnIndexes);
|
|
78435
|
-
const rowIndexes = this.wafermap.diesTable
|
|
78436
|
-
.getChild('rowIndex')
|
|
78437
|
-
.toArray();
|
|
78438
|
-
await this.matrixRenderer.setRowIndexes(rowIndexes);
|
|
78439
|
-
}
|
|
78440
|
-
async drawWafer() {
|
|
78441
|
-
await this.matrixRenderer.setTransform(this.wafermap.transform);
|
|
78442
|
-
const topLeftCanvasCorner = this.wafermap.transform.invert([0, 0]);
|
|
78443
|
-
const bottomRightCanvasCorner = this.wafermap.transform.invert([
|
|
78444
|
-
this.wafermap.canvasWidth,
|
|
78445
|
-
this.wafermap.canvasHeight
|
|
78223
|
+
await this.matrixRenderer.setCanvasDimensions(snapshot.canvasDimensions);
|
|
78224
|
+
await this.matrixRenderer.setRenderConfig(snapshot.renderConfig);
|
|
78225
|
+
await this.matrixRenderer.setColumnIndices(snapshot.columnIndices);
|
|
78226
|
+
await this.matrixRenderer.setRowIndices(snapshot.rowIndices);
|
|
78227
|
+
}
|
|
78228
|
+
async drawWafer(snapshot) {
|
|
78229
|
+
const topLeftCanvasCorner = snapshot.transform.invert([0, 0]);
|
|
78230
|
+
const bottomRightCanvasCorner = snapshot.transform.invert([
|
|
78231
|
+
snapshot.canvasDimensions.width,
|
|
78232
|
+
snapshot.canvasDimensions.height
|
|
78446
78233
|
]);
|
|
78447
|
-
await this.matrixRenderer.
|
|
78448
|
-
|
|
78449
|
-
|
|
78450
|
-
|
|
78451
|
-
-
|
|
78452
|
-
|
|
78453
|
-
|
|
78454
|
-
|
|
78234
|
+
await this.matrixRenderer.setTransformConfig({
|
|
78235
|
+
transform: snapshot.transform,
|
|
78236
|
+
topLeftCanvasCorner: {
|
|
78237
|
+
x: topLeftCanvasCorner[0] - snapshot.dieDimensions.width,
|
|
78238
|
+
y: topLeftCanvasCorner[1] - snapshot.dieDimensions.height
|
|
78239
|
+
},
|
|
78240
|
+
bottomRightCanvasCorner: {
|
|
78241
|
+
x: bottomRightCanvasCorner[0],
|
|
78242
|
+
y: bottomRightCanvasCorner[1]
|
|
78243
|
+
}
|
|
78455
78244
|
});
|
|
78456
78245
|
await this.matrixRenderer.drawWafer();
|
|
78457
|
-
this.renderHover();
|
|
78458
78246
|
}
|
|
78459
78247
|
renderHover() {
|
|
78460
|
-
if (this.wafermap.
|
|
78248
|
+
if (this.wafermap.computations.dieDimensions === undefined
|
|
78461
78249
|
|| this.wafermap.transform === undefined) {
|
|
78462
78250
|
return;
|
|
78463
78251
|
}
|
|
78464
|
-
this.wafermap.hoverWidth = this.wafermap.
|
|
78252
|
+
this.wafermap.hoverWidth = this.wafermap.computations.dieDimensions.width
|
|
78465
78253
|
* this.wafermap.transform.k;
|
|
78466
|
-
this.wafermap.hoverHeight = this.wafermap.
|
|
78254
|
+
this.wafermap.hoverHeight = this.wafermap.computations.dieDimensions.height
|
|
78467
78255
|
* this.wafermap.transform.k;
|
|
78468
78256
|
this.wafermap.hoverOpacity = this.wafermap.hoverDie === undefined
|
|
78469
78257
|
? HoverDieOpacity.hide
|
|
@@ -78472,17 +78260,17 @@ img.ProseMirror-separator {
|
|
|
78472
78260
|
}
|
|
78473
78261
|
calculateHoverTransform() {
|
|
78474
78262
|
if (this.wafermap.hoverDie !== undefined) {
|
|
78475
|
-
const scaledX = this.wafermap.
|
|
78263
|
+
const scaledX = this.wafermap.computations.horizontalScale(this.wafermap.hoverDie.x);
|
|
78476
78264
|
if (scaledX === undefined) {
|
|
78477
78265
|
return '';
|
|
78478
78266
|
}
|
|
78479
|
-
const scaledY = this.wafermap.
|
|
78267
|
+
const scaledY = this.wafermap.computations.verticalScale(this.wafermap.hoverDie.y);
|
|
78480
78268
|
if (scaledY === undefined) {
|
|
78481
78269
|
return '';
|
|
78482
78270
|
}
|
|
78483
78271
|
const transformedPoint = this.wafermap.transform.apply([
|
|
78484
|
-
scaledX + this.wafermap.
|
|
78485
|
-
scaledY + this.wafermap.
|
|
78272
|
+
scaledX + this.wafermap.computations.margin.left,
|
|
78273
|
+
scaledY + this.wafermap.computations.margin.top
|
|
78486
78274
|
]);
|
|
78487
78275
|
return `translate(${transformedPoint[0]}, ${transformedPoint[1]})`;
|
|
78488
78276
|
}
|
|
@@ -78642,10 +78430,8 @@ img.ProseMirror-separator {
|
|
|
78642
78430
|
? Math.ceil
|
|
78643
78431
|
: Math.floor;
|
|
78644
78432
|
// go to x and y scale to get the x,y values of the die.
|
|
78645
|
-
const x = xRoundFunction(this.wafermap.
|
|
78646
|
-
|
|
78647
|
-
const y = yRoundFunction(this.wafermap.experimentalDataManager.verticalScale.invert(mousePosition.y
|
|
78648
|
-
- this.wafermap.experimentalDataManager.margin.top));
|
|
78433
|
+
const x = xRoundFunction(this.wafermap.computations.horizontalScale.invert(mousePosition.x - this.wafermap.computations.margin.left));
|
|
78434
|
+
const y = yRoundFunction(this.wafermap.computations.verticalScale.invert(mousePosition.y - this.wafermap.computations.margin.top));
|
|
78649
78435
|
return { x, y };
|
|
78650
78436
|
}
|
|
78651
78437
|
return undefined;
|
|
@@ -78704,6 +78490,237 @@ img.ProseMirror-separator {
|
|
|
78704
78490
|
}
|
|
78705
78491
|
}
|
|
78706
78492
|
|
|
78493
|
+
/**
|
|
78494
|
+
* Computations calculates and stores different measures which are used in the Wafermap
|
|
78495
|
+
*/
|
|
78496
|
+
class Computations {
|
|
78497
|
+
get horizontalScale() {
|
|
78498
|
+
return this._horizontalScale;
|
|
78499
|
+
}
|
|
78500
|
+
get verticalScale() {
|
|
78501
|
+
return this._verticalScale;
|
|
78502
|
+
}
|
|
78503
|
+
get containerDimensions() {
|
|
78504
|
+
return this._containerDimensions;
|
|
78505
|
+
}
|
|
78506
|
+
get dieDimensions() {
|
|
78507
|
+
return this._dieDimensions;
|
|
78508
|
+
}
|
|
78509
|
+
get margin() {
|
|
78510
|
+
return this._margin;
|
|
78511
|
+
}
|
|
78512
|
+
get verticalCoefficient() {
|
|
78513
|
+
return this._verticalCoefficient;
|
|
78514
|
+
}
|
|
78515
|
+
get horizontalCoefficient() {
|
|
78516
|
+
return this._horizontalCoefficient;
|
|
78517
|
+
}
|
|
78518
|
+
get horizontalConstant() {
|
|
78519
|
+
return this._horizontalConstant;
|
|
78520
|
+
}
|
|
78521
|
+
get verticalConstant() {
|
|
78522
|
+
return this._verticalConstant;
|
|
78523
|
+
}
|
|
78524
|
+
get labelsFontSize() {
|
|
78525
|
+
return this._labelsFontSize;
|
|
78526
|
+
}
|
|
78527
|
+
get colorScale() {
|
|
78528
|
+
return this._colorScale;
|
|
78529
|
+
}
|
|
78530
|
+
constructor(wafermap) {
|
|
78531
|
+
this.wafermap = wafermap;
|
|
78532
|
+
this.baseMarginPercentage = 0.04;
|
|
78533
|
+
this.fontSizeFactor = 0.8;
|
|
78534
|
+
this.colorScaleResolution = 10;
|
|
78535
|
+
}
|
|
78536
|
+
componentResizeUpdate() {
|
|
78537
|
+
const canvasDimensions = {
|
|
78538
|
+
width: this.wafermap.canvasWidth,
|
|
78539
|
+
height: this.wafermap.canvasHeight
|
|
78540
|
+
};
|
|
78541
|
+
const canvasDiameter = Math.min(canvasDimensions.width, canvasDimensions.height);
|
|
78542
|
+
const canvasMargin = {
|
|
78543
|
+
top: (canvasDimensions.height - canvasDiameter) / 2,
|
|
78544
|
+
right: (canvasDimensions.width - canvasDiameter) / 2,
|
|
78545
|
+
bottom: (canvasDimensions.height - canvasDiameter) / 2,
|
|
78546
|
+
left: (canvasDimensions.width - canvasDiameter) / 2
|
|
78547
|
+
};
|
|
78548
|
+
const baseMargin = {
|
|
78549
|
+
top: canvasDiameter * this.baseMarginPercentage,
|
|
78550
|
+
right: canvasDiameter * this.baseMarginPercentage,
|
|
78551
|
+
bottom: canvasDiameter * this.baseMarginPercentage,
|
|
78552
|
+
left: canvasDiameter * this.baseMarginPercentage
|
|
78553
|
+
};
|
|
78554
|
+
this._margin = this.calculateMarginAddition(baseMargin, canvasMargin);
|
|
78555
|
+
this._containerDimensions = this.calculateContainerDimensions(canvasDimensions, this.margin);
|
|
78556
|
+
this.inputDataUpdate();
|
|
78557
|
+
}
|
|
78558
|
+
inputDataUpdate() {
|
|
78559
|
+
if (this._containerDimensions === undefined) {
|
|
78560
|
+
this.componentResizeUpdate();
|
|
78561
|
+
return;
|
|
78562
|
+
}
|
|
78563
|
+
const containerDiameter = Math.min(this._containerDimensions.width, this._containerDimensions.height);
|
|
78564
|
+
const gridDimensions = this.gridDimensionsValidAndDefined()
|
|
78565
|
+
? this.calculateGridDimensionsFromBoundingBox()
|
|
78566
|
+
: this.calculateGridDimensionsFromDies();
|
|
78567
|
+
// this scale is used for positioning the dies on the canvas
|
|
78568
|
+
const originLocation = this.wafermap.originLocation;
|
|
78569
|
+
this._horizontalScale = this.createHorizontalScale(originLocation, gridDimensions, containerDiameter);
|
|
78570
|
+
// this scale is used for positioning the dies on the canvas
|
|
78571
|
+
this._verticalScale = this.createVerticalScale(originLocation, gridDimensions, containerDiameter);
|
|
78572
|
+
this._horizontalCoefficient = this._horizontalScale(1) - this._horizontalScale(0);
|
|
78573
|
+
this._verticalCoefficient = this._verticalScale(1) - this._verticalScale(0);
|
|
78574
|
+
this._horizontalConstant = this._horizontalScale(0);
|
|
78575
|
+
this._verticalConstant = this._verticalScale(0);
|
|
78576
|
+
this._dieDimensions = {
|
|
78577
|
+
width: Math.abs(this._horizontalScale(0) - this._horizontalScale(1)),
|
|
78578
|
+
height: Math.abs(this._verticalScale(0) - this._verticalScale(1))
|
|
78579
|
+
};
|
|
78580
|
+
this.colorAndTextUpdate();
|
|
78581
|
+
}
|
|
78582
|
+
colorAndTextUpdate() {
|
|
78583
|
+
if (this._dieDimensions === undefined) {
|
|
78584
|
+
this.inputDataUpdate();
|
|
78585
|
+
return;
|
|
78586
|
+
}
|
|
78587
|
+
this._labelsFontSize = this.calculateLabelsFontSize(this._dieDimensions, this.wafermap.maxCharacters);
|
|
78588
|
+
this._colorScale = this.calculateColorScale();
|
|
78589
|
+
}
|
|
78590
|
+
gridDimensionsValidAndDefined() {
|
|
78591
|
+
return (!this.wafermap.validity.invalidGridDimensions
|
|
78592
|
+
&& typeof this.wafermap.gridMinX === 'number'
|
|
78593
|
+
&& typeof this.wafermap.gridMinY === 'number'
|
|
78594
|
+
&& typeof this.wafermap.gridMaxX === 'number'
|
|
78595
|
+
&& typeof this.wafermap.gridMinX === 'number');
|
|
78596
|
+
}
|
|
78597
|
+
calculateGridDimensionsFromBoundingBox() {
|
|
78598
|
+
const gridDimensions = { origin: { x: 0, y: 0 }, rows: 0, cols: 0 };
|
|
78599
|
+
if (typeof this.wafermap.gridMaxY === 'number'
|
|
78600
|
+
&& typeof this.wafermap.gridMinY === 'number'
|
|
78601
|
+
&& typeof this.wafermap.gridMaxX === 'number'
|
|
78602
|
+
&& typeof this.wafermap.gridMinX === 'number') {
|
|
78603
|
+
gridDimensions.origin.x = this.wafermap.gridMinX;
|
|
78604
|
+
gridDimensions.origin.y = this.wafermap.gridMinY;
|
|
78605
|
+
gridDimensions.rows = this.wafermap.gridMaxY - this.wafermap.gridMinY + 1;
|
|
78606
|
+
gridDimensions.cols = this.wafermap.gridMaxX - this.wafermap.gridMinX + 1;
|
|
78607
|
+
}
|
|
78608
|
+
return gridDimensions;
|
|
78609
|
+
}
|
|
78610
|
+
calculateGridDimensionsFromDies() {
|
|
78611
|
+
if (this.wafermap.diesTable === undefined) {
|
|
78612
|
+
return { origin: { x: 0, y: 0 }, rows: 0, cols: 0 };
|
|
78613
|
+
}
|
|
78614
|
+
const colIndex = this.wafermap.diesTable
|
|
78615
|
+
.getChild('colIndex')
|
|
78616
|
+
.toArray();
|
|
78617
|
+
const rowIndex = this.wafermap.diesTable
|
|
78618
|
+
.getChild('rowIndex')
|
|
78619
|
+
.toArray();
|
|
78620
|
+
const minPoint = { x: colIndex[0], y: rowIndex[0] };
|
|
78621
|
+
const maxPoint = { x: colIndex[0], y: rowIndex[0] };
|
|
78622
|
+
// will replace iterating with arquero after fixing issues: https://github.com/uwdata/arquero/pull/346
|
|
78623
|
+
for (let i = 0; i < colIndex.length; i++) {
|
|
78624
|
+
if (colIndex[i] < minPoint.x) {
|
|
78625
|
+
minPoint.x = colIndex[i];
|
|
78626
|
+
}
|
|
78627
|
+
if (colIndex[i] > maxPoint.x) {
|
|
78628
|
+
maxPoint.x = colIndex[i];
|
|
78629
|
+
}
|
|
78630
|
+
if (rowIndex[i] < minPoint.y) {
|
|
78631
|
+
minPoint.y = rowIndex[i];
|
|
78632
|
+
}
|
|
78633
|
+
if (rowIndex[i] > maxPoint.y) {
|
|
78634
|
+
maxPoint.y = rowIndex[i];
|
|
78635
|
+
}
|
|
78636
|
+
}
|
|
78637
|
+
return {
|
|
78638
|
+
origin: minPoint,
|
|
78639
|
+
rows: maxPoint.y - minPoint.y + 1,
|
|
78640
|
+
cols: maxPoint.x - minPoint.x + 1
|
|
78641
|
+
};
|
|
78642
|
+
}
|
|
78643
|
+
calculateContainerDimensions(canvasDimensions, margin) {
|
|
78644
|
+
return {
|
|
78645
|
+
width: canvasDimensions.width - margin.left - margin.right,
|
|
78646
|
+
height: canvasDimensions.height - margin.top - margin.bottom
|
|
78647
|
+
};
|
|
78648
|
+
}
|
|
78649
|
+
createHorizontalScale(originLocation, grid, containerWidth) {
|
|
78650
|
+
const scale = linear();
|
|
78651
|
+
if (originLocation === WaferMapOriginLocation.bottomLeft
|
|
78652
|
+
|| originLocation === WaferMapOriginLocation.topLeft) {
|
|
78653
|
+
return scale
|
|
78654
|
+
.domain([grid.origin.x, grid.origin.x + grid.cols])
|
|
78655
|
+
.range([0, containerWidth]);
|
|
78656
|
+
}
|
|
78657
|
+
return scale
|
|
78658
|
+
.domain([grid.origin.x - 1, grid.origin.x + grid.cols - 1])
|
|
78659
|
+
.range([containerWidth, 0]);
|
|
78660
|
+
}
|
|
78661
|
+
createVerticalScale(originLocation, grid, containerHeight) {
|
|
78662
|
+
const scale = linear();
|
|
78663
|
+
// html canvas has top-left origin https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes#the_grid
|
|
78664
|
+
// we need to flip the vertical scale
|
|
78665
|
+
if (originLocation === WaferMapOriginLocation.bottomLeft
|
|
78666
|
+
|| originLocation === WaferMapOriginLocation.bottomRight) {
|
|
78667
|
+
return scale
|
|
78668
|
+
.domain([grid.origin.y - 1, grid.origin.y + grid.rows - 1])
|
|
78669
|
+
.range([containerHeight, 0]);
|
|
78670
|
+
}
|
|
78671
|
+
return scale
|
|
78672
|
+
.domain([grid.origin.y, grid.origin.y + grid.rows])
|
|
78673
|
+
.range([0, containerHeight]);
|
|
78674
|
+
}
|
|
78675
|
+
calculateMarginAddition(baseMargin, addedMargin) {
|
|
78676
|
+
return {
|
|
78677
|
+
top: baseMargin.top + addedMargin.top,
|
|
78678
|
+
right: baseMargin.right + addedMargin.right,
|
|
78679
|
+
bottom: baseMargin.bottom + addedMargin.bottom,
|
|
78680
|
+
left: baseMargin.left + addedMargin.left
|
|
78681
|
+
};
|
|
78682
|
+
}
|
|
78683
|
+
calculateColorScale() {
|
|
78684
|
+
if (this.wafermap.colorScaleMode === WaferMapColorScaleMode.linear) {
|
|
78685
|
+
const values = this.wafermap.colorScale.values.map(item => +item);
|
|
78686
|
+
const d3ColorScale = linear()
|
|
78687
|
+
.domain(values)
|
|
78688
|
+
.range(this.wafermap.colorScale.colors);
|
|
78689
|
+
let min = values[0];
|
|
78690
|
+
let max = values[0];
|
|
78691
|
+
values.forEach(value => {
|
|
78692
|
+
if (value < min) {
|
|
78693
|
+
min = value;
|
|
78694
|
+
}
|
|
78695
|
+
if (value > max) {
|
|
78696
|
+
max = value;
|
|
78697
|
+
}
|
|
78698
|
+
});
|
|
78699
|
+
// the linear color scale will not be infinite but will be limited by the color scale resolution
|
|
78700
|
+
const valueSamples = ticks(min, max, values.length * this.colorScaleResolution);
|
|
78701
|
+
return valueSamples.map(value => {
|
|
78702
|
+
return {
|
|
78703
|
+
color: d3ColorScale(value),
|
|
78704
|
+
value
|
|
78705
|
+
};
|
|
78706
|
+
});
|
|
78707
|
+
}
|
|
78708
|
+
// ordinal color categories have to be sorted by value
|
|
78709
|
+
return this.wafermap.colorScale.colors
|
|
78710
|
+
.map((color, index) => {
|
|
78711
|
+
return {
|
|
78712
|
+
color,
|
|
78713
|
+
value: +this.wafermap.colorScale.values[index]
|
|
78714
|
+
};
|
|
78715
|
+
})
|
|
78716
|
+
.sort((a, b) => a.value - b.value);
|
|
78717
|
+
}
|
|
78718
|
+
calculateLabelsFontSize(dieDimensions, maxCharacters) {
|
|
78719
|
+
return Math.min(dieDimensions.height, (dieDimensions.width / (Math.max(2, maxCharacters) * 0.5))
|
|
78720
|
+
* this.fontSizeFactor);
|
|
78721
|
+
}
|
|
78722
|
+
}
|
|
78723
|
+
|
|
78707
78724
|
/**
|
|
78708
78725
|
* A nimble-styled WaferMap
|
|
78709
78726
|
*/
|
|
@@ -78725,8 +78742,8 @@ img.ProseMirror-separator {
|
|
|
78725
78742
|
this.dieLabelsHidden = false;
|
|
78726
78743
|
this.dieLabelsSuffix = '';
|
|
78727
78744
|
this.colorScaleMode = WaferMapColorScaleMode.linear;
|
|
78728
|
-
this.
|
|
78729
|
-
this.dataManager = new DataManager
|
|
78745
|
+
this.computations = new Computations(this.asRequiredFieldsWaferMap);
|
|
78746
|
+
this.dataManager = new DataManager(this.asRequiredFieldsWaferMap);
|
|
78730
78747
|
this.workerRenderer = new WorkerRenderer(this.asRequiredFieldsWaferMap);
|
|
78731
78748
|
this.renderer = new RenderingModule(this.asRequiredFieldsWaferMap);
|
|
78732
78749
|
/**
|
|
@@ -78795,24 +78812,22 @@ img.ProseMirror-separator {
|
|
|
78795
78812
|
return;
|
|
78796
78813
|
}
|
|
78797
78814
|
if (this.waferMapUpdateTracker.requiresEventsUpdate) {
|
|
78798
|
-
if (this.waferMapUpdateTracker.
|
|
78799
|
-
|
|
78800
|
-
this.experimentalDataManager.updateComputations();
|
|
78801
|
-
await this.workerRenderer.setupWafer();
|
|
78802
|
-
await this.workerRenderer.drawWafer();
|
|
78815
|
+
if (this.waferMapUpdateTracker.requiresComponentResizeUpdate) {
|
|
78816
|
+
this.computations.componentResizeUpdate();
|
|
78803
78817
|
}
|
|
78804
|
-
else if (this.waferMapUpdateTracker.
|
|
78805
|
-
|
|
78806
|
-
this.experimentalDataManager.updatePrerendering();
|
|
78807
|
-
await this.workerRenderer.drawWafer();
|
|
78818
|
+
else if (this.waferMapUpdateTracker.requiresInputDataUpdate) {
|
|
78819
|
+
this.computations.inputDataUpdate();
|
|
78808
78820
|
}
|
|
78809
|
-
else if (this.waferMapUpdateTracker.
|
|
78810
|
-
|
|
78821
|
+
else if (this.waferMapUpdateTracker.requiresColorAndTextUpdate) {
|
|
78822
|
+
this.computations.colorAndTextUpdate();
|
|
78811
78823
|
}
|
|
78824
|
+
const snapshot = this.createSnapshot();
|
|
78825
|
+
if (this.waferMapUpdateTracker.requiresWorkerWaferSetup) {
|
|
78826
|
+
await this.workerRenderer.setupWafer(snapshot);
|
|
78827
|
+
}
|
|
78828
|
+
await this.workerRenderer.drawWafer(snapshot);
|
|
78812
78829
|
}
|
|
78813
|
-
|
|
78814
|
-
this.workerRenderer.renderHover();
|
|
78815
|
-
}
|
|
78830
|
+
this.workerRenderer.renderHover();
|
|
78816
78831
|
}
|
|
78817
78832
|
/**
|
|
78818
78833
|
* @internal
|
|
@@ -78859,6 +78874,44 @@ img.ProseMirror-separator {
|
|
|
78859
78874
|
isExperimentalUpdate() {
|
|
78860
78875
|
return this.diesTable !== undefined;
|
|
78861
78876
|
}
|
|
78877
|
+
createSnapshot() {
|
|
78878
|
+
const canvasDimensions = {
|
|
78879
|
+
width: this.canvasWidth ?? 0,
|
|
78880
|
+
height: this.canvasHeight ?? 0
|
|
78881
|
+
};
|
|
78882
|
+
const renderConfig = {
|
|
78883
|
+
dieDimensions: this.computations.dieDimensions,
|
|
78884
|
+
margin: this.computations.margin,
|
|
78885
|
+
verticalCoefficient: this.computations.verticalCoefficient,
|
|
78886
|
+
horizontalCoefficient: this.computations.horizontalCoefficient,
|
|
78887
|
+
horizontalConstant: this.computations.horizontalConstant,
|
|
78888
|
+
verticalConstant: this.computations.verticalConstant,
|
|
78889
|
+
labelsFontSize: this.computations.labelsFontSize,
|
|
78890
|
+
colorScale: this.computations.colorScale
|
|
78891
|
+
};
|
|
78892
|
+
const dieDimensions = this.computations.dieDimensions;
|
|
78893
|
+
const transform = this.transform;
|
|
78894
|
+
if (this.diesTable === undefined) {
|
|
78895
|
+
return {
|
|
78896
|
+
canvasDimensions,
|
|
78897
|
+
renderConfig,
|
|
78898
|
+
dieDimensions,
|
|
78899
|
+
transform,
|
|
78900
|
+
columnIndices: Int32Array.from([]),
|
|
78901
|
+
rowIndices: Int32Array.from([])
|
|
78902
|
+
};
|
|
78903
|
+
}
|
|
78904
|
+
const columnIndices = this.diesTable.getChild('colIndex').toArray();
|
|
78905
|
+
const rowIndices = this.diesTable.getChild('rowIndex').toArray();
|
|
78906
|
+
return {
|
|
78907
|
+
canvasDimensions,
|
|
78908
|
+
renderConfig,
|
|
78909
|
+
columnIndices,
|
|
78910
|
+
rowIndices,
|
|
78911
|
+
dieDimensions,
|
|
78912
|
+
transform
|
|
78913
|
+
};
|
|
78914
|
+
}
|
|
78862
78915
|
validate() {
|
|
78863
78916
|
this.waferMapValidator.validateGridDimensions();
|
|
78864
78917
|
this.waferMapValidator.validateDiesTableSchema();
|