Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(TS) remove ts-nocheck from image class #9036

Merged
merged 14 commits into from
Jul 10, 2023
8 changes: 6 additions & 2 deletions src/canvas/StaticCanvas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { config } from '../config';
import { CENTER, iMatrix, VERSION } from '../constants';
import type { CanvasEvents, StaticCanvasEvents } from '../EventTypeDefs';
import type {
BaseFabricObject,
CanvasEvents,
StaticCanvasEvents,
} from '../EventTypeDefs';
import type { Gradient } from '../gradient/Gradient';
import { createCollectionMixin } from '../Collection';
import { CommonMethods } from '../CommonMethods';
Expand Down Expand Up @@ -1414,7 +1418,7 @@ export class StaticCanvas<
this.renderOnAddRemove = false;

return Promise.all([
enlivenObjects(objects, {
enlivenObjects<BaseFabricObject>(objects, {
reviver,
signal,
}),
Expand Down
3 changes: 2 additions & 1 deletion src/mixins/eraser_brush.mixin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//@ts-nocheck
import { Point } from '../Point';
import { FabricObject } from '../shapes/Object/FabricObject';
import { uid } from '../util/internals/uid';

(function (global) {
Expand Down Expand Up @@ -293,7 +294,7 @@ import { uid } from '../util/internals/uid';
options = fabric.util.object.clone(object, true);
delete options.objects;
return Promise.all([
fabric.util.enlivenObjects(objects),
fabric.util.enlivenObjects<FabricObject>(objects),
fabric.util.enlivenObjectEnlivables(options),
]).then(function (enlivedProps) {
return new fabric.Eraser(
Expand Down
2 changes: 1 addition & 1 deletion src/shapes/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ export class Group extends createCollectionMixin(
...options
}: T) {
return Promise.all([
enlivenObjects(objects),
enlivenObjects<FabricObject>(objects),
enlivenObjectEnlivables(options),
]).then(
([objects, hydratedOptions]) =>
Expand Down
86 changes: 41 additions & 45 deletions src/shapes/Image.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// @ts-nocheck
import { getFabricDocument, getEnv } from '../env';
import type { BaseFilter } from '../filters/BaseFilter';
import { getFilterBackend } from '../filters/FilterBackend';
import { SHARED_ATTRIBUTES } from '../parser/attributes';
import { parseAttributes } from '../parser/parseAttributes';
import type { TClassProperties, TSize } from '../typedefs';
import type { TClassProperties, TCrossOrigin, TSize } from '../typedefs';
import type { Abortable } from '../typedefs';
import { uid } from '../util/internals/uid';
import { createCanvasElement } from '../util/misc/dom';
Expand All @@ -26,6 +25,7 @@ import type {
import type { ObjectEvents } from '../EventTypeDefs';
import { WebGLFilterBackend } from '../filters/WebGLFilterBackend';
import { NONE } from '../constants';
import { getDocumentFromElement } from '../util/dom_misc';

// @todo Would be nice to have filtering code not imported directly.

Expand All @@ -40,7 +40,6 @@ interface UniqueImageProps {
cropX: number;
cropY: number;
imageSmoothing: boolean;
crossOrigin: string | null;
filters: BaseFilter[];
resizeFilter?: BaseFilter;
}
Expand All @@ -57,7 +56,7 @@ export const imageDefaultValues: Partial<UniqueImageProps> &

export interface SerializedImageProps extends SerializedObjectProps {
src: string;
crossOrigin: string | null;
crossOrigin: TCrossOrigin;
filters: any[];
resizeFilter?: any;
cropX: number;
Expand Down Expand Up @@ -168,7 +167,7 @@ export class Image<

protected declare _element: ImageSource;
protected declare _originalElement: ImageSource;
protected declare _filteredEl: ImageSource;
protected declare _filteredEl?: HTMLCanvasElement;

static type = 'Image';

Expand Down Expand Up @@ -199,7 +198,7 @@ export class Image<
this.setElement(
typeof arg0 === 'string'
? ((
(this.canvas && getElementDocument(this.canvas.getElement())) ||
(this.canvas && getDocumentFromElement(this.canvas.getElement())) ||
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buuuug

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TS helps sometimes

getFabricDocument()
).getElementById(arg0) as ImageSource)
: arg0,
Expand Down Expand Up @@ -357,12 +356,12 @@ export class Image<
* of the instance
*/
_toSVG() {
const imageMarkup = [],
const imageMarkup: string[] = [],
element = this._element,
x = -this.width / 2,
y = -this.height / 2;
let svgString = [],
strokeSvg,
let svgString: string[] = [],
strokeSvg: string[] = [],
clipPath = '',
imageRendering = '';
if (!element) {
Expand All @@ -386,28 +385,21 @@ export class Image<
clipPath = ' clip-path="url(#imageCrop_' + clipPathId + ')" ';
}
if (!this.imageSmoothing) {
imageRendering = '" image-rendering="optimizeSpeed';
imageRendering = ' image-rendering="optimizeSpeed"';
}
imageMarkup.push(
'\t<image ',
'COMMON_PARTS',
'xlink:href="',
this.getSvgSrc(true),
'" x="',
x - this.cropX,
'" y="',
y - this.cropY,
// we're essentially moving origin of transformation from top/left corner to the center of the shape
// by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
// so that object's center aligns with container's left/top
'" width="',
element.width || element.naturalWidth,
'" height="',
element.height || element.naturalHeight,
imageRendering,
'"',
clipPath,
'></image>\n'
`xlink:href="${this.getSvgSrc(true)}" x="${x - this.cropX}" y="${
y - this.cropY
// we're essentially moving origin of transformation from top/left corner to the center of the shape
// by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
// so that object's center aligns with container's left/top
}" width="${
element.width || (element as HTMLImageElement).naturalWidth
}" height="${
element.height || (element as HTMLImageElement).naturalHeight
}"${imageRendering}${clipPath}></image>\n`
);

if (this.stroke || this.strokeDashArray) {
Expand Down Expand Up @@ -445,14 +437,14 @@ export class Image<
getSrc(filtered?: boolean): string {
const element = filtered ? this._element : this._originalElement;
if (element) {
if (element.toDataURL) {
return element.toDataURL();
if ((element as HTMLCanvasElement).toDataURL) {
return (element as HTMLCanvasElement).toDataURL();
}

if (this.srcFromAttribute) {
return element.getAttribute('src');
return element.getAttribute('src') || '';
} else {
return element.src;
return (element as HTMLImageElement).src;
}
} else {
return this.src || '';
Expand Down Expand Up @@ -541,15 +533,18 @@ export class Image<

if (filters.length === 0) {
this._element = this._originalElement;
this._filteredEl = null;
// this is unsafe and needs to be rethinkend
this._filteredEl = undefined;
this._filterScalingX = 1;
this._filterScalingY = 1;
return;
}

const imgElement = this._originalElement,
sourceWidth = imgElement.naturalWidth || imgElement.width,
sourceHeight = imgElement.naturalHeight || imgElement.height;
sourceWidth =
(imgElement as HTMLImageElement).naturalWidth || imgElement.width,
sourceHeight =
(imgElement as HTMLImageElement).naturalHeight || imgElement.height;

if (this._element === this._originalElement) {
// if the element is the same we need to create a new element
Expand All @@ -563,7 +558,7 @@ export class Image<
// also dereference the eventual resized _element
this._element = this._filteredEl;
this._filteredEl
.getContext('2d')
.getContext('2d')!
.clearRect(0, 0, sourceWidth, sourceHeight);
// we also need to resize again at next renderAll, so remove saved _lastScaleX/Y
this._lastScaleX = 1;
Expand Down Expand Up @@ -636,8 +631,11 @@ export class Image<
// crop values cannot be lesser than 0.
cropX = Math.max(this.cropX, 0),
cropY = Math.max(this.cropY, 0),
elWidth = elementToDraw.naturalWidth || elementToDraw.width,
elHeight = elementToDraw.naturalHeight || elementToDraw.height,
elWidth =
(elementToDraw as HTMLImageElement).naturalWidth || elementToDraw.width,
elHeight =
(elementToDraw as HTMLImageElement).naturalHeight ||
elementToDraw.height,
sX = cropX * scaleX,
sY = cropY * scaleY,
// the width height cannot exceed element width/height, starting from the crop offset.
Expand Down Expand Up @@ -793,16 +791,14 @@ export class Image<
options: Abortable = {}
) {
return Promise.all([
loadImage(src, { ...options, crossOrigin }),
f && enlivenObjects(f, options),
loadImage(src!, { ...options, crossOrigin }),
f && enlivenObjects<BaseFilter>(f, options),
// TODO: redundant - handled by enlivenObjectEnlivables
rf && enlivenObjects([rf], options),
rf && enlivenObjects<BaseFilter>([rf], options),
enlivenObjectEnlivables(object, options),
]).then(([el, filters = [], [resizeFilter] = [], hydratedProps = {}]) => {
return new this(el, {
...object,
src,
crossOrigin,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i suspect this is the cause of some breakage in image.clone i can't explain.

filters,
resizeFilter,
...hydratedProps,
Expand All @@ -817,11 +813,11 @@ export class Image<
* @param {LoadImageOptions} [options] Options object
* @returns {Promise<Image>}
*/
static fromURL<T extends TProps<SerializedImageProps>>(
static fromURL(
url: string,
options: T & LoadImageOptions = {}
{ crossOrigin = 'anonymous', signal }: LoadImageOptions = {}
): Promise<Image> {
return loadImage(url, options).then((img) => new this(img, options));
return loadImage(url, { crossOrigin, signal }).then((img) => new this(img));
}

/**
Expand Down
28 changes: 17 additions & 11 deletions src/util/misc/objectEnlive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import type { FabricObject } from '../../shapes/Object/FabricObject';
import type { Abortable, TCrossOrigin, TFiller } from '../../typedefs';
import { createImage } from './dom';
import { classRegistry } from '../../ClassRegistry';
import { BaseFilter } from '../../filters/BaseFilter';
import { BaseFabricObject } from 'fabric/node';

export type LoadImageOptions = Abortable & {
/**
Expand Down Expand Up @@ -58,9 +60,9 @@ export type EnlivenObjectOptions = Abortable & {
* Method for further parsing of object elements,
* called after each fabric object created.
*/
reviver?: (
reviver?: <T extends BaseFabricObject | FabricObject | BaseFilter>(
serializedObj: Record<string, any>,
instance: FabricObject
instance: T
) => void;
};

Expand All @@ -73,12 +75,14 @@ export type EnlivenObjectOptions = Abortable & {
* @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal
* @returns {Promise<FabricObject[]>}
*/
export const enlivenObjects = (
export const enlivenObjects = <
T extends BaseFabricObject | FabricObject | BaseFilter
>(
objects: any[],
{ signal, reviver = noop }: EnlivenObjectOptions = {}
) =>
new Promise<FabricObject[]>((resolve, reject) => {
const instances: FabricObject[] = [];
new Promise<T[]>((resolve, reject) => {
const instances: T[] = [];
signal && signal.addEventListener('abort', reject, { once: true });
Promise.all(
objects.map((obj) =>
Expand All @@ -88,8 +92,8 @@ export const enlivenObjects = (
signal,
reviver,
})
.then((fabricInstance: FabricObject) => {
reviver(obj, fabricInstance);
.then((fabricInstance: T) => {
reviver<T>(obj, fabricInstance);
instances.push(fabricInstance);
return fabricInstance;
})
Expand Down Expand Up @@ -135,10 +139,12 @@ export const enlivenObjectEnlivables = <
}
// clipPath
if (value.type) {
return enlivenObjects([value], { signal }).then(([enlived]) => {
instances.push(enlived);
return enlived;
});
return enlivenObjects<FabricObject>([value], { signal }).then(
([enlived]) => {
instances.push(enlived);
return enlived;
}
);
}
// pattern
if (value.source) {
Expand Down