Skip to content

Commit

Permalink
fix: markdirty & scrolling was conflict before, so scrolling & dirty …
Browse files Browse the repository at this point in the history
…did not refresh whole viewport
  • Loading branch information
lumixraku committed May 16, 2024
1 parent 492ab67 commit 9a7c24b
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 96 deletions.
2 changes: 1 addition & 1 deletion packages/engine-render/src/basics/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ export function inRowViewRanges(ranges: IRange[], rowIndex: number) {
}

/**
* 如果 range 有相交, 那么扩展到第一个 range 中.
* 如果 range 有相交, 那么扩展到第一组 range 中.
* @param ranges
*/
export function mergeRangeIfIntersects(mainRanges: IRange[], ranges: IRange[]) {
Expand Down
5 changes: 4 additions & 1 deletion packages/engine-render/src/basics/vector2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,10 @@ export interface IViewportInfo {
*/
viewPortPosition: IBoundRectNoAngle;
viewPortKey: string;
isDirty?: boolean;
/**
* 后续会通过 number 来表示究竟是什么原因导致的标脏 这里采用二进制数值方便运算
*/
isDirty?: number;
isForceDirty?: boolean;

allowCache?: boolean;
Expand Down
4 changes: 2 additions & 2 deletions packages/engine-render/src/canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@ export class Canvas {
// this.setHeight(height || 0);
this._pixelRatio = pixelRatioParam || getDevicePixelRatio();

if (width) {
if (width !== undefined) {
this.getCanvasEle().width = width * this._pixelRatio;

this._width = this.getCanvasEle().width / this._pixelRatio;

this.getCanvasEle().style.width = `${this._width}px`;
}

if (height) {
if (height !== undefined) {
this.getCanvasEle().height = height * this._pixelRatio;

this._height = this.getCanvasEle().height / this._pixelRatio;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class Font extends SheetExtension {
/**
* Incremental content rendering for texture mapping
* startRow endRow 和 diffRanges 在 row 上不相交, 那么返回不渲染
* (因为可以走贴图)
* PS 如果这个单元格并不在 merge 区域内, mergeInfo start 和 end 就是单元格本身
*/
if (!this.isRowInDiffRanges(mergeInfo.startRow, mergeInfo.endRow, diffRanges)) {
return true;
Expand Down Expand Up @@ -346,7 +346,7 @@ export class Font extends SheetExtension {

ctx.rectByPrecision(startX, startY, endX - startX, endY - startY);
ctx.clip();
ctx.clearRectForTexture(startX, startY, endX - startX, endY - startY);
// ctx.clearRectForTexture(startX, startY, endX - startX, endY - startY);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1378,8 +1378,8 @@ export class SpreadsheetSkeleton extends Skeleton {
const row_ed = searchArray(rowHeightAccumulation, Math.round(viewBound.bottom) - this.columnHeaderHeightAndMarginTop);

if (row_st === -1 && row_ed === 0) {
dataset_row_st = -1;
dataset_row_ed = -1;
dataset_row_st = 0;
dataset_row_ed = 0;
} else {
if (row_st === -1) {
dataset_row_st = 0;
Expand All @@ -1400,8 +1400,8 @@ export class SpreadsheetSkeleton extends Skeleton {
const col_ed = searchArray(columnWidthAccumulation, Math.round(viewBound.right) - this.rowHeaderWidthAndMarginLeft);

if (col_st === -1 && col_ed === 0) {
dataset_col_st = -1;
dataset_col_ed = -1;
dataset_col_st = 0;
dataset_col_ed = 0;
} else {
if (col_st === -1) {
dataset_col_st = 0;
Expand Down
31 changes: 16 additions & 15 deletions packages/engine-render/src/components/sheets/spreadsheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ export class Spreadsheet extends SheetComponent {
this._fontExtension = null as unknown as Font;
}

/**
* 根据 viewport 绘制
* viewRange 根据 cacheBound 计算得到
* diffRange 根据 diffCacheBounds 得到
* @param ctx
* @param viewportInfo
* @returns
*/
override draw(ctx: UniverRenderingContext, viewportInfo: IViewportInfo) {
// const { parent = { scaleX: 1, scaleY: 1 } } = this;
// const mergeData = this.getMergeData();
Expand All @@ -123,7 +131,7 @@ export class Spreadsheet extends SheetComponent {

const parentScale = this.getParentScale();

const diffRanges = this._refreshIncrementalState && viewportInfo?.diffBounds
const diffRanges = this._refreshIncrementalState && viewportInfo?.diffCacheBounds
? viewportInfo?.diffBounds?.map((bound) => spreadsheetSkeleton.getRowColumnSegmentByViewBound(bound))
: undefined;
const viewRanges = [spreadsheetSkeleton.getRowColumnSegmentByViewBound(viewportInfo?.cacheBound)];
Expand Down Expand Up @@ -218,10 +226,8 @@ export class Spreadsheet extends SheetComponent {
}

/**
* canvas resize 并不会调用此函数
* resize 调用的是 forceDirty
* canvas resize calling not this function
* @param state
* @returns
*/
override makeDirty(state: boolean = true) {
super.makeDirty(state);
Expand All @@ -242,28 +248,23 @@ export class Spreadsheet extends SheetComponent {
const bufferEdgeSizeX = bufferEdgeX * scaleX / window.devicePixelRatio;
const bufferEdgeSizeY = bufferEdgeY * scaleY / window.devicePixelRatio;


const cacheCtx = cacheCanvas.getContext();
cacheCtx.save();

const { left, top, right, bottom } = viewPortPosition;

const dw = right - left + rowHeaderWidth;
const dh = bottom - top + columnHeaderHeight;


// 没有滚动
if (diffBounds.length === 0 || (diffX === 0 && diffY === 0) || isForceDirty) {
if (diffBounds.length === 0 || (diffX === 0 && diffY === 0) || isForceDirty || isDirty) {
if (isDirty || isForceDirty) {
this.refreshCacheCanvas(viewportBoundsInfo, { cacheCanvas, cacheCtx, mainCtx, topOrigin, leftOrigin, bufferEdgeX, bufferEdgeY });
}
this._applyCacheFreeze(mainCtx, cacheCanvas, bufferEdgeSizeX, bufferEdgeSizeY, dw, dh, left, top, dw, dh);
} else {
if (isDirty) {
this.paintNewAreaOfCacheCanvas(viewportBoundsInfo, {
cacheCanvas, cacheCtx, mainCtx, topOrigin, leftOrigin, bufferEdgeX, bufferEdgeY, scaleX, scaleY, columnHeaderHeight, rowHeaderWidth,
});
}
} else if (diffBounds.length !== 0 || diffX !== 0 || diffY === 0) {
// scrolling && no dirty
this.paintNewAreaOfCacheCanvas(viewportBoundsInfo, {
cacheCanvas, cacheCtx, mainCtx, topOrigin, leftOrigin, bufferEdgeX, bufferEdgeY, scaleX, scaleY, columnHeaderHeight, rowHeaderWidth,
});
this._applyCacheFreeze(mainCtx, cacheCanvas, bufferEdgeSizeX, bufferEdgeSizeY, dw, dh, left, top, dw, dh);
}
cacheCtx.restore();
Expand Down
4 changes: 0 additions & 4 deletions packages/engine-render/src/scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,6 @@ export class Scene extends ThinScene {
return this._viewports;
}

getSpreadSheetViewports() {
return this.getViewports().filter((v) => ['viewMain', 'viewMainLeftTop', 'viewMainTop', 'viewMainLeft'].includes(v.viewportKey));
}

getViewport(key: string) {
for (const viewport of this._viewports) {
if (viewport.viewportKey === key) {
Expand Down
117 changes: 53 additions & 64 deletions packages/engine-render/src/viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,6 @@ export class Viewport {
* @param objects
* @param isMaxLayer
* @param isLast
* @returns
*/
render(parentCtx?: UniverRenderingContext, objects: BaseObject[] = [], isMaxLayer = false, isLast = false) {
if (
Expand All @@ -673,24 +672,14 @@ export class Viewport {
if (this._renderClipState) {
mainCtx.beginPath();
// DEPT: left is set by upper views but width and height is not
// 这里用 (this.width || 0) * scale 反而出错了 选区不对
// 此刻 this.left 已经乘了 scale
// this.left has handle scale already, no need to `this.width * scale`
mainCtx.rect(this.left, this.top, (this.width || 0), (this.height || 0));
mainCtx.clip();
}

mainCtx.transform(tm[0], tm[1], tm[2], tm[3], tm[4], tm[5]);
const viewPortInfo = this._calcViewportInfo();


// scrolling ---> make Dirty
if (viewPortInfo.diffX !== 0 || viewPortInfo.diffY !== 0 || viewPortInfo.diffBounds.length !== 0) {
this.markDirty();
viewPortInfo.isDirty = true;
}
viewPortInfo.cacheCanvas = this._cacheCanvas!;


objects.forEach((o) => {
o.render(mainCtx, viewPortInfo);
});
Expand Down Expand Up @@ -722,48 +711,54 @@ export class Viewport {
this._scrollRendered();
}


private _makeDefaultViewport() {
return {
viewBound: {
left: -1,
top: -1,
right: -1,
bottom: -1,
},
diffBounds: [],
diffX: -1,
diffY: -1,
viewPortPosition: {
top: 0,
left: 0,
bottom: 0,
right: 0,
},
viewPortKey: this.viewportKey,
// isDirty: this.isDirty,
isForceDirty: this.isForceDirty,
allowCache: false,
cacheBound: {
left: -1,
top: -1,
right: -1,
bottom: -1,
},
diffCacheBounds: [],
cacheViewPortPosition: {
top: 0,
left: 0,
bottom: 0,
right: 0,
},
shouldCacheUpdate: 0,
sceneTrans: Transform.create([1, 0, 0, 1, 0, 0]),
leftOrigin: 0,
topOrigin: 0,
bufferEdgeX: this.bufferEdgeX,
bufferEdgeY: this.bufferEdgeY,
} satisfies IViewportInfo;
}

// eslint-disable-next-line max-lines-per-function
private _calcViewportInfo(): IViewportInfo {
if (this.isActive === false) {
return {
viewBound: {
left: -1,
top: -1,
right: -1,
bottom: -1,
},
diffBounds: [],
diffX: -1,
diffY: -1,
viewPortPosition: {
top: 0,
left: 0,
bottom: 0,
right: 0,
},
viewPortKey: this.viewportKey,
isDirty: this.isDirty,
isForceDirty: this.isForceDirty,
allowCache: false,
cacheBound: {
left: -1,
top: -1,
right: -1,
bottom: -1,
},
diffCacheBounds: [],
cacheViewPortPosition: {
top: 0,
left: 0,
bottom: 0,
right: 0,
},
shouldCacheUpdate: 0,
sceneTrans: Transform.create([1, 0, 0, 1, 0, 0]),
leftOrigin: 0,
topOrigin: 0,
bufferEdgeX: this.bufferEdgeX,
bufferEdgeY: this.bufferEdgeY,
} satisfies IViewportInfo;
return this._makeDefaultViewport();
}

const sceneTrans = this._scene.transform.clone();
Expand Down Expand Up @@ -804,10 +799,6 @@ export class Viewport {

const viewBound = {
// 这里若对 top left 做 Math.floor 对 right bottom Math.ceil 操作, 放大后, 贴图会模糊
// top: parseFloat(topLeft.y.toFixed(3)),
// left: parseFloat(topLeft.x.toFixed(3)),
// right: parseFloat(bottomRight.x.toFixed(3)),
// bottom: parseFloat(bottomRight.y.toFixed(3)),
top: topLeft.y,
left: topLeft.x,
right: bottomRight.x,
Expand All @@ -833,7 +824,6 @@ export class Viewport {
const cacheViewPortPosition = this.expandBounds(viewPortPosition);

const shouldCacheUpdate = this._shouldCacheUpdate(viewBound, this._preCacheBound, diffX, diffY);
// console.log('shouldCacheUpdate', this.viewPortKey, shouldCacheUpdate);
if (shouldCacheUpdate) {
diffCacheBounds = this._calcDiffCacheBound(this._preCacheBound, cacheBound);
}
Expand All @@ -845,7 +835,7 @@ export class Viewport {
diffY,
viewPortPosition,
viewPortKey: this.viewportKey,
isDirty: this.isDirty,
isDirty: this.isDirty ? 0b10 : 0b00,
isForceDirty: this.isForceDirty,
allowCache: this._allowCache,
cacheBound: this.cacheBound,
Expand Down Expand Up @@ -881,18 +871,18 @@ export class Viewport {
return svCoord;
}


// eslint-disable-next-line complexity
onMouseWheel(evt: IWheelEvent, state: EventState) {
if (!this._scrollBar || this.isActive === false) {
return;
}
let isLimitedStore;
if (evt.inputIndex === PointerInput.MouseWheelX) {
const deltaFactor = Math.abs(evt.deltaX);
// let magicNumber = deltaFactor < 40 ? 2 : deltaFactor < 80 ? 3 : 4;
const allWidth = this._scene.width;
const viewWidth = this.width || 1;
const scrollNum = (viewWidth / allWidth) * deltaFactor;

if (evt.deltaX > 0) {
isLimitedStore = this.scrollBy({
x: scrollNum,
Expand Down Expand Up @@ -967,7 +957,6 @@ export class Viewport {
}
if (evt.inputIndex === PointerInput.MouseWheelZ) {
// TODO
// ...
}

this._scene.makeDirty(true);
Expand Down Expand Up @@ -1084,15 +1073,13 @@ export class Viewport {

private _resizeCacheCanvasAndScrollBar() {
const actualScrollX = this.actualScrollX;

const actualScrollY = this.actualScrollY;
const { width, height, parentHeight } = this._getViewPortSize();
const { width, height } = this._getViewPortSize();

const scaleX = this.scene.scaleX;
const scaleY = this.scene.scaleY;
const canvasW = width !== 0 ? width + this.bufferEdgeX * 2 * scaleX : 0;
const canvasH = height !== 0 ? height + this.bufferEdgeY * 2 * scaleY : 0;

this._cacheCanvas?.setSize(canvasW, canvasH);

const contentWidth = (this._scene.width - this._paddingEndX) * this._scene.scaleX;
Expand Down Expand Up @@ -1135,6 +1122,8 @@ export class Viewport {
} else {
height = (this._heightOrigin || 0) * scaleY;
}
width = Math.max(0, width);
height = Math.max(0, height);

this._width = width;
this._height = height;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,8 @@ export class SheetRenderController extends RxDisposable {
scene.makeDirty();
if (!command.params) return;
const cmdParams = command.params as Record<string, any>;
const viewports = scene.getSpreadSheetViewports();
// 还有个概念和这个很像, SetRangeValuesCommand
const viewports = scene.getViewports().filter((v) => ['viewMain', 'viewMainLeftTop', 'viewMainTop', 'viewMainLeft'].includes(v.viewportKey));
if (command.id === SetRangeValuesMutation.id && cmdParams.cellValue) {
// TODO command.params 数据结构有很多种
const dirtyRange: IRange = this._cellValueToRange(cmdParams.cellValue);
const dirtyBounds = this._rangeToBounds([dirtyRange]);
this.markViewportDirty(viewports, dirtyBounds);
Expand Down

0 comments on commit 9a7c24b

Please sign in to comment.