client/src/components/special/hcs-image/hcs-cell-selector/canvas-utilities.js (94 lines of code) (raw):

/* * Copyright 2017-2022 EPAM Systems, Inc. (https://www.epam.com/) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* eslint-disable max-len */ const VERTEX = `attribute vec2 position; uniform vec4 color; uniform mat4 viewScale; uniform mat4 viewTranslate; uniform mat4 modelScale; uniform mat4 modelTranslate; uniform mat4 projection; varying vec4 vColor; void main() { vColor = color; gl_Position = projection * viewTranslate * viewScale * modelTranslate * modelScale * vec4(position, 0, 1); }`; const FRAGMENT = `precision mediump float; varying vec4 vColor; void main() { gl_FragColor = vColor; }`; function makeShader (gl, src, type) { if (!gl) { return; } const shader = gl.createShader(type); gl.shaderSource(shader, src); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.warn(gl.getShaderInfoLog(shader)); return; } return shader; } function initShaders (gl) { const vertexShader = makeShader(gl, VERTEX, gl.VERTEX_SHADER); const fragmentShader = makeShader(gl, FRAGMENT, gl.FRAGMENT_SHADER); const glProgram = gl.createProgram(); gl.attachShader(glProgram, vertexShader); gl.attachShader(glProgram, fragmentShader); gl.linkProgram(glProgram); if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) { console.warn('Error initializing gl program'); return false; } gl.useProgram(glProgram); gl.program = glProgram; return glProgram; } export function resizeCanvas (canvas, size) { if (!canvas || !size || !size.width || !size.height) { return false; } const { width: canvasWidth, height: canvasHeight } = size; if ( canvas.width !== canvasWidth * window.devicePixelRatio || canvas.height !== canvasHeight * window.devicePixelRatio ) { canvas.width = canvasWidth * window.devicePixelRatio; canvas.height = canvasHeight * window.devicePixelRatio; canvas.style.width = `${canvasWidth}px`; canvas.style.height = `${canvasHeight}px`; return true; } return false; } export function createGLProgram (gl) { if (!gl) { return; } const glProgram = initShaders(gl); if (glProgram) { gl.useProgram(glProgram); return { program: glProgram, color: gl.getUniformLocation(glProgram, 'color'), aPosition: gl.getAttribLocation(glProgram, 'position'), modelScale: gl.getUniformLocation(glProgram, 'modelScale'), modelTranslate: gl.getUniformLocation(glProgram, 'modelTranslate'), viewScale: gl.getUniformLocation(glProgram, 'viewScale'), viewTranslate: gl.getUniformLocation(glProgram, 'viewTranslate'), projection: gl.getUniformLocation(glProgram, 'projection') }; } return undefined; } /** * @param {number} size * @param {{borders: boolean, threshold: number, from: number?, to: number?, unitScale: number}} options * @returns {number[]} */ export function getLinesToDraw (size, options = {}) { const { borders = true, threshold = 10, from = 0, to = size, unitScale = 1 } = options; const aStep = Math.floor(2 ** Math.max(0, Math.log2(threshold / unitScale))); const fromCorrected = Math.min(size, Math.max(0, Math.ceil(from))); const toCorrected = Math.min(size, Math.max(0, Math.ceil(to))); const result = new Set(borders ? [fromCorrected, toCorrected] : [fromCorrected] ); for (let i = fromCorrected + aStep; i <= toCorrected; i += aStep) { result.add(i); } return [...result]; }