Socket
Socket
Sign inDemoInstall

vega-label

Package Overview
Dependencies
30
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.1.0 to 1.2.0

156

build/vega-label.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vega-canvas'), require('vega-dataflow'), require('vega-scenegraph'), require('vega-util')) :
typeof define === 'function' && define.amd ? define(['exports', 'vega-canvas', 'vega-dataflow', 'vega-scenegraph', 'vega-util'], factory) :
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vega-scenegraph'), require('vega-canvas'), require('vega-dataflow'), require('vega-util')) :
typeof define === 'function' && define.amd ? define(['exports', 'vega-scenegraph', 'vega-canvas', 'vega-dataflow', 'vega-util'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.vega = global.vega || {}, global.vega.transforms = {}), global.vega, global.vega, global.vega, global.vega));
}(this, (function (exports, vegaCanvas, vegaDataflow, vegaScenegraph, vegaUtil) { 'use strict';
})(this, (function (exports, vegaScenegraph, vegaCanvas, vegaDataflow, vegaUtil) { 'use strict';
const ALPHA_MASK = 0xff000000; // alpha value equivalent to opacity 0.0625
const INSIDE_OPACITY_IN_ALPHA = 0x10000000;
const INSIDE_OPACITY = 0.0625;
const ALPHA_MASK = 0xff000000;
function baseBitmaps($, data) {

@@ -17,3 +14,3 @@ const bitmap = $.bitmap(); // when there is no base mark but data points are to be avoided

}
function markBitmaps($, avoidMarks, labelInside, isGroupArea) {
function markBitmaps($, baseMark, avoidMarks, labelInside, isGroupArea) {
// create canvas

@@ -23,22 +20,35 @@ const width = $.width,

border = labelInside || isGroupArea,
context = vegaCanvas.canvas(width, height).getContext('2d'); // render all marks to be avoided into canvas
context = vegaCanvas.canvas(width, height).getContext('2d'),
baseMarkContext = vegaCanvas.canvas(width, height).getContext('2d'),
strokeContext = border && vegaCanvas.canvas(width, height).getContext('2d'); // render all marks to be avoided into canvas
avoidMarks.forEach(items => draw(context, items, border)); // get canvas buffer, create bitmaps
avoidMarks.forEach(items => draw(context, items, false));
draw(baseMarkContext, baseMark, false);
const buffer = new Uint32Array(context.getImageData(0, 0, width, height).data.buffer),
if (border) {
draw(strokeContext, baseMark, true);
} // get canvas buffer, create bitmaps
const buffer = getBuffer(context, width, height),
baseMarkBuffer = getBuffer(baseMarkContext, width, height),
strokeBuffer = border && getBuffer(strokeContext, width, height),
layer1 = $.bitmap(),
layer2 = border && $.bitmap(); // populate bitmap layers
let x, y, u, v, alpha;
let x, y, u, v, index, alpha, strokeAlpha, baseMarkAlpha;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
alpha = buffer[y * width + x] & ALPHA_MASK;
index = y * width + x;
alpha = buffer[index] & ALPHA_MASK;
baseMarkAlpha = baseMarkBuffer[index] & ALPHA_MASK;
strokeAlpha = border && strokeBuffer[index] & ALPHA_MASK;
if (alpha) {
if (alpha || strokeAlpha || baseMarkAlpha) {
u = $(x);
v = $(y);
if (!isGroupArea) layer1.set(u, v); // update interior bitmap
if (!isGroupArea && (alpha || baseMarkAlpha)) layer1.set(u, v); // update interior bitmap
if (border && alpha ^ INSIDE_OPACITY_IN_ALPHA) layer2.set(u, v); // update border bitmap
if (border && (alpha || strokeAlpha)) layer2.set(u, v); // update border bitmap
}

@@ -51,2 +61,6 @@ }

function getBuffer(context, width, height) {
return new Uint32Array(context.getImageData(0, 0, width, height).data.buffer);
}
function draw(context, items, interior) {

@@ -76,13 +90,10 @@ if (!items.length) return;

if (item.stroke) {
item.strokeOpacity = 1;
if (item.stroke && item.strokeOpacity !== 0 || item.fill && item.fillOpacity !== 0) {
return { ...item,
strokeOpacity: 1,
stroke: '#000',
fillOpacity: 0
};
}
if (item.fill) {
item.fillOpacity = INSIDE_OPACITY;
item.stroke = '#000';
item.strokeOpacity = 1;
item.strokeWidth = 2;
}
return item;

@@ -294,7 +305,2 @@ }

}
function _outOfBounds() {
return false;
}
function collision($, x, y, textHeight, textWidth, h, bm0, bm1) {

@@ -309,23 +315,5 @@ const w = textWidth * h / (textHeight * 2),

function _collision($, x, y, textHeight, textWidth, h, bm0, bm1) {
const w = textWidth * h / (textHeight * 2);
let x1 = $(x - w),
x2 = $(x + w),
y1 = $(y - (h = h / 2)),
y2 = $(y + h);
x1 = x1 > 0 ? x1 : 0;
y1 = y1 > 0 ? y1 : 0;
x2 = x2 < $.width ? x2 : $.width - 1;
y2 = y2 < $.height ? y2 : $.height - 1;
return bm0.getRange(x1, y1, x2, y2) || bm1 && bm1.getRange(x1, y1, x2, y2);
}
function getTests(infPadding) {
return infPadding ? [_collision, _outOfBounds] : [collision, outOfBounds];
}
function placeAreaLabelReducedSearch ($, bitmaps, avoidBaseMark, markIndex, infPadding) {
function placeAreaLabelReducedSearch ($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height,
[collision, outOfBounds] = getTests(infPadding),
bm0 = bitmaps[0],

@@ -474,6 +462,5 @@ // where labels have been placed

const Y_DIR = [-1, 1, -1, 1];
function placeAreaLabelFloodFill ($, bitmaps, avoidBaseMark, markIndex, infPadding) {
function placeAreaLabelFloodFill ($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height,
[collision, outOfBounds] = getTests(infPadding),
bm0 = bitmaps[0],

@@ -599,3 +586,3 @@ // where labels have been placed

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

@@ -610,7 +597,7 @@ height = $.height,

if (!infPadding && (boundary[2] < 0 || boundary[5] < 0 || boundary[0] > width || boundary[3] > height)) {
if (boundary[2] < 0 || boundary[5] < 0 || boundary[0] > width || boundary[3] > height) {
return false;
}
let textWidth = 0,
let textWidth = d.textWidth ?? 0,
dx,

@@ -647,8 +634,2 @@ dy,

if (infPadding) {
_x1 = _x1 < 0 ? 0 : _x1;
_y1 = _y1 < 0 ? 0 : _y1;
_y2 = _y2 >= $.height ? $.height - 1 : _y2;
}
if (!textWidth) {

@@ -671,7 +652,2 @@ // to avoid finding width of text label,

if (infPadding) {
_x1 = _x1 < 0 ? 0 : _x1;
_x2 = _x2 >= $.width ? $.width - 1 : _x2;
}
if (test(_x1, _x2, _y1, _y2, bm0, bm1, x1, x2, y1, y2, boundary, isInside)) {

@@ -693,9 +669,5 @@ // place label if the position is placeable

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 || 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];
}
const TOP = 0x0,

@@ -735,14 +707,23 @@ MIDDLE = 0x4,

infPadding = padding === null || padding === Infinity,
$ = scaler(size[0], size[1], infPadding ? 0 : padding),
isNaiveGroupArea = isGroupArea && method === 'naive'; // prepare text mark data for placing
isNaiveGroupArea = isGroupArea && method === 'naive';
let maxTextWidth = -1,
maxTextHeight = -1; // prepare text mark data for placing
const data = texts.map(d => ({
datum: d,
opacity: 0,
x: undefined,
y: undefined,
align: undefined,
baseline: undefined,
boundary: boundary(d)
}));
const data = texts.map(d => {
const textWidth = infPadding ? vegaScenegraph.textMetrics.width(d, d.text) : undefined;
maxTextWidth = Math.max(maxTextWidth, textWidth);
maxTextHeight = Math.max(maxTextHeight, d.fontSize);
return {
datum: d,
opacity: 0,
x: undefined,
y: undefined,
align: undefined,
baseline: undefined,
boundary: boundary(d),
textWidth
};
});
padding = padding === null || padding === Infinity ? Math.max(maxTextWidth, maxTextHeight) + Math.max(...offset) : padding;
const $ = scaler(size[0], size[1], padding);
let bitmaps;

@@ -767,12 +748,9 @@

if (marktype && (avoidBaseMark || isGroupArea)) {
avoidMarks = [texts.map(d => d.datum)].concat(avoidMarks);
} // generate bitmaps for layout calculation
const baseMark = (marktype && avoidBaseMark || isGroupArea) && texts.map(d => d.datum); // generate bitmaps for layout calculation
bitmaps = avoidMarks.length ? markBitmaps($, avoidMarks, labelInside, isGroupArea) : baseBitmaps($, avoidBaseMark && data);
bitmaps = avoidMarks.length || baseMark ? markBitmaps($, baseMark || [], avoidMarks, labelInside, isGroupArea) : baseBitmaps($, avoidBaseMark && data);
} // generate label placement function
const place = isGroupArea ? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex, infPadding) : placeMarkLabel($, bitmaps, anchors, offsets, infPadding); // place all labels
const place = isGroupArea ? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex) : placeMarkLabel($, bitmaps, anchors, offsets); // place all labels

@@ -812,3 +790,3 @@ data.forEach(d => d.opacity = +place(d));

* is the coordinate of each data point. When base mark is grouped line,
* boundary is either at the beginning or end of the line depending on the
* boundary is either at the start or end of the line depending on the
* value of lineAnchor. Otherwise, use bounds of base mark.

@@ -967,2 +945,2 @@ */

})));
}));

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

@@ -0,10 +1,7 @@

import { Marks, textMetrics } from 'vega-scenegraph';
import { canvas } from 'vega-canvas';
import { rederive, Transform } from 'vega-dataflow';
import { Marks, textMetrics } from 'vega-scenegraph';
import { inherits, isFunction, error, array } from 'vega-util';
const ALPHA_MASK = 0xff000000; // alpha value equivalent to opacity 0.0625
const INSIDE_OPACITY_IN_ALPHA = 0x10000000;
const INSIDE_OPACITY = 0.0625;
const ALPHA_MASK = 0xff000000;
function baseBitmaps($, data) {

@@ -16,3 +13,3 @@ const bitmap = $.bitmap(); // when there is no base mark but data points are to be avoided

}
function markBitmaps($, avoidMarks, labelInside, isGroupArea) {
function markBitmaps($, baseMark, avoidMarks, labelInside, isGroupArea) {
// create canvas

@@ -22,22 +19,35 @@ const width = $.width,

border = labelInside || isGroupArea,
context = canvas(width, height).getContext('2d'); // render all marks to be avoided into canvas
context = canvas(width, height).getContext('2d'),
baseMarkContext = canvas(width, height).getContext('2d'),
strokeContext = border && canvas(width, height).getContext('2d'); // render all marks to be avoided into canvas
avoidMarks.forEach(items => draw(context, items, border)); // get canvas buffer, create bitmaps
avoidMarks.forEach(items => draw(context, items, false));
draw(baseMarkContext, baseMark, false);
const buffer = new Uint32Array(context.getImageData(0, 0, width, height).data.buffer),
if (border) {
draw(strokeContext, baseMark, true);
} // get canvas buffer, create bitmaps
const buffer = getBuffer(context, width, height),
baseMarkBuffer = getBuffer(baseMarkContext, width, height),
strokeBuffer = border && getBuffer(strokeContext, width, height),
layer1 = $.bitmap(),
layer2 = border && $.bitmap(); // populate bitmap layers
let x, y, u, v, alpha;
let x, y, u, v, index, alpha, strokeAlpha, baseMarkAlpha;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
alpha = buffer[y * width + x] & ALPHA_MASK;
index = y * width + x;
alpha = buffer[index] & ALPHA_MASK;
baseMarkAlpha = baseMarkBuffer[index] & ALPHA_MASK;
strokeAlpha = border && strokeBuffer[index] & ALPHA_MASK;
if (alpha) {
if (alpha || strokeAlpha || baseMarkAlpha) {
u = $(x);
v = $(y);
if (!isGroupArea) layer1.set(u, v); // update interior bitmap
if (!isGroupArea && (alpha || baseMarkAlpha)) layer1.set(u, v); // update interior bitmap
if (border && alpha ^ INSIDE_OPACITY_IN_ALPHA) layer2.set(u, v); // update border bitmap
if (border && (alpha || strokeAlpha)) layer2.set(u, v); // update border bitmap
}

@@ -50,2 +60,6 @@ }

function getBuffer(context, width, height) {
return new Uint32Array(context.getImageData(0, 0, width, height).data.buffer);
}
function draw(context, items, interior) {

@@ -75,13 +89,10 @@ if (!items.length) return;

if (item.stroke) {
item.strokeOpacity = 1;
if (item.stroke && item.strokeOpacity !== 0 || item.fill && item.fillOpacity !== 0) {
return { ...item,
strokeOpacity: 1,
stroke: '#000',
fillOpacity: 0
};
}
if (item.fill) {
item.fillOpacity = INSIDE_OPACITY;
item.stroke = '#000';
item.strokeOpacity = 1;
item.strokeWidth = 2;
}
return item;

@@ -293,7 +304,2 @@ }

}
function _outOfBounds() {
return false;
}
function collision($, x, y, textHeight, textWidth, h, bm0, bm1) {

@@ -308,23 +314,5 @@ const w = textWidth * h / (textHeight * 2),

function _collision($, x, y, textHeight, textWidth, h, bm0, bm1) {
const w = textWidth * h / (textHeight * 2);
let x1 = $(x - w),
x2 = $(x + w),
y1 = $(y - (h = h / 2)),
y2 = $(y + h);
x1 = x1 > 0 ? x1 : 0;
y1 = y1 > 0 ? y1 : 0;
x2 = x2 < $.width ? x2 : $.width - 1;
y2 = y2 < $.height ? y2 : $.height - 1;
return bm0.getRange(x1, y1, x2, y2) || bm1 && bm1.getRange(x1, y1, x2, y2);
}
function getTests(infPadding) {
return infPadding ? [_collision, _outOfBounds] : [collision, outOfBounds];
}
function placeAreaLabelReducedSearch ($, bitmaps, avoidBaseMark, markIndex, infPadding) {
function placeAreaLabelReducedSearch ($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height,
[collision, outOfBounds] = getTests(infPadding),
bm0 = bitmaps[0],

@@ -473,6 +461,5 @@ // where labels have been placed

const Y_DIR = [-1, 1, -1, 1];
function placeAreaLabelFloodFill ($, bitmaps, avoidBaseMark, markIndex, infPadding) {
function placeAreaLabelFloodFill ($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height,
[collision, outOfBounds] = getTests(infPadding),
bm0 = bitmaps[0],

@@ -598,3 +585,3 @@ // where labels have been placed

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

@@ -606,10 +593,12 @@ height = $.height,

return function (d) {
var _d$textWidth;
const boundary = d.boundary,
textHeight = d.datum.fontSize; // can not be placed if the mark is not visible in the graph bound
if (!infPadding && (boundary[2] < 0 || boundary[5] < 0 || boundary[0] > width || boundary[3] > height)) {
if (boundary[2] < 0 || boundary[5] < 0 || boundary[0] > width || boundary[3] > height) {
return false;
}
let textWidth = 0,
let textWidth = (_d$textWidth = d.textWidth) !== null && _d$textWidth !== void 0 ? _d$textWidth : 0,
dx,

@@ -646,8 +635,2 @@ dy,

if (infPadding) {
_x1 = _x1 < 0 ? 0 : _x1;
_y1 = _y1 < 0 ? 0 : _y1;
_y2 = _y2 >= $.height ? $.height - 1 : _y2;
}
if (!textWidth) {

@@ -670,7 +653,2 @@ // to avoid finding width of text label,

if (infPadding) {
_x1 = _x1 < 0 ? 0 : _x1;
_x2 = _x2 >= $.width ? $.width - 1 : _x2;
}
if (test(_x1, _x2, _y1, _y2, bm0, bm1, x1, x2, y1, y2, boundary, isInside)) {

@@ -692,9 +670,5 @@ // place label if the position is placeable

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 || 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];
}
const TOP = 0x0,

@@ -734,14 +708,23 @@ MIDDLE = 0x4,

infPadding = padding === null || padding === Infinity,
$ = scaler(size[0], size[1], infPadding ? 0 : padding),
isNaiveGroupArea = isGroupArea && method === 'naive'; // prepare text mark data for placing
isNaiveGroupArea = isGroupArea && method === 'naive';
let maxTextWidth = -1,
maxTextHeight = -1; // prepare text mark data for placing
const data = texts.map(d => ({
datum: d,
opacity: 0,
x: undefined,
y: undefined,
align: undefined,
baseline: undefined,
boundary: boundary(d)
}));
const data = texts.map(d => {
const textWidth = infPadding ? textMetrics.width(d, d.text) : undefined;
maxTextWidth = Math.max(maxTextWidth, textWidth);
maxTextHeight = Math.max(maxTextHeight, d.fontSize);
return {
datum: d,
opacity: 0,
x: undefined,
y: undefined,
align: undefined,
baseline: undefined,
boundary: boundary(d),
textWidth
};
});
padding = padding === null || padding === Infinity ? Math.max(maxTextWidth, maxTextHeight) + Math.max(...offset) : padding;
const $ = scaler(size[0], size[1], padding);
let bitmaps;

@@ -766,12 +749,9 @@

if (marktype && (avoidBaseMark || isGroupArea)) {
avoidMarks = [texts.map(d => d.datum)].concat(avoidMarks);
} // generate bitmaps for layout calculation
const baseMark = (marktype && avoidBaseMark || isGroupArea) && texts.map(d => d.datum); // generate bitmaps for layout calculation
bitmaps = avoidMarks.length ? markBitmaps($, avoidMarks, labelInside, isGroupArea) : baseBitmaps($, avoidBaseMark && data);
bitmaps = avoidMarks.length || baseMark ? markBitmaps($, baseMark || [], avoidMarks, labelInside, isGroupArea) : baseBitmaps($, avoidBaseMark && data);
} // generate label placement function
const place = isGroupArea ? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex, infPadding) : placeMarkLabel($, bitmaps, anchors, offsets, infPadding); // place all labels
const place = isGroupArea ? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex) : placeMarkLabel($, bitmaps, anchors, offsets); // place all labels

@@ -811,3 +791,3 @@ data.forEach(d => d.opacity = +place(d));

* is the coordinate of each data point. When base mark is grouped line,
* boundary is either at the beginning or end of the line depending on the
* boundary is either at the start or end of the line depending on the
* value of lineAnchor. Otherwise, use bounds of base mark.

@@ -814,0 +794,0 @@ */

{
"name": "vega-label",
"version": "1.1.0",
"version": "1.2.0",
"description": "Label layout transform for Vega dataflows.",

@@ -27,3 +27,3 @@ "keywords": [

"dependencies": {
"vega-canvas": "^1.2.5",
"vega-canvas": "^1.2.6",
"vega-dataflow": "^5.7.3",

@@ -36,3 +36,3 @@ "vega-scenegraph": "^4.9.2",

},
"gitHead": "774165e29850b66ec8b79ba52a7955f1ab936ea6"
"gitHead": "9a3faca4395cade9ecdfde90af98f1c53e9916b2"
}

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

import {textMetrics} from 'vega-scenegraph';
import {baseBitmaps, markBitmaps} from './util/markBitmaps';

@@ -49,16 +50,30 @@ import scaler from './util/scaler';

infPadding = padding === null || padding === Infinity,
$ = scaler(size[0], size[1], infPadding ? 0 : padding),
isNaiveGroupArea = isGroupArea && method === 'naive';
let maxTextWidth = -1,
maxTextHeight = -1;
// prepare text mark data for placing
const data = texts.map(d => ({
datum: d,
opacity: 0,
x: undefined,
y: undefined,
align: undefined,
baseline: undefined,
boundary: boundary(d)
}));
const data = texts.map(d => {
const textWidth = infPadding ? textMetrics.width(d, d.text) : undefined;
maxTextWidth = Math.max(maxTextWidth, textWidth);
maxTextHeight = Math.max(maxTextHeight, d.fontSize);
return {
datum: d,
opacity: 0,
x: undefined,
y: undefined,
align: undefined,
baseline: undefined,
boundary: boundary(d),
textWidth
};
});
padding = (padding === null || padding === Infinity)
? Math.max(maxTextWidth, maxTextHeight) + Math.max(...offset)
: padding;
const $ = scaler(size[0], size[1], padding);
let bitmaps;

@@ -81,9 +96,7 @@ if (!isNaiveGroupArea) {

// base mark is implicitly avoided if it is a group area
if (marktype && (avoidBaseMark || isGroupArea)) {
avoidMarks = [texts.map(d => d.datum)].concat(avoidMarks);
}
const baseMark = ((marktype && avoidBaseMark) || isGroupArea) && texts.map(d => d.datum);
// generate bitmaps for layout calculation
bitmaps = avoidMarks.length
? markBitmaps($, avoidMarks, labelInside, isGroupArea)
bitmaps = avoidMarks.length || baseMark
? markBitmaps($, baseMark || [], avoidMarks, labelInside, isGroupArea)
: baseBitmaps($, avoidBaseMark && data);

@@ -94,4 +107,4 @@ }

const place = isGroupArea
? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex, infPadding)
: placeMarkLabel($, bitmaps, anchors, offsets, infPadding);
? placeAreaLabel[method]($, bitmaps, avoidBaseMark, markIndex)
: placeMarkLabel($, bitmaps, anchors, offsets);

@@ -128,3 +141,3 @@ // place all labels

* is the coordinate of each data point. When base mark is grouped line,
* boundary is either at the beginning or end of the line depending on the
* boundary is either at the start or end of the line depending on the
* value of lineAnchor. Otherwise, use bounds of base mark.

@@ -131,0 +144,0 @@ */

@@ -8,6 +8,2 @@ import {canvas} from 'vega-canvas';

// alpha value equivalent to opacity 0.0625
const INSIDE_OPACITY_IN_ALPHA = 0x10000000;
const INSIDE_OPACITY = 0.0625;
export function baseBitmaps($, data) {

@@ -20,3 +16,3 @@ const bitmap = $.bitmap();

export function markBitmaps($, avoidMarks, labelInside, isGroupArea) {
export function markBitmaps($, baseMark, avoidMarks, labelInside, isGroupArea) {
// create canvas

@@ -26,9 +22,17 @@ const width = $.width,

border = labelInside || isGroupArea,
context = canvas(width, height).getContext('2d');
context = canvas(width, height).getContext('2d'),
baseMarkContext = canvas(width, height).getContext('2d'),
strokeContext = border && canvas(width, height).getContext('2d');
// render all marks to be avoided into canvas
avoidMarks.forEach(items => draw(context, items, border));
avoidMarks.forEach(items => draw(context, items, false));
draw(baseMarkContext, baseMark, false);
if (border) {
draw(strokeContext, baseMark, true);
}
// get canvas buffer, create bitmaps
const buffer = new Uint32Array(context.getImageData(0, 0, width, height).data.buffer),
const buffer = getBuffer(context, width, height),
baseMarkBuffer = getBuffer(baseMarkContext, width, height),
strokeBuffer = border && getBuffer(strokeContext, width, height),
layer1 = $.bitmap(),

@@ -38,11 +42,16 @@ layer2 = border && $.bitmap();

// populate bitmap layers
let x, y, u, v, alpha;
let x, y, u, v, index, alpha, strokeAlpha, baseMarkAlpha;
for (y=0; y < height; ++y) {
for (x=0; x < width; ++x) {
alpha = buffer[y * width + x] & ALPHA_MASK;
if (alpha) {
index = y * width + x;
alpha = buffer[index] & ALPHA_MASK;
baseMarkAlpha = baseMarkBuffer[index] & ALPHA_MASK;
strokeAlpha = border && (strokeBuffer[index] & ALPHA_MASK);
if (alpha || strokeAlpha || baseMarkAlpha) {
u = $(x);
v = $(y);
if (!isGroupArea) layer1.set(u, v); // update interior bitmap
if (border && alpha ^ INSIDE_OPACITY_IN_ALPHA) layer2.set(u, v); // update border bitmap
if (!isGroupArea && (alpha || baseMarkAlpha)) layer1.set(u, v); // update interior bitmap
if (border && (alpha || strokeAlpha)) layer2.set(u, v); // update border bitmap
}

@@ -55,2 +64,6 @@ }

function getBuffer(context, width, height) {
return new Uint32Array(context.getImageData(0, 0, width, height).data.buffer);
}
function draw(context, items, interior) {

@@ -77,14 +90,15 @@ if (!items.length) return;

if (item.stroke) {
item.strokeOpacity = 1;
if (
(item.stroke && item.strokeOpacity !== 0) ||
(item.fill && item.fillOpacity !== 0)
) {
return {
...item,
strokeOpacity: 1,
stroke: '#000',
fillOpacity: 0
};
}
if (item.fill) {
item.fillOpacity = INSIDE_OPACITY;
item.stroke = '#000';
item.strokeOpacity = 1;
item.strokeWidth = 2;
}
return item;
}

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

function outOfBounds(x, y, textWidth, textHeight, width, height) {
export function outOfBounds(x, y, textWidth, textHeight, width, height) {
let r = textWidth / 2;

@@ -9,7 +9,3 @@ return x - r < 0

function _outOfBounds() {
return false;
}
function collision($, x, y, textHeight, textWidth, h, bm0, bm1) {
export function collision($, x, y, textHeight, textWidth, h, bm0, bm1) {
const w = (textWidth * h) / (textHeight * 2),

@@ -24,23 +20,2 @@ x1 = $(x - w),

|| (bm1 && bm1.getRange(x1, y1, x2, y2));
}
function _collision($, x, y, textHeight, textWidth, h, bm0, bm1) {
const w = (textWidth * h) / (textHeight * 2);
let x1 = $(x - w),
x2 = $(x + w),
y1 = $(y - (h = h/2)),
y2 = $(y + h);
x1 = x1 > 0 ? x1 : 0;
y1 = y1 > 0 ? y1 : 0;
x2 = x2 < $.width ? x2 : $.width - 1;
y2 = y2 < $.height ? y2 : $.height - 1;
return bm0.getRange(x1, y1, x2, y2) || (bm1 && bm1.getRange(x1, y1, x2, y2));
}
export function getTests(infPadding) {
return infPadding
? [_collision, _outOfBounds]
: [collision, outOfBounds];
}
import {textMetrics} from 'vega-scenegraph';
import {getTests} from './common';
import {collision, outOfBounds} from './common';

@@ -8,6 +8,5 @@ // pixel direction offsets for flood fill search

export default function($, bitmaps, avoidBaseMark, markIndex, infPadding) {
export default function($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height,
[collision, outOfBounds] = getTests(infPadding),
bm0 = bitmaps[0], // where labels have been placed

@@ -14,0 +13,0 @@ bm1 = bitmaps[1], // area outlines

import {textMetrics} from 'vega-scenegraph';
import {getTests} from './common';
import {collision, outOfBounds} from './common';
export default function($, bitmaps, avoidBaseMark, markIndex, infPadding) {
export default function($, bitmaps, avoidBaseMark, markIndex) {
const width = $.width,
height = $.height,
[collision, outOfBounds] = getTests(infPadding),
bm0 = bitmaps[0], // where labels have been placed

@@ -9,0 +8,0 @@ bm1 = bitmaps[1]; // area outlines

@@ -6,3 +6,3 @@ import {textMetrics} from 'vega-scenegraph';

export default function($, bitmaps, anchors, offsets, infPadding) {
export default function($, bitmaps, anchors, offsets) {
const width = $.width,

@@ -19,7 +19,7 @@ height = $.height,

// can not be placed if the mark is not visible in the graph bound
if (!infPadding && (boundary[2] < 0 || boundary[5] < 0 || boundary[0] > width || boundary[3] > height)) {
if (boundary[2] < 0 || boundary[5] < 0 || boundary[0] > width || boundary[3] > height) {
return false;
}
let textWidth = 0,
let textWidth = d.textWidth ?? 0,
dx, dy, isInside, sizeFactor, insideFactor,

@@ -47,8 +47,2 @@ x1, x2, y1, y2, xc, yc,

if (infPadding) {
_x1 = _x1 < 0 ? 0 : _x1;
_y1 = _y1 < 0 ? 0 : _y1;
_y2 = _y2 >= $.height ? ($.height - 1) : _y2;
}
if (!textWidth) {

@@ -72,7 +66,2 @@ // to avoid finding width of text label,

if (infPadding) {
_x1 = _x1 < 0 ? 0 : _x1;
_x2 = _x2 >= $.width ? ($.width - 1) : _x2;
}
if (test(_x1, _x2, _y1, _y2, bm0, bm1, x1, x2, y1, y2, boundary, isInside)) {

@@ -99,11 +88,4 @@ // place label if the position is placeable

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))
((isInside && bm1) || 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];
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc