Skip to content

Commit

Permalink
Merge pull request #44 from atlas-viewer/feature/v2.0.9
Browse files Browse the repository at this point in the history
v2.0.9
  • Loading branch information
stephenwf authored Apr 3, 2024
2 parents fb2dba9 + 23643d7 commit e92470f
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/__tests__/clean-objects/traits/generic-object.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from '../../../clean-objects/traits/generic-object';
import { DnaFactory } from '@atlas-viewer/dna';

describe('generic objects', function () {
describe.skip('generic objects', function () {
test('is generic', () => {
expect(isGeneric({})).toEqual(false);
expect(isGeneric(genericObjectDefaults('node'))).toEqual(true);
Expand Down
2 changes: 1 addition & 1 deletion src/clean-objects/traits/evented.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export function removeEventListener<Name extends SupportedEventNames>(
}

export function isEvented(t: unknown): t is Evented {
return !!(t && (t as any).events.handlers);
return !!(t && (t as any).events && (t as any).events.handlers);
}

export function dispatchEvent<Name extends SupportedEventFunctionNames | SupportedEventNames>(
Expand Down
1 change: 1 addition & 0 deletions src/clean-objects/traits/generic-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export function applyGenericObjectProps(
} else {
toObject.points.set(targetPoints);
}

toObject.display.scale = scale;
toObject.display.width = target.width / scale;
toObject.display.height = target.height / scale;
Expand Down
63 changes: 48 additions & 15 deletions src/modules/canvas-renderer/canvas-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import { TiledImage } from '../../spacial-content/tiled-image';
import { Renderer } from '../../renderer/renderer';
import { World } from '../../world';
import { Box } from '../../objects/box';
import { h } from '../../clean-objects/runtime/h';
import LRUCache from 'lru-cache';
import { Geometry } from '../../objects/geometry';
import { HookOptions } from 'src/standalone';

const shadowRegex =
/(-?[0-9]+(px|em)\s+|0\s+)(-?[0-9]+(px|em)\s+|0\s+)(-?[0-9]+(px|em)\s+|0\s+)?(-?[0-9]+(px|em)\s+|0\s+)?(.*)/g;
const shadowRegexCache: any = {};
const isFirefox =
typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().includes('firefox');

export type CanvasRendererOptions = {
beforeFrame?: (delta: number) => void;
Expand Down Expand Up @@ -89,7 +90,7 @@ export class CanvasRenderer implements Renderer {
currentTask: Promise<any> = Promise.resolve();
tasksRunning = 0;
stats?: Stats;
averageJobTime = 1000; // ms
averageJobTime = 64; // ms
lastKnownScale = 1;
visible: Array<SpacialContent> = [];
previousVisible: Array<SpacialContent> = [];
Expand Down Expand Up @@ -258,9 +259,17 @@ export class CanvasRenderer implements Renderer {
clearInterval(this._scheduled);
this._scheduled = 0;
}

let parallel = this.parallelTasks || 1;

if (!this.firstMeaningfulPaint && this.loadingQueue.length) {
parallel = this.loadingQueue.length;
}
// And here's our working being called. Since JS is blocking, this will complete
// before the next tick, so its possible that this could be more than 1ms.
this._worker();
for (let i = 0; i <= parallel; i++) {
this._worker();
}
};

getScale(width: number, height: number, dpi?: boolean): number {
Expand Down Expand Up @@ -457,17 +466,31 @@ export class CanvasRenderer implements Renderer {
);
}
} else {
this.ctx.drawImage(
canvasToPaint,
0, // paint.display.points[index * 5 + 1],
0, // paint.display.points[index * 5 + 2],
paint.display.points[index * 5 + 3] - paint.display.points[index * 5 + 1],
paint.display.points[index * 5 + 4] - paint.display.points[index * 5 + 2],
x,
y,
width + Number.MIN_VALUE,
height + Number.MIN_VALUE
);
if (isFirefox) {
this.ctx.drawImage(
canvasToPaint,
0, // paint.display.points[index * 5 + 1],
0, // paint.display.points[index * 5 + 2],
paint.display.points[index * 5 + 3] - paint.display.points[index * 5 + 1],
paint.display.points[index * 5 + 4] - paint.display.points[index * 5 + 2],
x,
y,
width + 1,
height + 1
);
} else {
this.ctx.drawImage(
canvasToPaint,
0, // paint.display.points[index * 5 + 1],
0, // paint.display.points[index * 5 + 2],
paint.display.points[index * 5 + 3] - paint.display.points[index * 5 + 1],
paint.display.points[index * 5 + 4] - paint.display.points[index * 5 + 2],
x,
y,
width + Number.MIN_VALUE + 0.5,
height + Number.MIN_VALUE + 0.5
);
}
}
}
} catch (err) {
Expand All @@ -482,6 +505,7 @@ export class CanvasRenderer implements Renderer {
const isBox = paint instanceof Box && this.options.box;
const isGeometry = paint instanceof Geometry && this.options.polygon;
if ((isBox || isGeometry) && !paint.props.className && !paint.props.html && !paint.props.href) {
this.visible.push(paint);
if (paint.props.style) {
const style = Object.assign(
//
Expand Down Expand Up @@ -782,7 +806,16 @@ export class CanvasRenderer implements Renderer {
this.imagesPending === 0 &&
this.loadingQueue.length === 0 &&
this.tasksRunning === 0; /*&& this.visible.length > 0*/
if (!this.firstMeaningfulPaint && ready) {

if (!ready && this.visible.length === 0) {
// If its still not ready by 500ms, force it to be.
setTimeout(() => {
this.canvas.style.opacity = '1';
this.firstMeaningfulPaint = true;
}, 500);
}

if (!this.firstMeaningfulPaint && ready && this.visible.length) {
// Fade in the canvas?
this.canvas.style.opacity = '1';
// We've not rendered yet, can we render this frame?
Expand Down
7 changes: 7 additions & 0 deletions src/modules/react-reconciler/components/ImageService.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { ReactNode, useEffect, useState } from 'react';
import { GetTile } from '../../iiif/shared';
import { TileSet } from './TileSet';
import { getTileFromImageService } from '../../iiif/get-tiles';
import { CompositeResourceProps } from '../../../spacial-content';

export const ImageService: React.FC<{
id: string;
Expand All @@ -13,6 +14,9 @@ export const ImageService: React.FC<{
scale?: number;
children?: ReactNode;
crop?: any;
enableSizes?: boolean;
enableThumbnail?: boolean;
renderOptions?: CompositeResourceProps;
}> = (props) => {
const [tiles, setTile] = useState<GetTile | undefined>();

Expand All @@ -33,6 +37,9 @@ export const ImageService: React.FC<{
height={props.crop?.height || props.height}
rotation={props.rotation}
crop={props.crop}
enableSizes={props.enableSizes}
enableThumbnail={props.enableThumbnail}
renderOptions={props.renderOptions}
>
{props.children}
</TileSet>
Expand Down
3 changes: 3 additions & 0 deletions src/modules/react-reconciler/components/TileSet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { ReactNode, useMemo } from 'react';
import { GetTile } from '../../iiif/shared';
import { CompositeResourceProps } from '../../../spacial-content';

export const TileSet: React.FC<{
tiles: GetTile;
Expand All @@ -13,6 +14,7 @@ export const TileSet: React.FC<{
enableThumbnail?: boolean;
enableSizes?: boolean;
onClick?: (e: any) => void;
renderOptions?: CompositeResourceProps;
}> = (props) => {
const scale = props.width / (props.crop?.width || props.tiles.width);
const tiles = props.tiles.imageService.tiles || [];
Expand Down Expand Up @@ -44,6 +46,7 @@ export const TileSet: React.FC<{
width={props.crop?.width || props.tiles.width}
height={props.crop?.height || props.tiles.height}
crop={props.crop}
renderOptions={props.renderOptions}
>
{enableThumbnail && props.tiles.thumbnail ? (
<world-image
Expand Down
1 change: 1 addition & 0 deletions src/modules/react-reconciler/reconciler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ function createInstance(
width: props.width,
height: props.height,
images: [],
renderOptions: props.renderOptions,
});
break;
case 'tiledImage':
Expand Down
2 changes: 2 additions & 0 deletions src/modules/react-reconciler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { UpdateTextureFunction } from '../../spacial-content/image-texture';
import { BoxStyle } from '../../objects/box';
import { EventListenerProps } from '../../clean-objects/traits/evented';
import { GeometryProps } from '../../objects/geometry';
import { CompositeResourceProps } from '../../spacial-content/composite-resource';

type BaseElement = {
id?: string;
Expand Down Expand Up @@ -68,6 +69,7 @@ declare global {
height: number;
children?: React.ReactNode;
crop?: any;
renderOptions?: CompositeResourceProps;
} & AllEvents;
tiledImage: BaseElement & {
uri: string;
Expand Down
19 changes: 9 additions & 10 deletions src/modules/static-renderer/static-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ type StaticRendererOptions = {
background: string;
};

// @todo make this configurable.
const MIN = 1 + Number.MIN_VALUE;

export class StaticRenderer implements Renderer {
container: HTMLElement;
width: number;
Expand Down Expand Up @@ -165,12 +168,10 @@ export class StaticRenderer implements Renderer {
element.className =
this.options.imageClass +
' ' +
this.stylesheet.addStylesheet(
`width:${(width + Number.MIN_VALUE).toFixed(2)}px;height:${(height + Number.MIN_VALUE).toFixed(2)}px;`
);
this.stylesheet.addStylesheet(`width:${(width + MIN).toFixed(2)}px;height:${(height + MIN).toFixed(2)}px;`);
} else {
element.style.width = `${width + Number.MIN_VALUE}px`;
element.style.height = `${height + Number.MIN_VALUE}px`;
element.style.width = `${width + MIN}px`;
element.style.height = `${height + MIN}px`;
}
element.style.transform = `translate(${x}px, ${y}px)`;
}
Expand Down Expand Up @@ -198,12 +199,10 @@ export class StaticRenderer implements Renderer {
element.className =
this.options.imageClass +
' ' +
this.stylesheet.addStylesheet(
`width:${(width + Number.MIN_VALUE).toFixed(2)}px;height:${(height + Number.MIN_VALUE).toFixed(2)}px;`
);
this.stylesheet.addStylesheet(`width:${(width + MIN).toFixed(2)}px;height:${(height + MIN).toFixed(2)}px;`);
} else {
element.style.width = `${width + Number.MIN_VALUE}px`;
element.style.height = `${height + Number.MIN_VALUE}px`;
element.style.width = `${width + MIN}px`;
element.style.height = `${height + MIN}px`;
}
element.style.transform = `translate(${x}px, ${y}px)`;
}
Expand Down
33 changes: 17 additions & 16 deletions src/renderer/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type UnwrapHook<T> = T extends Array<infer R> ? R : never;
type UnwrapHookArg<T> = T extends Array<(arg: infer R) => any> ? R : never;

export type ViewerMode = 'static' | 'explore' | 'sketch';
const MIN = Number.MIN_VALUE + 1;

export type ViewerFilters = {
grayscale: number;
Expand Down Expand Up @@ -284,18 +285,18 @@ export class Runtime {
const fullWidth = ar * target.height;
const space = (fullWidth - target.width) / 2;

this.target[1] = -space + target.x;
this.target[2] = target.y;
this.target[3] = fullWidth - space + target.x;
this.target[4] = target.height + target.y;
this.target[1] = Math.round(-space + target.x);
this.target[2] = Math.round(target.y);
this.target[3] = Math.round(fullWidth - space + target.x);
this.target[4] = Math.round(target.height + target.y);
} else {
const fullHeight = target.width / ar;
const space = (fullHeight - target.height) / 2;

this.target[1] = target.x;
this.target[2] = target.y - space;
this.target[3] = target.x + target.width;
this.target[4] = target.y + fullHeight - space;
this.target[1] = Math.round(target.x);
this.target[2] = Math.round(target.y - space);
this.target[3] = Math.round(target.x + target.width);
this.target[4] = Math.round(target.y + fullHeight - space);
}

this.constrainBounds(this.target);
Expand Down Expand Up @@ -420,8 +421,8 @@ export class Runtime {
* @param data
*/
setViewport = (data: { x?: number; y?: number; width?: number; height?: number }) => {
const x = typeof data.x === 'undefined' ? this.target[1] : data.x;
const y = typeof data.y === 'undefined' ? this.target[2] : data.y;
const x = Math.round(typeof data.x === 'undefined' ? this.target[1] : data.x);
const y = Math.round(typeof data.y === 'undefined' ? this.target[2] : data.y);

if (data.width) {
this.target[3] = x + data.width;
Expand Down Expand Up @@ -449,8 +450,8 @@ export class Runtime {

let isConstrained = false;
const constrained = ref ? target : dna(target);
const width = target[3] - target[1];
const height = target[4] - target[2];
const width = Math.round(target[3] - target[1]);
const height = Math.round(target[4] - target[2]);

if (minX > target[1]) {
isConstrained = true;
Expand Down Expand Up @@ -550,10 +551,10 @@ export class Runtime {
// const minY = addConstraintPaddingY ? yA : yB;
// const maxY = addConstraintPaddingY ? yC : yD;

const maxX = Math.max(xB, xD);
const minX = Math.min(xB, xD);
const maxY = Math.max(yB, yD);
const minY = Math.min(yB, yD);
const maxX = Math.round(Math.max(xB, xD));
const minX = Math.round(Math.min(xB, xD));
const maxY = Math.round(Math.max(yB, yD));
const minY = Math.round(Math.min(yB, yD));

return { minX, maxX, minY, maxY } as const;
}
Expand Down
8 changes: 4 additions & 4 deletions src/spacial-content/composite-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type RenderOptions = {
quality: number;
};

type CompositeResourceProps = RenderOptions;
export type CompositeResourceProps = RenderOptions;

export class CompositeResource
extends AbstractContent
Expand Down Expand Up @@ -59,10 +59,10 @@ export class CompositeResource
};
this.renderOptions = {
renderSmallestFallback: true,
renderLayers: 3,
renderLayers: 2,
minSize: 255,
maxImageSize: 1024,
quality: 1.2,
quality: 1.75,
...(data.renderOptions || {}),
};

Expand Down Expand Up @@ -228,7 +228,7 @@ export class CompositeResource
}
const smallestIdx = toPaintIdx[0];
if (this.renderOptions.renderLayers) {
toPaintIdx = toPaintIdx.slice(-this.renderOptions.renderLayers);
toPaintIdx = toPaintIdx.slice(-Math.min(toPaintIdx.length, this.renderOptions.renderLayers));
}

if (this.renderOptions.renderSmallestFallback && toPaintIdx.indexOf(smallestIdx) === -1) {
Expand Down
Loading

0 comments on commit e92470f

Please sign in to comment.