all files migrated; tweaks needed

This commit is contained in:
Lincoln Stein
2023-03-03 00:02:15 -05:00
parent 3f0b0f3250
commit 6a990565ff
496 changed files with 276 additions and 934 deletions

View File

@ -0,0 +1,17 @@
import { Vector2d } from 'konva/lib/types';
const calculateCoordinates = (
containerWidth: number,
containerHeight: number,
containerX: number,
containerY: number,
contentWidth: number,
contentHeight: number,
scale: number
): Vector2d => {
const x = containerWidth / 2 - (containerX + contentWidth / 2) * scale;
const y = containerHeight / 2 - (containerY + contentHeight / 2) * scale;
return { x, y };
};
export default calculateCoordinates;

View File

@ -0,0 +1,14 @@
const calculateScale = (
containerWidth: number,
containerHeight: number,
contentWidth: number,
contentHeight: number,
padding = 0.95
): number => {
const scaleX = (containerWidth * padding) / contentWidth;
const scaleY = (containerHeight * padding) / contentHeight;
const scaleFit = Math.min(1, Math.min(scaleX, scaleY));
return scaleFit;
};
export default calculateScale;

View File

@ -0,0 +1,16 @@
import { RgbaColor, RgbColor } from 'react-colorful';
export const rgbaColorToString = (color: RgbaColor): string => {
const { r, g, b, a } = color;
return `rgba(${r}, ${g}, ${b}, ${a})`;
};
export const rgbaColorToRgbString = (color: RgbaColor): string => {
const { r, g, b } = color;
return `rgba(${r}, ${g}, ${b})`;
};
export const rgbColorToString = (color: RgbColor): string => {
const { r, g, b } = color;
return `rgba(${r}, ${g}, ${b})`;
};

View File

@ -0,0 +1,17 @@
// bounding box anchor size
export const TRANSFORMER_ANCHOR_SIZE = 15;
// canvas wheel zoom exponential scale factor
export const CANVAS_SCALE_BY = 0.999;
// minimum (furthest-zoomed-out) scale
export const MIN_CANVAS_SCALE = 0.1;
// maximum (furthest-zoomed-in) scale
export const MAX_CANVAS_SCALE = 20;
// padding given to initial image/bounding box when stage view is reset
export const STAGE_PADDING_PERCENTAGE = 0.95;
export const COLOR_PICKER_SIZE = 30;
export const COLOR_PICKER_STROKE_RADIUS = 10;

View File

@ -0,0 +1,34 @@
/**
* Copies an image to the clipboard by drawing it to a canvas and then
* calling toBlob() on the canvas.
*/
const copyImage = (url: string, width: number, height: number) => {
const imageElement = document.createElement('img');
imageElement.addEventListener('load', () => {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const context = canvas.getContext('2d');
if (!context) return;
context.drawImage(imageElement, 0, 0);
canvas.toBlob((blob) => {
blob &&
navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob,
}),
]);
});
canvas.remove();
imageElement.remove();
});
imageElement.src = url;
};
export default copyImage;

View File

@ -0,0 +1,14 @@
/**
* Downloads a file, given its URL.
*/
const downloadFile = (url: string) => {
const a = document.createElement('a');
a.href = url;
a.download = '';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
a.remove();
};
export default downloadFile;

View File

@ -0,0 +1,10 @@
import { Vector2d } from 'konva/lib/types';
const floorCoordinates = (coord: Vector2d): Vector2d => {
return {
x: Math.floor(coord.x),
y: Math.floor(coord.y),
};
};
export default floorCoordinates;

View File

@ -0,0 +1,64 @@
import { CanvasMaskLine } from 'features/canvas/store/canvasTypes';
import Konva from 'konva';
import { IRect } from 'konva/lib/types';
/**
* Generating a mask image from InpaintingCanvas.tsx is not as simple
* as calling toDataURL() on the canvas, because the mask may be represented
* by colored lines or transparency, or the user may have inverted the mask
* display.
*
* So we need to regenerate the mask image by creating an offscreen canvas,
* drawing the mask and compositing everything correctly to output a valid
* mask image.
*/
const generateMask = (lines: CanvasMaskLine[], boundingBox: IRect): string => {
// create an offscreen canvas and add the mask to it
const { width, height } = boundingBox;
const offscreenContainer = document.createElement('div');
const stage = new Konva.Stage({
container: offscreenContainer,
width: width,
height: height,
});
const baseLayer = new Konva.Layer();
const maskLayer = new Konva.Layer();
// composite the image onto the mask layer
baseLayer.add(
new Konva.Rect({
...boundingBox,
fill: 'white',
})
);
lines.forEach((line) =>
maskLayer.add(
new Konva.Line({
points: line.points,
stroke: 'black',
strokeWidth: line.strokeWidth * 2,
tension: 0,
lineCap: 'round',
lineJoin: 'round',
shadowForStrokeEnabled: false,
globalCompositeOperation:
line.tool === 'brush' ? 'source-over' : 'destination-out',
})
)
);
stage.add(baseLayer);
stage.add(maskLayer);
const dataURL = stage.toDataURL({ ...boundingBox });
offscreenContainer.remove();
return dataURL;
};
export default generateMask;

View File

@ -0,0 +1,39 @@
import { roundToMultiple } from 'common/util/roundDownToMultiple';
import { Dimensions } from '../store/canvasTypes';
const getScaledBoundingBoxDimensions = (dimensions: Dimensions) => {
const { width, height } = dimensions;
const scaledDimensions = { width, height };
const targetArea = 512 * 512;
const aspectRatio = width / height;
let currentArea = width * height;
let maxDimension = 448;
while (currentArea < targetArea) {
maxDimension += 64;
if (width === height) {
scaledDimensions.width = 512;
scaledDimensions.height = 512;
break;
} else {
if (aspectRatio > 1) {
scaledDimensions.width = maxDimension;
scaledDimensions.height = roundToMultiple(
maxDimension / aspectRatio,
64
);
} else if (aspectRatio < 1) {
scaledDimensions.height = maxDimension;
scaledDimensions.width = roundToMultiple(
maxDimension * aspectRatio,
64
);
}
currentArea = scaledDimensions.width * scaledDimensions.height;
}
}
return scaledDimensions;
};
export default getScaledBoundingBoxDimensions;

View File

@ -0,0 +1,18 @@
import { Stage } from 'konva/lib/Stage';
const getScaledCursorPosition = (stage: Stage) => {
const pointerPosition = stage.getPointerPosition();
const stageTransform = stage.getAbsoluteTransform().copy();
if (!pointerPosition || !stageTransform) return;
const scaledCursorPosition = stageTransform.invert().point(pointerPosition);
return {
x: scaledCursorPosition.x,
y: scaledCursorPosition.y,
};
};
export default getScaledCursorPosition;

View File

@ -0,0 +1,16 @@
import Konva from 'konva';
let canvasBaseLayer: Konva.Layer | null = null;
let canvasStage: Konva.Stage | null = null;
export const setCanvasBaseLayer = (layer: Konva.Layer) => {
canvasBaseLayer = layer;
};
export const getCanvasBaseLayer = () => canvasBaseLayer;
export const setCanvasStage = (stage: Konva.Stage) => {
canvasStage = stage;
};
export const getCanvasStage = () => canvasStage;

View File

@ -0,0 +1,53 @@
import Konva from 'konva';
import { IRect, Vector2d } from 'konva/lib/types';
const layerToDataURL = (
layer: Konva.Layer,
stageScale: number,
stageCoordinates: Vector2d,
boundingBox?: IRect
) => {
const tempScale = layer.scale();
const relativeClientRect = layer.getClientRect({
relativeTo: layer.getParent(),
});
// Scale the canvas before getting it as a Blob
layer.scale({
x: 1 / stageScale,
y: 1 / stageScale,
});
const { x, y, width, height } = layer.getClientRect();
const dataURLBoundingBox = boundingBox
? {
x: boundingBox.x + stageCoordinates.x,
y: boundingBox.y + stageCoordinates.y,
width: boundingBox.width,
height: boundingBox.height,
}
: {
x: x,
y: y,
width: width,
height: height,
};
const dataURL = layer.toDataURL(dataURLBoundingBox);
// Unscale the canvas
layer.scale(tempScale);
return {
dataURL,
boundingBox: {
x: relativeClientRect.x,
y: relativeClientRect.y,
width: width,
height: height,
},
};
};
export default layerToDataURL;

View File

@ -0,0 +1,11 @@
import { roundToMultiple } from 'common/util/roundDownToMultiple';
import { Dimensions } from '../store/canvasTypes';
const roundDimensionsTo64 = (dimensions: Dimensions): Dimensions => {
return {
width: roundToMultiple(dimensions.width, 64),
height: roundToMultiple(dimensions.height, 64),
};
};
export default roundDimensionsTo64;

View File

@ -0,0 +1,5 @@
const roundToHundreth = (val: number): number => {
return Math.round(val * 100) / 100;
};
export default roundToHundreth;