@sutton-signwriting/core
Version:
a javascript package for node and browsers that supports general processing of the Sutton SignWriting script
252 lines (235 loc) • 6.17 kB
JavaScript
import { parse } from './fsw-parse';
import { info } from './fsw-info';
const columnDefaults = {
'height': 500,
'width': 150,
'offset': 50,
'pad': 20,
'margin': 5,
'dynamic': false,
'background': undefined,
'punctuation': {
'spacing': true,
'pad': 30,
'pull': true
},
'style':{
'detail': ['black','white'],
'zoom': 1
}
}
/**
* Function to an object of column options with default values
*
* @function fsw.columnDefaultsMerge
* @param {ColumnOptions} options - object of column options
* @returns {ColumnOptions} object of column options merged with column defaults
* @example
* fsw.columnDefaultsMerge({height: 500,width:150})
*
* return {
* "height": 500,
* "width": 150,
* "offset": 50,
* "pad": 20,
* "margin": 5,
* "dynamic": false,
* "punctuation": {
* "spacing": true,
* "pad": 30,
* "pull": true
* },
* "style": {
* "detail": [
* "black",
* "white"
* ],
* "zoom": 1
* }
* }
*/
const columnDefaultsMerge = (options) => {
if (typeof options !== 'object') options = {};
return {
...columnDefaults,
...options,
punctuation: {
...columnDefaults.punctuation,
...options.punctuation
},
style: {
...columnDefaults.style,
...options.style
}
}
}
/**
* Function to transform an FSW text to an array of columns
*
* @function fsw.columns
* @param {string} fswText - FSW text of signs and punctuation
* @param {ColumnOptions} options - object of column options
* @returns {{options:ColumnOptions,widths:number[],columns:ColumnData}} object of column options, widths array, and column data
* @example
* fsw.columns('AS14c20S27106M518x529S14c20481x471S27106503x489 AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468 S38800464x496', {height: 500,width:150})
*
* return {
* "options": {
* "height": 500,
* "width": 150,
* "offset": 50,
* "pad": 20,
* "margin": 5,
* "dynamic": false,
* "punctuation": {
* "spacing": true,
* "pad": 30,
* "pull": true
* },
* "style": {
* "detail": [
* "black",
* "white"
* ],
* "zoom": 1
* }
* },
* "widths": [
* 150
* ],
* "columns": [
* [
* {
* "x": 56,
* "y": 20,
* "minX": 481,
* "minY": 471,
* "width": 37,
* "height": 58,
* "lane": 0,
* "padding": 0,
* "segment": "sign",
* "text": "AS14c20S27106M518x529S14c20481x471S27106503x489",
* "zoom": 1
* },
* {
* "x": 57,
* "y": 118,
* "minX": 482,
* "minY": 468,
* "width": 36,
* "height": 65,
* "lane": 0,
* "padding": 0,
* "segment": "sign",
* "text": "AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468",
* "zoom": 1
* },
* {
* "x": 39,
* "y": 203,
* "minX": 464,
* "minY": 496,
* "width": 72,
* "height": 8,
* "lane": 0,
* "padding": 0,
* "segment": "symbol",
* "text": "S38800464x496",
* "zoom": 1
* }
* ]
* ]
* }
*/
const columns = (fswText, options) => {
if (typeof fswText !== 'string') return {};
const values = columnDefaultsMerge(options);
let input = parse.text(fswText);
let cursor = 0;
let cols = [];
let col = [];
let plus = 0;
let center = parseInt(values.width/2);
let maxHeight = values.height - values.margin;
let pullable = true;
let finalize = false;
for (let val of input) {
let informed = info(val);
cursor += plus;
if (values.punctuation.spacing){
cursor += ((informed.segment=='sign')?values.pad:0);
} else {
cursor += values.pad;
}
finalize = ((cursor + informed.height) > maxHeight);
if (finalize && informed.segment=='symbol' && values.punctuation.pull && pullable){
finalize = false;
pullable = false;
}
if (col.length == 0) { finalize = false; }
if ( finalize) {
cursor = values.pad;
cols.push(col);
col = [];
pullable = true;
}
col.push(Object.assign(informed,{
x: center + (values.offset * informed.lane) - ((500-informed.minX) * informed.zoom * values.style.zoom),
y: cursor,
text: val
}))
cursor += (informed.height * informed.zoom * values.style.zoom);
if (values.punctuation.spacing){
plus = (informed.segment=='sign')?values.pad:values.punctuation.pad;
} else {
plus = values.pad;
}
}
if (col.length) {
cols.push(col);
}
// over height issue when pulling punctuation
if (values.punctuation.pull) {
for (let col of cols){
let last = col[col.length -1];
let diff = (last.y + last.height) - (values.height - values.margin);
if (diff>0){
let adj = parseInt(diff/(col.length)) + 1;
for (let i in col){
col[i].y -= adj*i + adj;
}
}
}
}
// contract, expand, adjust
let widths = [];
for (let col of cols){
let min = [(center - values.offset - values.pad)]
let max = [(center + values.offset + values.pad)]
for (let item of col){
min.push(item.x - values.pad);
max.push(item.x + item.width + values.pad);
}
min = Math.min(...min);
max = Math.max(...max);
let width = values.width;
let adj = 0;
if (!values.dynamic){
adj = center - parseInt((min + max)/2);
} else {
width = max - min;
adj = -min;
}
for (let item of col){
item.x += adj;
}
widths.push(width);
}
return {
'options': values,
'widths': widths,
'columns': cols
};
}
export { columnDefaults, columnDefaultsMerge, columns }