Socket
Socket
Sign inDemoInstall

vega-label

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vega-label - npm Package Compare versions

Comparing version 0.0.5 to 1.0.0

build/vega-label.min.js.map

609

build/vega-label.js

@@ -7,16 +7,12 @@ (function (global, factory) {

// bit mask for getting first 2 bytes of alpha value
const ALPHA_MASK = 0xff000000;
const ALPHA_MASK = 0xff000000; // alpha value equivalent to opacity 0.0625
// alpha value equivalent to opacity 0.0625
const INSIDE_OPACITY_IN_ALPHA = 0x10000000;
const INSIDE_OPACITY = 0.0625;
function baseBitmaps($, data) {
const bitmap = $.bitmap(); // when there is no base mark but data points are to be avoided
function baseBitmaps($, data) {
const bitmap = $.bitmap();
// when there is no base mark but data points are to be avoided
(data || []).forEach(d => bitmap.set($(d.boundary[0]), $(d.boundary[3])));
return [bitmap, undefined];
}
function markBitmaps($, avoidMarks, labelInside, isGroupArea) {

@@ -27,17 +23,16 @@ // create canvas

border = labelInside || isGroupArea,
context = vegaCanvas.canvas(width, height).getContext('2d');
context = vegaCanvas.canvas(width, height).getContext('2d'); // render all marks to be avoided into canvas
// render all marks to be avoided into canvas
avoidMarks.forEach(items => draw(context, items, border));
avoidMarks.forEach(items => draw(context, items, border)); // get canvas buffer, create bitmaps
// get canvas buffer, create bitmaps
const buffer = new Uint32Array(context.getImageData(0, 0, width, height).data.buffer),
layer1 = $.bitmap(),
layer2 = border && $.bitmap();
layer2 = border && $.bitmap(); // populate bitmap layers
// populate bitmap layers
let x, y, u, v, alpha;
for (y=0; y < height; ++y) {
for (x=0; x < width; ++x) {
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
alpha = buffer[y * width + x] & ALPHA_MASK;
if (alpha) {

@@ -47,2 +42,3 @@ u = $(x);

if (!isGroupArea) layer1.set(u, v); // update interior bitmap
if (border && alpha ^ INSIDE_OPACITY_IN_ALPHA) layer2.set(u, v); // update border bitmap

@@ -65,6 +61,7 @@ }

} else {
vegaScenegraph.Marks[type].draw(context, {items: interior ? items.map(prepare) : items});
vegaScenegraph.Marks[type].draw(context, {
items: interior ? items.map(prepare) : items
});
}
}
/**

@@ -75,2 +72,4 @@ * Prepare item before drawing into canvas (setting stroke and opacity)

*/
function prepare(source) {

@@ -93,16 +92,21 @@ const item = vegaDataflow.rederive(source, {});

const DIV = 5, // bit shift from x, y index to bit vector array index
MOD = 31, // bit mask for index lookup within a bit vector
SIZE = 32, // individual bit vector size
RIGHT0 = new Uint32Array(SIZE + 1), // left-anchored bit vectors, full -> 0
RIGHT1 = new Uint32Array(SIZE + 1); // right-anchored bit vectors, 0 -> full
const DIV = 5,
// bit shift from x, y index to bit vector array index
MOD = 31,
// bit mask for index lookup within a bit vector
SIZE = 32,
// individual bit vector size
RIGHT0 = new Uint32Array(SIZE + 1),
// left-anchored bit vectors, full -> 0
RIGHT1 = new Uint32Array(SIZE + 1); // right-anchored bit vectors, 0 -> full
RIGHT1[0] = 0;
RIGHT0[0] = ~RIGHT1[0];
for (let i=1; i <= SIZE; ++i) {
RIGHT1[i] = (RIGHT1[i - 1] << 1) | 1;
for (let i = 1; i <= SIZE; ++i) {
RIGHT1[i] = RIGHT1[i - 1] << 1 | 1;
RIGHT0[i] = ~RIGHT1[i];
}
function Bitmap(w, h) {
function Bitmap (w, h) {
const array = new Uint32Array(~~((w * h + SIZE) / SIZE));

@@ -120,20 +124,23 @@

array: array,
get: (x, y) => {
const index = y * w + x;
return array[index >>> DIV] & (1 << (index & MOD));
return array[index >>> DIV] & 1 << (index & MOD);
},
set: (x, y) => {
const index = y * w + x;
_set(index >>> DIV, 1 << (index & MOD));
},
clear: (x, y) => {
const index = y * w + x;
_clear(index >>> DIV, ~(1 << (index & MOD)));
},
getRange: (x, y, x2, y2) => {
let r = y2,
start,
end,
indexStart,
indexEnd;
getRange: (x, y, x2, y2) => {
let r = y2, start, end, indexStart, indexEnd;
for (; r >= y; --r) {

@@ -144,2 +151,3 @@ start = r * w + x;

indexEnd = end >>> DIV;
if (indexStart === indexEnd) {

@@ -152,2 +160,3 @@ if (array[indexStart] & RIGHT0[start & MOD] & RIGHT1[(end & MOD) + 1]) {

if (array[indexEnd] & RIGHT1[(end & MOD) + 1]) return true;
for (let i = indexStart + 1; i < indexEnd; ++i) {

@@ -158,7 +167,8 @@ if (array[i]) return true;

}
return false;
},
setRange: (x, y, x2, y2) => {
let start, end, indexStart, indexEnd, i;
for (; y <= y2; ++y) {

@@ -169,2 +179,3 @@ start = y * w + x;

indexEnd = end >>> DIV;
if (indexStart === indexEnd) {

@@ -174,3 +185,5 @@ _set(indexStart, RIGHT0[start & MOD] & RIGHT1[(end & MOD) + 1]);

_set(indexStart, RIGHT0[start & MOD]);
_set(indexEnd, RIGHT1[(end & MOD) + 1]);
for (i = indexStart + 1; i < indexEnd; ++i) _set(i, 0xffffffff);

@@ -180,5 +193,5 @@ }

},
clearRange: (x, y, x2, y2) => {
let start, end, indexStart, indexEnd, i;
for (; y <= y2; ++y) {

@@ -189,2 +202,3 @@ start = y * w + x;

indexEnd = end >>> DIV;
if (indexStart === indexEnd) {

@@ -194,3 +208,5 @@ _clear(indexStart, RIGHT1[start & MOD] | RIGHT0[(end & MOD) + 1]);

_clear(indexStart, RIGHT1[start & MOD]);
_clear(indexEnd, RIGHT0[(end & MOD) + 1]);
for (i = indexStart + 1; i < indexEnd; ++i) _clear(i, 0);

@@ -200,3 +216,2 @@ }

},
outOfBounds: (x, y, x2, y2) => x < 0 || y < 0 || y2 >= h || x2 >= w

@@ -206,4 +221,4 @@ };

function scaler(width, height, padding) {
const ratio = Math.max(1, Math.sqrt((width * height) / 1e6)),
function scaler (width, height, padding) {
const ratio = Math.max(1, Math.sqrt(width * height / 1e6)),
w = ~~((width + 2 * padding + ratio) / ratio),

@@ -213,4 +228,6 @@ h = ~~((height + 2 * padding + ratio) / ratio),

scale.invert = _ => (_ * ratio) - padding;
scale.invert = _ => _ * ratio - padding;
scale.bitmap = () => Bitmap(w, h);
scale.ratio = ratio;

@@ -220,22 +237,28 @@ scale.padding = padding;

scale.height = height;
return scale;
}
function placeAreaLabelNaive($, bitmaps, avoidBaseMark, markIndex) {
function placeAreaLabelNaive ($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height;
// try to place a label within an input area mark
return function(d) {
const items = d.datum.datum.items[markIndex].items, // area points
n = items.length, // number of points
textHeight = d.datum.fontSize, // label width
textWidth = vegaScenegraph.textMetrics.width(d.datum, d.datum.text); // label height
height = $.height; // try to place a label within an input area mark
return function (d) {
const items = d.datum.datum.items[markIndex].items,
// area points
n = items.length,
// number of points
textHeight = d.datum.fontSize,
// label width
textWidth = vegaScenegraph.textMetrics.width(d.datum, d.datum.text); // label height
let maxAreaWidth = 0,
x1, x2, y1, y2, x, y, areaWidth;
x1,
x2,
y1,
y2,
x,
y,
areaWidth; // for each area sample point
// for each area sample point
for (let i=0; i<n; ++i) {
for (let i = 0; i < n; ++i) {
x1 = items[i].x;

@@ -247,4 +270,4 @@ y1 = items[i].y;

y = (y1 + y2) / 2;
areaWidth = Math.abs(x2 - x1 + y2 - y1);
areaWidth = Math.abs(x2 - x1 + y2 - y1);
if (areaWidth >= maxAreaWidth) {

@@ -263,4 +286,4 @@ maxAreaWidth = areaWidth;

y2 = d.y + y;
d.align = 'center';
d.align = 'center';
if (x1 < 0 && x2 <= width) {

@@ -273,2 +296,3 @@ d.align = 'left';

d.baseline = 'middle';
if (y1 < 0 && y2 <= height) {

@@ -286,26 +310,20 @@ d.baseline = 'top';

let r = textWidth / 2;
return x - r < 0
|| x + r > width
|| y - (r = textHeight / 2) < 0
|| y + r > height;
return x - r < 0 || x + r > width || y - (r = textHeight / 2) < 0 || y + r > height;
}
function collision($, x, y, textHeight, textWidth, h, bm0, bm1) {
const w = (textWidth * h) / (textHeight * 2),
const w = textWidth * h / (textHeight * 2),
x1 = $(x - w),
x2 = $(x + w),
y1 = $(y - (h = h/2)),
y1 = $(y - (h = h / 2)),
y2 = $(y + h);
return bm0.outOfBounds(x1, y1, x2, y2)
|| bm0.getRange(x1, y1, x2, y2)
|| (bm1 && bm1.getRange(x1, y1, x2, y2));
return bm0.outOfBounds(x1, y1, x2, y2) || bm0.getRange(x1, y1, x2, y2) || bm1 && bm1.getRange(x1, y1, x2, y2);
}
function placeAreaLabelReducedSearch($, bitmaps, avoidBaseMark, markIndex) {
function placeAreaLabelReducedSearch ($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height,
bm0 = bitmaps[0], // where labels have been placed
bm1 = bitmaps[1]; // area outlines
height = $.height,
bm0 = bitmaps[0],
// where labels have been placed
bm1 = bitmaps[1]; // area outlines
function tryLabel(_x, _y, maxSize, textWidth, textHeight) {

@@ -317,7 +335,4 @@ const x = $.invert(_x),

mid;
if (
!outOfBounds(x, y, textWidth, textHeight, width, height) &&
!collision($, x, y, textHeight, textWidth, lo, bm0, bm1) &&
!collision($, x, y, textHeight, textWidth, textHeight, bm0, null)
) {
if (!outOfBounds(x, y, textWidth, textHeight, width, height) && !collision($, x, y, textHeight, textWidth, lo, bm0, bm1) && !collision($, x, y, textHeight, textWidth, textHeight, bm0, null)) {
// if the label fits at the current sample point,

@@ -327,2 +342,3 @@ // perform binary search to find the largest font size that fits

mid = (lo + hi) / 2;
if (collision($, x, y, textHeight, textWidth, mid, bm0, bm1)) {

@@ -333,4 +349,5 @@ hi = mid;

}
}
// place label if current lower bound exceeds prior max font size
} // place label if current lower bound exceeds prior max font size
if (lo > maxSize) {

@@ -340,11 +357,14 @@ return [x, y, lo, true];

}
}
} // try to place a label within an input area mark
// try to place a label within an input area mark
return function(d) {
const items = d.datum.datum.items[markIndex].items, // area points
n = items.length, // number of points
textHeight = d.datum.fontSize, // label width
textWidth = vegaScenegraph.textMetrics.width(d.datum, d.datum.text); // label height
return function (d) {
const items = d.datum.datum.items[markIndex].items,
// area points
n = items.length,
// number of points
textHeight = d.datum.fontSize,
// label width
textWidth = vegaScenegraph.textMetrics.width(d.datum, d.datum.text); // label height
let maxSize = avoidBaseMark ? textHeight : 0,

@@ -354,6 +374,22 @@ labelPlaced = false,

maxAreaWidth = 0,
x1, x2, y1, y2, x, y, _x, _y, _x1, _xMid, _x2, _y1, _yMid, _y2, areaWidth, result, swapTmp;
x1,
x2,
y1,
y2,
x,
y,
_x,
_y,
_x1,
_xMid,
_x2,
_y1,
_yMid,
_y2,
areaWidth,
result,
swapTmp; // for each area sample point
// for each area sample point
for (let i=0; i<n; ++i) {
for (let i = 0; i < n; ++i) {
x1 = items[i].x;

@@ -381,8 +417,8 @@ y1 = items[i].y;

_y2 = $(y2);
_yMid = ~~((_y1 + _y2) / 2);
_yMid = ~~((_y1 + _y2) / 2); // search along the line from mid point between the 2 border to lower border
// search along the line from mid point between the 2 border to lower border
for (_x = _xMid; _x >= _x1; --_x) {
for (_y = _yMid; _y >= _y1; --_y) {
result = tryLabel(_x, _y, maxSize, textWidth, textHeight);
if (result) {

@@ -392,8 +428,9 @@ [d.x, d.y, maxSize, labelPlaced] = result;

}
}
} // search along the line from mid point between the 2 border to upper border
// search along the line from mid point between the 2 border to upper border
for (_x = _xMid; _x <= _x2; ++_x) {
for (_y = _yMid; _y <= _y2; ++_y) {
result = tryLabel(_x, _y, maxSize, textWidth, textHeight);
if (result) {

@@ -403,6 +440,6 @@ [d.x, d.y, maxSize, labelPlaced] = result;

}
}
} // place label at slice center if not placed through other means
// and if we're not avoiding overlap with other areas
// place label at slice center if not placed through other means
// and if we're not avoiding overlap with other areas
if (!labelPlaced && !avoidBaseMark) {

@@ -412,10 +449,5 @@ // one span is zero, hence we can add

x = (x1 + x2) / 2;
y = (y1 + y2) / 2;
y = (y1 + y2) / 2; // place label if it fits and improves the max area width
// place label if it fits and improves the max area width
if (
areaWidth >= maxAreaWidth &&
!outOfBounds(x, y, textWidth, textHeight, width, height) &&
!collision($, x, y, textHeight, textWidth, textHeight, bm0, null)
) {
if (areaWidth >= maxAreaWidth && !outOfBounds(x, y, textWidth, textHeight, width, height) && !collision($, x, y, textHeight, textWidth, textHeight, bm0, null)) {
maxAreaWidth = areaWidth;

@@ -427,5 +459,5 @@ d.x = x;

}
}
} // record current label placement information, update label bitmap
// record current label placement information, update label bitmap
if (labelPlaced || labelPlaced2) {

@@ -444,21 +476,25 @@ x = textWidth / 2;

// pixel direction offsets for flood fill search
const X_DIR = [-1, -1, 1, 1];
const Y_DIR = [-1, 1, -1, 1];
function placeAreaLabelFloodFill($, bitmaps, avoidBaseMark, markIndex) {
function placeAreaLabelFloodFill ($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height,
bm0 = bitmaps[0], // where labels have been placed
bm1 = bitmaps[1], // area outlines
bm2 = $.bitmap(); // flood-fill visitations
height = $.height,
bm0 = bitmaps[0],
// where labels have been placed
bm1 = bitmaps[1],
// area outlines
bm2 = $.bitmap(); // flood-fill visitations
// try to place a label within an input area mark
return function(d) {
const items = d.datum.datum.items[markIndex].items, // area points
n = items.length, // number of points
textHeight = d.datum.fontSize, // label width
textWidth = vegaScenegraph.textMetrics.width(d.datum, d.datum.text), // label height
stack = []; // flood fill stack
return function (d) {
const items = d.datum.datum.items[markIndex].items,
// area points
n = items.length,
// number of points
textHeight = d.datum.fontSize,
// label width
textWidth = vegaScenegraph.textMetrics.width(d.datum, d.datum.text),
// label height
stack = []; // flood fill stack
let maxSize = avoidBaseMark ? textHeight : 0,

@@ -468,31 +504,39 @@ labelPlaced = false,

maxAreaWidth = 0,
x1, x2, y1, y2, x, y, _x, _y, lo, hi, mid, areaWidth;
x1,
x2,
y1,
y2,
x,
y,
_x,
_y,
lo,
hi,
mid,
areaWidth; // for each area sample point
// for each area sample point
for (let i=0; i<n; ++i) {
for (let i = 0; i < n; ++i) {
x1 = items[i].x;
y1 = items[i].y;
x2 = items[i].x2 === undefined ? x1 : items[i].x2;
y2 = items[i].y2 === undefined ? y1 : items[i].y2;
y2 = items[i].y2 === undefined ? y1 : items[i].y2; // add scaled center point to stack
// add scaled center point to stack
stack.push([$((x1 + x2) / 2), $((y1 + y2) / 2)]);
stack.push([$((x1 + x2) / 2), $((y1 + y2) / 2)]); // perform flood fill, visit points
// perform flood fill, visit points
while (stack.length) {
[_x, _y] = stack.pop();
[_x, _y] = stack.pop(); // exit if point already marked
// exit if point already marked
if (bm0.get(_x, _y) || bm1.get(_x, _y) || bm2.get(_x, _y)) continue;
if (bm0.get(_x, _y) || bm1.get(_x, _y) || bm2.get(_x, _y)) continue; // mark point in flood fill bitmap
// add search points for all (in bound) directions
// mark point in flood fill bitmap
// add search points for all (in bound) directions
bm2.set(_x, _y);
for (let j=0; j<4; ++j) {
for (let j = 0; j < 4; ++j) {
x = _x + X_DIR[j];
y = _y + Y_DIR[j];
if (!bm2.outOfBounds(x, y, x, y)) stack.push([x, y]);
}
} // unscale point back to x, y space
// unscale point back to x, y space
x = $.invert(_x);

@@ -503,7 +547,3 @@ y = $.invert(_y);

if (
!outOfBounds(x, y, textWidth, textHeight, width, height) &&
!collision($, x, y, textHeight, textWidth, lo, bm0, bm1) &&
!collision($, x, y, textHeight, textWidth, textHeight, bm0, null)
) {
if (!outOfBounds(x, y, textWidth, textHeight, width, height) && !collision($, x, y, textHeight, textWidth, lo, bm0, bm1) && !collision($, x, y, textHeight, textWidth, textHeight, bm0, null)) {
// if the label fits at the current sample point,

@@ -513,2 +553,3 @@ // perform binary search to find the largest font size that fits

mid = (lo + hi) / 2;
if (collision($, x, y, textHeight, textWidth, mid, bm0, bm1)) {

@@ -519,4 +560,5 @@ hi = mid;

}
}
// place label if current lower bound exceeds prior max font size
} // place label if current lower bound exceeds prior max font size
if (lo > maxSize) {

@@ -529,6 +571,6 @@ d.x = x;

}
}
} // place label at slice center if not placed through other means
// and if we're not avoiding overlap with other areas
// place label at slice center if not placed through other means
// and if we're not avoiding overlap with other areas
if (!labelPlaced && !avoidBaseMark) {

@@ -538,10 +580,5 @@ // one span is zero, hence we can add

x = (x1 + x2) / 2;
y = (y1 + y2) / 2;
y = (y1 + y2) / 2; // place label if it fits and improves the max area width
// place label if it fits and improves the max area width
if (
areaWidth >= maxAreaWidth &&
!outOfBounds(x, y, textWidth, textHeight, width, height) &&
!collision($, x, y, textHeight, textWidth, textHeight, bm0, null)
) {
if (areaWidth >= maxAreaWidth && !outOfBounds(x, y, textWidth, textHeight, width, height) && !collision($, x, y, textHeight, textWidth, textHeight, bm0, null)) {
maxAreaWidth = areaWidth;

@@ -553,5 +590,5 @@ d.x = x;

}
}
} // record current label placement information, update label bitmap
// record current label placement information, update label bitmap
if (labelPlaced || labelPlaced2) {

@@ -572,4 +609,3 @@ x = textWidth / 2;

Baselines = ['bottom', 'middle', 'top'];
function placeMarkLabel($, bitmaps, anchors, offsets) {
function placeMarkLabel ($, bitmaps, anchors, offsets) {
const width = $.width,

@@ -580,8 +616,6 @@ height = $.height,

n = offsets.length;
return function(d) {
return function (d) {
const boundary = d.boundary,
textHeight = d.datum.fontSize;
textHeight = d.datum.fontSize; // can not be placed if the mark is not visible in the graph bound
// can not be placed if the mark is not visible in the graph bound
if (boundary[2] < 0 || boundary[5] < 0 || boundary[0] > width || boundary[3] > height) {

@@ -592,20 +626,29 @@ return false;

let textWidth = 0,
dx, dy, isInside, sizeFactor, insideFactor,
x1, x2, y1, y2, xc, yc,
_x1, _x2, _y1, _y2;
dx,
dy,
isInside,
sizeFactor,
insideFactor,
x1,
x2,
y1,
y2,
xc,
yc,
_x1,
_x2,
_y1,
_y2; // for each anchor and offset
// for each anchor and offset
for (let i=0; i<n; ++i) {
for (let i = 0; i < n; ++i) {
dx = (anchors[i] & 0x3) - 1;
dy = ((anchors[i] >>> 0x2) & 0x3) - 1;
isInside = (dx === 0 && dy === 0) || offsets[i] < 0;
dy = (anchors[i] >>> 0x2 & 0x3) - 1;
isInside = dx === 0 && dy === 0 || offsets[i] < 0;
sizeFactor = dx && dy ? Math.SQRT1_2 : 1;
insideFactor = offsets[i] < 0 ? -1 : 1;
x1 = boundary[1 + dx] + offsets[i] * dx * sizeFactor;
yc = boundary[4 + dy] + (insideFactor * textHeight * dy) / 2 + offsets[i] * dy * sizeFactor;
yc = boundary[4 + dy] + insideFactor * textHeight * dy / 2 + offsets[i] * dy * sizeFactor;
y1 = yc - textHeight / 2;
y2 = yc + textHeight / 2;
_x1 = $(x1);

@@ -626,6 +669,5 @@ _y1 = $(y1);

xc = x1 + (insideFactor * textWidth * dx) / 2;
xc = x1 + insideFactor * textWidth * dx / 2;
x1 = xc - textWidth / 2;
x2 = xc + textWidth / 2;
_x1 = $(x1);

@@ -638,6 +680,4 @@ _x2 = $(x2);

d.y = !dy ? yc : dy * insideFactor < 0 ? y2 : y1;
d.align = Aligns[dx * insideFactor + 1];
d.baseline = Baselines[dy * insideFactor + 1];
bm0.setRange(_x1, _y1, _x2, _y2);

@@ -650,40 +690,30 @@ return true;

};
}
} // Test if a label with the given dimensions can be added without overlap
// Test if a label with the given dimensions can be added without overlap
function test(_x1, _x2, _y1, _y2, bm0, bm1, x1, x2, y1, y2, boundary, isInside) {
return !(
bm0.outOfBounds(_x1, _y1, _x2, _y2) ||
(isInside && bm1
? bm1.getRange(_x1, _y1, _x2, _y2) || !isInMarkBound(x1, y1, x2, y2, boundary)
: bm0.getRange(_x1, _y1, _x2, _y2))
);
return !(bm0.outOfBounds(_x1, _y1, _x2, _y2) || (isInside && bm1 ? bm1.getRange(_x1, _y1, _x2, _y2) || !isInMarkBound(x1, y1, x2, y2, boundary) : bm0.getRange(_x1, _y1, _x2, _y2)));
}
function isInMarkBound(x1, y1, x2, y2, boundary) {
return boundary[0] <= x1 && x2 <= boundary[2]
&& boundary[3] <= y1 && y2 <= boundary[5];
return boundary[0] <= x1 && x2 <= boundary[2] && boundary[3] <= y1 && y2 <= boundary[5];
}
// 8-bit representation of anchors
const TOP = 0x0,
const TOP = 0x0,
MIDDLE = 0x4,
BOTTOM = 0x8,
LEFT = 0x0,
LEFT = 0x0,
CENTER = 0x1,
RIGHT = 0x2;
RIGHT = 0x2; // Mapping from text anchor to number representation
// Mapping from text anchor to number representation
const anchorCode = {
'top-left': TOP + LEFT,
'top': TOP + CENTER,
'top-right': TOP + RIGHT,
'left': MIDDLE + LEFT,
'middle': MIDDLE + CENTER,
'right': MIDDLE + RIGHT,
'bottom-left': BOTTOM + LEFT,
'bottom': BOTTOM + CENTER,
'top-left': TOP + LEFT,
'top': TOP + CENTER,
'top-right': TOP + RIGHT,
'left': MIDDLE + LEFT,
'middle': MIDDLE + CENTER,
'right': MIDDLE + RIGHT,
'bottom-left': BOTTOM + LEFT,
'bottom': BOTTOM + CENTER,
'bottom-right': BOTTOM + RIGHT
};
const placeAreaLabel = {

@@ -694,9 +724,5 @@ 'naive': placeAreaLabelNaive,

};
function labelLayout(texts, size, compare, offset, anchor,
avoidMarks, avoidBaseMark, lineAnchor, markIndex, padding, method)
{
function labelLayout (texts, size, compare, offset, anchor, avoidMarks, avoidBaseMark, lineAnchor, markIndex, padding, method) {
// early exit for empty data
if (!texts.length) return texts;
const positions = Math.max(offset.length, anchor.length),

@@ -710,5 +736,4 @@ offsets = getOffsets(offset, positions),

$ = scaler(size[0], size[1], padding),
isNaiveGroupArea = isGroupArea && method === 'naive';
isNaiveGroupArea = isGroupArea && method === 'naive'; // prepare text mark data for placing
// prepare text mark data for placing
const data = texts.map(d => ({

@@ -723,4 +748,4 @@ datum: d,

}));
let bitmaps;
let bitmaps;
if (!isNaiveGroupArea) {

@@ -730,32 +755,27 @@ // sort labels in priority order, if comparator is provided

data.sort((a, b) => compare(a.datum, b.datum));
}
} // flag indicating if label can be placed inside its base mark
// flag indicating if label can be placed inside its base mark
let labelInside = false;
for (let i=0; i < anchors.length && !labelInside; ++i) {
for (let i = 0; i < anchors.length && !labelInside; ++i) {
// label inside if anchor is at center
// label inside if offset to be inside the mark bound
labelInside = anchors[i] === 0x5 || offsets[i] < 0;
}
} // extract data information from base mark when base mark is to be avoided
// base mark is implicitly avoided if it is a group area
// extract data information from base mark when base mark is to be avoided
// base mark is implicitly avoided if it is a group area
if (marktype && (avoidBaseMark || isGroupArea)) {
avoidMarks = [texts.map(d => d.datum)].concat(avoidMarks);
}
} // generate bitmaps for layout calculation
// generate bitmaps for layout calculation
bitmaps = avoidMarks.length
? markBitmaps($, avoidMarks, labelInside, isGroupArea)
: baseBitmaps($, avoidBaseMark && data);
}
// generate label placement function
const place = isGroupArea
? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex)
: placeMarkLabel($, bitmaps, anchors, offsets);
bitmaps = avoidMarks.length ? markBitmaps($, avoidMarks, labelInside, isGroupArea) : baseBitmaps($, avoidBaseMark && data);
} // generate label placement function
// place all labels
const place = isGroupArea ? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex) : placeMarkLabel($, bitmaps, anchors, offsets); // place all labels
data.forEach(d => d.opacity = +place(d));
return data;

@@ -767,4 +787,7 @@ }

n = _.length;
for (let i=0; i<n; ++i) offsets[i] = _[i] || 0;
for (let i=n; i<count; ++i) offsets[i] = offsets[n - 1];
for (let i = 0; i < n; ++i) offsets[i] = _[i] || 0;
for (let i = n; i < count; ++i) offsets[i] = offsets[n - 1];
return offsets;

@@ -776,4 +799,7 @@ }

n = _.length;
for (let i=0; i<n; ++i) anchors[i] |= anchorCode[_[i]];
for (let i=n; i<count; ++i) anchors[i] = anchors[n - 1];
for (let i = 0; i < n; ++i) anchors[i] |= anchorCode[_[i]];
for (let i = n; i < count; ++i) anchors[i] = anchors[n - 1];
return anchors;

@@ -785,3 +811,2 @@ }

}
/**

@@ -794,2 +819,4 @@ * Factory function for function for getting base mark boundary, depending

*/
function markBoundary(marktype, grouptype, lineAnchor, markIndex) {

@@ -800,18 +827,13 @@ const xy = d => [d.x, d.x, d.x, d.y, d.y, d.y];

return xy; // no reactive geometry
}
else if (marktype === 'line' || marktype === 'area') {
} else if (marktype === 'line' || marktype === 'area') {
return d => xy(d.datum);
}
else if (grouptype === 'line') {
} else if (grouptype === 'line') {
return d => {
const items = d.datum.items[markIndex].items;
return xy(items.length
? items[lineAnchor === 'start' ? 0 : items.length - 1]
: {x: NaN, y: NaN});
return xy(items.length ? items[lineAnchor === 'start' ? 0 : items.length - 1] : {
x: NaN,
y: NaN
});
};
}
else {
} else {
return d => {

@@ -824,21 +846,4 @@ const b = d.datum.bounds;

const Output = [
'x',
'y',
'opacity',
'align',
'baseline'
];
const Anchors = [
'top-left',
'left',
'bottom-left',
'top',
'bottom',
'top-right',
'right',
'bottom-right'
];
const Output = ['x', 'y', 'opacity', 'align', 'baseline'];
const Anchors = ['top-left', 'left', 'bottom-left', 'top', 'bottom', 'top-right', 'right', 'bottom-right'];
/**

@@ -870,24 +875,63 @@ * Compute text label layout to annotate marks.

*/
function Label(params) {
vegaDataflow.Transform.call(this, null, params);
}
Label.Definition = {
type: 'Label',
metadata: { modifies: true },
params: [
{ name: 'size', type: 'number', array: true, length: 2, required: true },
{ name: 'sort', type: 'compare' },
{ name: 'anchor', type: 'string', array: true, default: Anchors },
{ name: 'offset', type: 'number', array: true, default: [1] },
{ name: 'padding', type: 'number', default: 0 },
{ name: 'lineAnchor', type: 'string', values: ['start', 'end'], default: 'end' },
{ name: 'markIndex', type: 'number', default: 0 },
{ name: 'avoidBaseMark', type: 'boolean', default: true },
{ name: 'avoidMarks', type: 'data', array: true },
{ name: 'method', type: 'string', default: 'naive'},
{ name: 'as', type: 'string', array: true, length: Output.length, default: Output }
]
metadata: {
modifies: true
},
params: [{
name: 'size',
type: 'number',
array: true,
length: 2,
required: true
}, {
name: 'sort',
type: 'compare'
}, {
name: 'anchor',
type: 'string',
array: true,
default: Anchors
}, {
name: 'offset',
type: 'number',
array: true,
default: [1]
}, {
name: 'padding',
type: 'number',
default: 0
}, {
name: 'lineAnchor',
type: 'string',
values: ['start', 'end'],
default: 'end'
}, {
name: 'markIndex',
type: 'number',
default: 0
}, {
name: 'avoidBaseMark',
type: 'boolean',
default: true
}, {
name: 'avoidMarks',
type: 'data',
array: true
}, {
name: 'method',
type: 'string',
default: 'naive'
}, {
name: 'as',
type: 'string',
array: true,
length: Output.length,
default: Output
}]
};
vegaUtil.inherits(Label, vegaDataflow.Transform, {

@@ -901,3 +945,5 @@ transform(_, pulse) {

const mod = _.modified();
if (!(mod || pulse.changed(pulse.ADD_REM) || modp('sort'))) return;
if (!_.size || _.size.length !== 2) {

@@ -907,18 +953,5 @@ vegaUtil.error('Size parameter should be specified as a [width, height] array.');

const as = _.as || Output;
const as = _.as || Output; // run label layout
// run label layout
labelLayout(
pulse.materialize(pulse.SOURCE).source,
_.size,
_.sort,
vegaUtil.array(_.offset || 1),
vegaUtil.array(_.anchor || Anchors),
_.avoidMarks || [],
_.avoidBaseMark === false ? false : true,
_.lineAnchor || 'end',
_.markIndex || 0,
_.padding || 0,
_.method || 'naive'
).forEach(l => {
labelLayout(pulse.materialize(pulse.SOURCE).source, _.size, _.sort, vegaUtil.array(_.offset || 1), vegaUtil.array(_.anchor || Anchors), _.avoidMarks || [], _.avoidBaseMark === false ? false : true, _.lineAnchor || 'end', _.markIndex || 0, _.padding || 0, _.method || 'naive').forEach(l => {
// write layout results to data stream

@@ -932,5 +965,5 @@ const t = l.datum;

});
return pulse.reflow(mod).modifies(as);
}
});

@@ -937,0 +970,0 @@

@@ -1,1 +0,2 @@

!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("vega-canvas"),require("vega-dataflow"),require("vega-scenegraph"),require("vega-util")):"function"==typeof define&&define.amd?define(["exports","vega-canvas","vega-dataflow","vega-scenegraph","vega-util"],e):e(((t="undefined"!=typeof globalThis?globalThis:t||self).vega=t.vega||{},t.vega.transforms={}),t.vega,t.vega,t.vega,t.vega)}(this,(function(t,e,n,r,a){"use strict";function i(t,n,a,i){const u=t.width,s=t.height,f=a||i,l=e.canvas(u,s).getContext("2d");n.forEach(t=>function t(e,n,a){if(!n.length)return;const i=n[0].mark.marktype;"group"===i?n.forEach(n=>{n.items.forEach(n=>t(e,n.items,a))}):r.Marks[i].draw(e,{items:a?n.map(o):n})}(l,t,f));const d=new Uint32Array(l.getImageData(0,0,u,s).data.buffer),c=t.bitmap(),m=f&&t.bitmap();let g,h,y,p,x;for(h=0;h<s;++h)for(g=0;g<u;++g)x=4278190080&d[h*u+g],x&&(y=t(g),p=t(h),i||c.set(y,p),f&&268435456^x&&m.set(y,p));return[c,m]}function o(t){const e=n.rederive(t,{});return e.stroke&&(e.strokeOpacity=1),e.fill&&(e.fillOpacity=.0625,e.stroke="#000",e.strokeOpacity=1,e.strokeWidth=2),e}const u=31,s=new Uint32Array(33),f=new Uint32Array(33);f[0]=0,s[0]=~f[0];for(let t=1;t<=32;++t)f[t]=f[t-1]<<1|1,s[t]=~f[t];function l(t,e,n){const r=Math.max(1,Math.sqrt(t*e/1e6)),a=~~((t+2*n+r)/r),i=~~((e+2*n+r)/r),o=t=>~~((t+n)/r);return o.invert=t=>t*r-n,o.bitmap=()=>function(t,e){const n=new Uint32Array(~~((t*e+32)/32));function r(t,e){n[t]|=e}function a(t,e){n[t]&=e}return{array:n,get:(e,r)=>{const a=r*t+e;return n[a>>>5]&1<<(a&u)},set:(e,n)=>{const a=n*t+e;r(a>>>5,1<<(a&u))},clear:(e,n)=>{const r=n*t+e;a(r>>>5,~(1<<(r&u)))},getRange:(e,r,a,i)=>{let o,l,d,c,m=i;for(;m>=r;--m)if(o=m*t+e,l=m*t+a,d=o>>>5,c=l>>>5,d===c){if(n[d]&s[o&u]&f[1+(l&u)])return!0}else{if(n[d]&s[o&u])return!0;if(n[c]&f[1+(l&u)])return!0;for(let t=d+1;t<c;++t)if(n[t])return!0}return!1},setRange:(e,n,a,i)=>{let o,l,d,c,m;for(;n<=i;++n)if(o=n*t+e,l=n*t+a,d=o>>>5,c=l>>>5,d===c)r(d,s[o&u]&f[1+(l&u)]);else for(r(d,s[o&u]),r(c,f[1+(l&u)]),m=d+1;m<c;++m)r(m,4294967295)},clearRange:(e,n,r,i)=>{let o,l,d,c,m;for(;n<=i;++n)if(o=n*t+e,l=n*t+r,d=o>>>5,c=l>>>5,d===c)a(d,f[o&u]|s[1+(l&u)]);else for(a(d,f[o&u]),a(c,s[1+(l&u)]),m=d+1;m<c;++m)a(m,0)},outOfBounds:(n,r,a,i)=>n<0||r<0||i>=e||a>=t}}(a,i),o.ratio=r,o.padding=n,o.width=t,o.height=e,o}function d(t,e,n,r,a,i){let o=n/2;return t-o<0||t+o>a||e-(o=r/2)<0||e+o>i}function c(t,e,n,r,a,i,o,u){const s=a*i/(2*r),f=t(e-s),l=t(e+s),d=t(n-(i/=2)),c=t(n+i);return o.outOfBounds(f,d,l,c)||o.getRange(f,d,l,c)||u&&u.getRange(f,d,l,c)}const m=[-1,-1,1,1],g=[-1,1,-1,1];const h=["right","center","left"],y=["bottom","middle","top"];function p(t,e,n,r,a,i,o,u,s,f,l,d){return!(a.outOfBounds(t,n,e,r)||(d&&i?i.getRange(t,n,e,r)||!function(t,e,n,r,a){return a[0]<=t&&n<=a[2]&&a[3]<=e&&r<=a[5]}(o,s,u,f,l):a.getRange(t,n,e,r)))}const x={"top-left":0,top:1,"top-right":2,left:4,middle:5,right:6,"bottom-left":8,bottom:9,"bottom-right":10},v={naive:function(t,e,n,a){const i=t.width,o=t.height;return function(t){const e=t.datum.datum.items[a].items,n=e.length,u=t.datum.fontSize,s=r.textMetrics.width(t.datum,t.datum.text);let f,l,d,c,m,g,h,y=0;for(let r=0;r<n;++r)f=e[r].x,d=e[r].y,l=void 0===e[r].x2?f:e[r].x2,c=void 0===e[r].y2?d:e[r].y2,m=(f+l)/2,g=(d+c)/2,h=Math.abs(l-f+c-d),h>=y&&(y=h,t.x=m,t.y=g);return m=s/2,g=u/2,f=t.x-m,l=t.x+m,d=t.y-g,c=t.y+g,t.align="center",f<0&&l<=i?t.align="left":0<=f&&i<l&&(t.align="right"),t.baseline="middle",d<0&&c<=o?t.baseline="top":0<=d&&o<c&&(t.baseline="bottom"),!0}},"reduced-search":function(t,e,n,a){const i=t.width,o=t.height,u=e[0],s=e[1];function f(e,n,r,a,f){const l=t.invert(e),m=t.invert(n);let g,h=r,y=o;if(!d(l,m,a,f,i,o)&&!c(t,l,m,f,a,h,u,s)&&!c(t,l,m,f,a,f,u,null)){for(;y-h>=1;)g=(h+y)/2,c(t,l,m,f,a,g,u,s)?y=g:h=g;if(h>r)return[l,m,h,!0]}}return function(e){const s=e.datum.datum.items[a].items,l=s.length,m=e.datum.fontSize,g=r.textMetrics.width(e.datum,e.datum.text);let h,y,p,x,v,b,w,k,M,R,z,A,O,E,S,q,B,T=n?m:0,U=!1,D=!1,I=0;for(let r=0;r<l;++r){for(h=s[r].x,p=s[r].y,y=void 0===s[r].x2?h:s[r].x2,x=void 0===s[r].y2?p:s[r].y2,h>y&&(B=h,h=y,y=B),p>x&&(B=p,p=x,x=B),M=t(h),z=t(y),R=~~((M+z)/2),A=t(p),E=t(x),O=~~((A+E)/2),w=R;w>=M;--w)for(k=O;k>=A;--k)q=f(w,k,T,g,m),q&&([e.x,e.y,T,U]=q);for(w=R;w<=z;++w)for(k=O;k<=E;++k)q=f(w,k,T,g,m),q&&([e.x,e.y,T,U]=q);U||n||(S=Math.abs(y-h+x-p),v=(h+y)/2,b=(p+x)/2,S>=I&&!d(v,b,g,m,i,o)&&!c(t,v,b,m,g,m,u,null)&&(I=S,e.x=v,e.y=b,D=!0))}return!(!U&&!D)&&(v=g/2,b=m/2,u.setRange(t(e.x-v),t(e.y-b),t(e.x+v),t(e.y+b)),e.align="center",e.baseline="middle",!0)}},floodfill:function(t,e,n,a){const i=t.width,o=t.height,u=e[0],s=e[1],f=t.bitmap();return function(e){const l=e.datum.datum.items[a].items,h=l.length,y=e.datum.fontSize,p=r.textMetrics.width(e.datum,e.datum.text),x=[];let v,b,w,k,M,R,z,A,O,E,S,q,B=n?y:0,T=!1,U=!1,D=0;for(let r=0;r<h;++r){for(v=l[r].x,w=l[r].y,b=void 0===l[r].x2?v:l[r].x2,k=void 0===l[r].y2?w:l[r].y2,x.push([t((v+b)/2),t((w+k)/2)]);x.length;)if([z,A]=x.pop(),!(u.get(z,A)||s.get(z,A)||f.get(z,A))){f.set(z,A);for(let t=0;t<4;++t)M=z+m[t],R=A+g[t],f.outOfBounds(M,R,M,R)||x.push([M,R]);if(M=t.invert(z),R=t.invert(A),O=B,E=o,!d(M,R,p,y,i,o)&&!c(t,M,R,y,p,O,u,s)&&!c(t,M,R,y,p,y,u,null)){for(;E-O>=1;)S=(O+E)/2,c(t,M,R,y,p,S,u,s)?E=S:O=S;O>B&&(e.x=M,e.y=R,B=O,T=!0)}}T||n||(q=Math.abs(b-v+k-w),M=(v+b)/2,R=(w+k)/2,q>=D&&!d(M,R,p,y,i,o)&&!c(t,M,R,y,p,y,u,null)&&(D=q,e.x=M,e.y=R,U=!0))}return!(!T&&!U)&&(M=p/2,R=y/2,u.setRange(t(e.x-M),t(e.y-R),t(e.x+M),t(e.y+R)),e.align="center",e.baseline="middle",!0)}}};function b(t,e,n,a,o,u,s,f,d,c,m){if(!t.length)return t;const g=Math.max(a.length,o.length),b=function(t,e){const n=new Float64Array(e),r=t.length;for(let e=0;e<r;++e)n[e]=t[e]||0;for(let t=r;t<e;++t)n[t]=n[r-1];return n}(a,g),w=function(t,e){const n=new Int8Array(e),r=t.length;for(let e=0;e<r;++e)n[e]|=x[t[e]];for(let t=r;t<e;++t)n[t]=n[r-1];return n}(o,g),k=(E=t[0].datum)&&E.mark&&E.mark.marktype,M="group"===k&&t[0].datum.items[d].marktype,R="area"===M,z=function(t,e,n,r){const a=t=>[t.x,t.x,t.x,t.y,t.y,t.y];return t?"line"===t||"area"===t?t=>a(t.datum):"line"===e?t=>{const e=t.datum.items[r].items;return a(e.length?e["start"===n?0:e.length-1]:{x:NaN,y:NaN})}:t=>{const e=t.datum.bounds;return[e.x1,(e.x1+e.x2)/2,e.x2,e.y1,(e.y1+e.y2)/2,e.y2]}:a}(k,M,f,d),A=l(e[0],e[1],c),O=R&&"naive"===m;var E;const S=t.map(t=>({datum:t,opacity:0,x:void 0,y:void 0,align:void 0,baseline:void 0,boundary:z(t)}));let q;if(!O){n&&S.sort((t,e)=>n(t.datum,e.datum));let e=!1;for(let t=0;t<w.length&&!e;++t)e=5===w[t]||b[t]<0;k&&(s||R)&&(u=[t.map(t=>t.datum)].concat(u)),q=u.length?i(A,u,e,R):function(t,e){const n=t.bitmap();return(e||[]).forEach(e=>n.set(t(e.boundary[0]),t(e.boundary[3]))),[n,void 0]}(A,s&&S)}const B=R?v[m](A,q,s,d):function(t,e,n,a){const i=t.width,o=t.height,u=e[0],s=e[1],f=a.length;return function(e){const l=e.boundary,d=e.datum.fontSize;if(l[2]<0||l[5]<0||l[0]>i||l[3]>o)return!1;let c,m,g,x,v,b,w,k,M,R,z,A,O,E,S,q=0;for(let i=0;i<f;++i){if(c=(3&n[i])-1,m=(n[i]>>>2&3)-1,g=0===c&&0===m||a[i]<0,x=c&&m?Math.SQRT1_2:1,v=a[i]<0?-1:1,b=l[1+c]+a[i]*c*x,z=l[4+m]+v*d*m/2+a[i]*m*x,k=z-d/2,M=z+d/2,A=t(b),E=t(k),S=t(M),!q){if(!p(A,A,E,S,u,s,b,b,k,M,l,g))continue;q=r.textMetrics.width(e.datum,e.datum.text)}if(R=b+v*q*c/2,b=R-q/2,w=R+q/2,A=t(b),O=t(w),p(A,O,E,S,u,s,b,w,k,M,l,g))return e.x=c?c*v<0?w:b:R,e.y=m?m*v<0?M:k:z,e.align=h[c*v+1],e.baseline=y[m*v+1],u.setRange(A,E,O,S),!0}return!1}}(A,q,w,b);return S.forEach(t=>t.opacity=+B(t)),S}const w=["x","y","opacity","align","baseline"],k=["top-left","left","bottom-left","top","bottom","top-right","right","bottom-right"];function M(t){n.Transform.call(this,null,t)}M.Definition={type:"Label",metadata:{modifies:!0},params:[{name:"size",type:"number",array:!0,length:2,required:!0},{name:"sort",type:"compare"},{name:"anchor",type:"string",array:!0,default:k},{name:"offset",type:"number",array:!0,default:[1]},{name:"padding",type:"number",default:0},{name:"lineAnchor",type:"string",values:["start","end"],default:"end"},{name:"markIndex",type:"number",default:0},{name:"avoidBaseMark",type:"boolean",default:!0},{name:"avoidMarks",type:"data",array:!0},{name:"method",type:"string",default:"naive"},{name:"as",type:"string",array:!0,length:w.length,default:w}]},a.inherits(M,n.Transform,{transform(t,e){const n=t.modified();if(!(n||e.changed(e.ADD_REM)||function(n){const r=t[n];return a.isFunction(r)&&e.modified(r.fields)}("sort")))return;t.size&&2===t.size.length||a.error("Size parameter should be specified as a [width, height] array.");const r=t.as||w;return b(e.materialize(e.SOURCE).source,t.size,t.sort,a.array(t.offset||1),a.array(t.anchor||k),t.avoidMarks||[],!1!==t.avoidBaseMark,t.lineAnchor||"end",t.markIndex||0,t.padding||0,t.method||"naive").forEach(t=>{const e=t.datum;e[r[0]]=t.x,e[r[1]]=t.y,e[r[2]]=t.opacity,e[r[3]]=t.align,e[r[4]]=t.baseline}),e.reflow(n).modifies(r)}}),t.label=M,Object.defineProperty(t,"__esModule",{value:!0})}));
this.vega=this.vega||{},this.vega.transforms=function(t,e,n,r,a){"use strict";function i(t,n,r,a){const i=t.width,s=t.height,u=r||a,f=e.canvas(i,s).getContext("2d");n.forEach(t=>o(f,t,u));const l=new Uint32Array(f.getImageData(0,0,i,s).data.buffer),d=t.bitmap(),c=u&&t.bitmap();let m,g,h,y,p;for(g=0;g<s;++g)for(m=0;m<i;++m)p=4278190080&l[g*i+m],p&&(h=t(m),y=t(g),a||d.set(h,y),u&&268435456^p&&c.set(h,y));return[d,c]}function o(t,e,n){if(!e.length)return;const a=e[0].mark.marktype;"group"===a?e.forEach(e=>{e.items.forEach(e=>o(t,e.items,n))}):r.Marks[a].draw(t,{items:n?e.map(s):e})}function s(t){const e=n.rederive(t,{});return e.stroke&&(e.strokeOpacity=1),e.fill&&(e.fillOpacity=.0625,e.stroke="#000",e.strokeOpacity=1,e.strokeWidth=2),e}const u=31,f=new Uint32Array(33),l=new Uint32Array(33);l[0]=0,f[0]=~l[0];for(let t=1;t<=32;++t)l[t]=l[t-1]<<1|1,f[t]=~l[t];function d(t,e,n){const r=Math.max(1,Math.sqrt(t*e/1e6)),a=~~((t+2*n+r)/r),i=~~((e+2*n+r)/r),o=t=>~~((t+n)/r);return o.invert=t=>t*r-n,o.bitmap=()=>function(t,e){const n=new Uint32Array(~~((t*e+32)/32));function r(t,e){n[t]|=e}function a(t,e){n[t]&=e}return{array:n,get:(e,r)=>{const a=r*t+e;return n[a>>>5]&1<<(a&u)},set:(e,n)=>{const a=n*t+e;r(a>>>5,1<<(a&u))},clear:(e,n)=>{const r=n*t+e;a(r>>>5,~(1<<(r&u)))},getRange:(e,r,a,i)=>{let o,s,d,c,m=i;for(;m>=r;--m)if(o=m*t+e,s=m*t+a,d=o>>>5,c=s>>>5,d===c){if(n[d]&f[o&u]&l[1+(s&u)])return!0}else{if(n[d]&f[o&u])return!0;if(n[c]&l[1+(s&u)])return!0;for(let t=d+1;t<c;++t)if(n[t])return!0}return!1},setRange:(e,n,a,i)=>{let o,s,d,c,m;for(;n<=i;++n)if(o=n*t+e,s=n*t+a,d=o>>>5,c=s>>>5,d===c)r(d,f[o&u]&l[1+(s&u)]);else for(r(d,f[o&u]),r(c,l[1+(s&u)]),m=d+1;m<c;++m)r(m,4294967295)},clearRange:(e,n,r,i)=>{let o,s,d,c,m;for(;n<=i;++n)if(o=n*t+e,s=n*t+r,d=o>>>5,c=s>>>5,d===c)a(d,l[o&u]|f[1+(s&u)]);else for(a(d,l[o&u]),a(c,f[1+(s&u)]),m=d+1;m<c;++m)a(m,0)},outOfBounds:(n,r,a,i)=>n<0||r<0||i>=e||a>=t}}(a,i),o.ratio=r,o.padding=n,o.width=t,o.height=e,o}function c(t,e,n,r,a,i){let o=n/2;return t-o<0||t+o>a||e-(o=r/2)<0||e+o>i}function m(t,e,n,r,a,i,o,s){const u=a*i/(2*r),f=t(e-u),l=t(e+u),d=t(n-(i/=2)),c=t(n+i);return o.outOfBounds(f,d,l,c)||o.getRange(f,d,l,c)||s&&s.getRange(f,d,l,c)}const g=[-1,-1,1,1],h=[-1,1,-1,1];const y=["right","center","left"],p=["bottom","middle","top"];function x(t,e,n,r,a,i,o,s,u,f,l,d){return!(a.outOfBounds(t,n,e,r)||(d&&i?i.getRange(t,n,e,r)||!function(t,e,n,r,a){return a[0]<=t&&n<=a[2]&&a[3]<=e&&r<=a[5]}(o,u,s,f,l):a.getRange(t,n,e,r)))}const b={"top-left":0,top:1,"top-right":2,left:4,middle:5,right:6,"bottom-left":8,bottom:9,"bottom-right":10},v={naive:function(t,e,n,a){const i=t.width,o=t.height;return function(t){const e=t.datum.datum.items[a].items,n=e.length,s=t.datum.fontSize,u=r.textMetrics.width(t.datum,t.datum.text);let f,l,d,c,m,g,h,y=0;for(let r=0;r<n;++r)f=e[r].x,d=e[r].y,l=void 0===e[r].x2?f:e[r].x2,c=void 0===e[r].y2?d:e[r].y2,m=(f+l)/2,g=(d+c)/2,h=Math.abs(l-f+c-d),h>=y&&(y=h,t.x=m,t.y=g);return m=u/2,g=s/2,f=t.x-m,l=t.x+m,d=t.y-g,c=t.y+g,t.align="center",f<0&&l<=i?t.align="left":0<=f&&i<l&&(t.align="right"),t.baseline="middle",d<0&&c<=o?t.baseline="top":0<=d&&o<c&&(t.baseline="bottom"),!0}},"reduced-search":function(t,e,n,a){const i=t.width,o=t.height,s=e[0],u=e[1];function f(e,n,r,a,f){const l=t.invert(e),d=t.invert(n);let g,h=r,y=o;if(!c(l,d,a,f,i,o)&&!m(t,l,d,f,a,h,s,u)&&!m(t,l,d,f,a,f,s,null)){for(;y-h>=1;)g=(h+y)/2,m(t,l,d,f,a,g,s,u)?y=g:h=g;if(h>r)return[l,d,h,!0]}}return function(e){const u=e.datum.datum.items[a].items,l=u.length,d=e.datum.fontSize,g=r.textMetrics.width(e.datum,e.datum.text);let h,y,p,x,b,v,w,k,M,R,z,A,E,O,S,B,U,D=n?d:0,I=!1,N=!1,T=0;for(let r=0;r<l;++r){for(h=u[r].x,p=u[r].y,y=void 0===u[r].x2?h:u[r].x2,x=void 0===u[r].y2?p:u[r].y2,h>y&&(U=h,h=y,y=U),p>x&&(U=p,p=x,x=U),M=t(h),z=t(y),R=~~((M+z)/2),A=t(p),O=t(x),E=~~((A+O)/2),w=R;w>=M;--w)for(k=E;k>=A;--k)B=f(w,k,D,g,d),B&&([e.x,e.y,D,I]=B);for(w=R;w<=z;++w)for(k=E;k<=O;++k)B=f(w,k,D,g,d),B&&([e.x,e.y,D,I]=B);I||n||(S=Math.abs(y-h+x-p),b=(h+y)/2,v=(p+x)/2,S>=T&&!c(b,v,g,d,i,o)&&!m(t,b,v,d,g,d,s,null)&&(T=S,e.x=b,e.y=v,N=!0))}return!(!I&&!N)&&(b=g/2,v=d/2,s.setRange(t(e.x-b),t(e.y-v),t(e.x+b),t(e.y+v)),e.align="center",e.baseline="middle",!0)}},floodfill:function(t,e,n,a){const i=t.width,o=t.height,s=e[0],u=e[1],f=t.bitmap();return function(e){const l=e.datum.datum.items[a].items,d=l.length,y=e.datum.fontSize,p=r.textMetrics.width(e.datum,e.datum.text),x=[];let b,v,w,k,M,R,z,A,E,O,S,B,U=n?y:0,D=!1,I=!1,N=0;for(let r=0;r<d;++r){for(b=l[r].x,w=l[r].y,v=void 0===l[r].x2?b:l[r].x2,k=void 0===l[r].y2?w:l[r].y2,x.push([t((b+v)/2),t((w+k)/2)]);x.length;)if([z,A]=x.pop(),!(s.get(z,A)||u.get(z,A)||f.get(z,A))){f.set(z,A);for(let t=0;t<4;++t)M=z+g[t],R=A+h[t],f.outOfBounds(M,R,M,R)||x.push([M,R]);if(M=t.invert(z),R=t.invert(A),E=U,O=o,!c(M,R,p,y,i,o)&&!m(t,M,R,y,p,E,s,u)&&!m(t,M,R,y,p,y,s,null)){for(;O-E>=1;)S=(E+O)/2,m(t,M,R,y,p,S,s,u)?O=S:E=S;E>U&&(e.x=M,e.y=R,U=E,D=!0)}}D||n||(B=Math.abs(v-b+k-w),M=(b+v)/2,R=(w+k)/2,B>=N&&!c(M,R,p,y,i,o)&&!m(t,M,R,y,p,y,s,null)&&(N=B,e.x=M,e.y=R,I=!0))}return!(!D&&!I)&&(M=p/2,R=y/2,s.setRange(t(e.x-M),t(e.y-R),t(e.x+M),t(e.y+R)),e.align="center",e.baseline="middle",!0)}}};function w(t,e,n,a,o,s,u,f,l,c,m){if(!t.length)return t;const g=Math.max(a.length,o.length),h=function(t,e){const n=new Float64Array(e),r=t.length;for(let e=0;e<r;++e)n[e]=t[e]||0;for(let t=r;t<e;++t)n[t]=n[r-1];return n}(a,g),w=function(t,e){const n=new Int8Array(e),r=t.length;for(let e=0;e<r;++e)n[e]|=b[t[e]];for(let t=r;t<e;++t)n[t]=n[r-1];return n}(o,g),k=(O=t[0].datum)&&O.mark&&O.mark.marktype,M="group"===k&&t[0].datum.items[l].marktype,R="area"===M,z=function(t,e,n,r){const a=t=>[t.x,t.x,t.x,t.y,t.y,t.y];return t?"line"===t||"area"===t?t=>a(t.datum):"line"===e?t=>{const e=t.datum.items[r].items;return a(e.length?e["start"===n?0:e.length-1]:{x:NaN,y:NaN})}:t=>{const e=t.datum.bounds;return[e.x1,(e.x1+e.x2)/2,e.x2,e.y1,(e.y1+e.y2)/2,e.y2]}:a}(k,M,f,l),A=d(e[0],e[1],c),E=R&&"naive"===m;var O;const S=t.map(t=>({datum:t,opacity:0,x:void 0,y:void 0,align:void 0,baseline:void 0,boundary:z(t)}));let B;if(!E){n&&S.sort((t,e)=>n(t.datum,e.datum));let e=!1;for(let t=0;t<w.length&&!e;++t)e=5===w[t]||h[t]<0;k&&(u||R)&&(s=[t.map(t=>t.datum)].concat(s)),B=s.length?i(A,s,e,R):function(t,e){const n=t.bitmap();return(e||[]).forEach(e=>n.set(t(e.boundary[0]),t(e.boundary[3]))),[n,void 0]}(A,u&&S)}const U=R?v[m](A,B,u,l):function(t,e,n,a){const i=t.width,o=t.height,s=e[0],u=e[1],f=a.length;return function(e){const l=e.boundary,d=e.datum.fontSize;if(l[2]<0||l[5]<0||l[0]>i||l[3]>o)return!1;let c,m,g,h,b,v,w,k,M,R,z,A,E,O,S,B=0;for(let i=0;i<f;++i){if(c=(3&n[i])-1,m=(n[i]>>>2&3)-1,g=0===c&&0===m||a[i]<0,h=c&&m?Math.SQRT1_2:1,b=a[i]<0?-1:1,v=l[1+c]+a[i]*c*h,z=l[4+m]+b*d*m/2+a[i]*m*h,k=z-d/2,M=z+d/2,A=t(v),O=t(k),S=t(M),!B){if(!x(A,A,O,S,s,u,v,v,k,M,l,g))continue;B=r.textMetrics.width(e.datum,e.datum.text)}if(R=v+b*B*c/2,v=R-B/2,w=R+B/2,A=t(v),E=t(w),x(A,E,O,S,s,u,v,w,k,M,l,g))return e.x=c?c*b<0?w:v:R,e.y=m?m*b<0?M:k:z,e.align=y[c*b+1],e.baseline=p[m*b+1],s.setRange(A,O,E,S),!0}return!1}}(A,B,w,h);return S.forEach(t=>t.opacity=+U(t)),S}const k=["x","y","opacity","align","baseline"],M=["top-left","left","bottom-left","top","bottom","top-right","right","bottom-right"];function R(t){n.Transform.call(this,null,t)}return R.Definition={type:"Label",metadata:{modifies:!0},params:[{name:"size",type:"number",array:!0,length:2,required:!0},{name:"sort",type:"compare"},{name:"anchor",type:"string",array:!0,default:M},{name:"offset",type:"number",array:!0,default:[1]},{name:"padding",type:"number",default:0},{name:"lineAnchor",type:"string",values:["start","end"],default:"end"},{name:"markIndex",type:"number",default:0},{name:"avoidBaseMark",type:"boolean",default:!0},{name:"avoidMarks",type:"data",array:!0},{name:"method",type:"string",default:"naive"},{name:"as",type:"string",array:!0,length:k.length,default:k}]},a.inherits(R,n.Transform,{transform(t,e){const n=t.modified();if(!(n||e.changed(e.ADD_REM)||function(n){const r=t[n];return a.isFunction(r)&&e.modified(r.fields)}("sort")))return;t.size&&2===t.size.length||a.error("Size parameter should be specified as a [width, height] array.");const r=t.as||k;return w(e.materialize(e.SOURCE).source,t.size,t.sort,a.array(t.offset||1),a.array(t.anchor||M),t.avoidMarks||[],!1!==t.avoidBaseMark,t.lineAnchor||"end",t.markIndex||0,t.padding||0,t.method||"naive").forEach(t=>{const e=t.datum;e[r[0]]=t.x,e[r[1]]=t.y,e[r[2]]=t.opacity,e[r[3]]=t.align,e[r[4]]=t.baseline}),e.reflow(n).modifies(r)}}),t.label=R,t}({},vega,vega,vega,vega);
//# sourceMappingURL=vega-label.min.js.map
{
"name": "vega-label",
"version": "0.0.5",
"version": "1.0.0",
"description": "Label layout transform for Vega dataflows.",

@@ -16,19 +16,17 @@ "keywords": [

"main": "build/vega-label.js",
"module": "index",
"module": "build/vega-label.module.js",
"unpkg": "build/vega-label.min.js",
"repository": "vega/vega",
"scripts": {
"rollup": "rollup -g vega-canvas:vega,vega-dataflow:vega,vega-scenegraph:vega,vega-util:vega -f umd -n vega.transforms -o build/vega-label.js -- index.js",
"prebuild": "rimraf build && mkdir build",
"build": "yarn rollup",
"postbuild": "terser build/vega-label.js -c -m -o build/vega-label.min.js",
"pretest": "yarn prebuild && yarn rollup",
"prebuild": "rimraf build",
"build": "rollup -c --config-transform",
"pretest": "yarn build --config-test",
"test": "tape 'test/**/*-test.js'",
"prepublishOnly": "yarn test && yarn build",
"postpublish": "git push && git push --tags"
"prepublishOnly": "yarn test && yarn build"
},
"dependencies": {
"vega-canvas": "^1.2.4",
"vega-dataflow": "^5.7.2",
"vega-scenegraph": "^4.9.1",
"vega-util": "^1.15.1"
"vega-canvas": "^1.2.5",
"vega-dataflow": "^5.7.3",
"vega-scenegraph": "^4.9.2",
"vega-util": "^1.15.2"
},

@@ -38,3 +36,3 @@ "devDependencies": {

},
"gitHead": "8d6793f4ca7eaaf2d22186764e9ce2dae687cf52"
"gitHead": "4affcbedb9d14815dbb6d3b250ed231b54fc95c0"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc