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

feat: everything feels very lag when there is a long range dashrect(cliparea) #2472

Merged
merged 6 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 25 additions & 15 deletions packages/core/src/shared/rectangle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { IRange } from '../types/interfaces/i-range';
import type { IRange, IRectLTRB } from '../types/interfaces/i-range';
import { AbsoluteRefType, RANGE_TYPE } from '../types/interfaces/i-range';
import type { Nullable } from './types';

Expand Down Expand Up @@ -314,20 +314,7 @@ export class Rectangle {
return result;
}

static hasIntersectionBetweenTwoBounds(
rect1: {
left: number;
top: number;
right: number;
bottom: number;
},
rect2: {
left: number;
top: number;
right: number;
bottom: number;
}
) {
static hasIntersectionBetweenTwoRect(rect1: IRectLTRB, rect2: IRectLTRB) {
if (
rect1.left > rect2.right || // rect1 在 rect2 右侧
rect1.right < rect2.left || // rect1 在 rect2 左侧
Expand All @@ -339,4 +326,27 @@ export class Rectangle {

return true;
}

static getIntersectionBetweenTwoRect(rect1: IRectLTRB, rect2: IRectLTRB) {
// 计算两个矩形的交集部分的坐标
const left = Math.max(rect1.left, rect2.left);
const right = Math.min(rect1.right, rect2.right);
const top = Math.max(rect1.top, rect2.top);
const bottom = Math.min(rect1.bottom, rect2.bottom);

// 如果交集部分的宽度或高度小于等于 0,说明两个矩形不相交
if (right <= left || bottom <= top) {
return null;
}

// 返回交集部分的矩形
return {
left,
right,
top,
bottom,
width: right - left,
height: bottom - top,
} as Required<IRectLTRB>;
}
}
9 changes: 9 additions & 0 deletions packages/core/src/types/interfaces/i-range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,12 @@ export interface IOptionData {
* Option of copyTo function
*/
export interface ICopyToOptionsData extends IOptionData {}

export interface IRectLTRB {
left: number;
top: number;
right: number;
bottom: number;
width?: number;
height?: number;
}
2 changes: 1 addition & 1 deletion packages/engine-render/src/base-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ export abstract class BaseObject extends Disposable {
this._makeDirtyMix();
}

render(ctx: UniverRenderingContext, bounds?: IViewportInfo) {
render(ctx: UniverRenderingContext, bounds: IViewportInfo) {
/* abstract */
}

Expand Down
4 changes: 2 additions & 2 deletions packages/engine-render/src/basics/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ export class Transform {
this._m[1] *= sx;
this._m[2] *= sy;
this._m[3] *= sy;
this._m[4] *= sx;
this._m[5] *= sy;
// this._m[4] *= sx;
lumixraku marked this conversation as resolved.
Show resolved Hide resolved
// this._m[5] *= sy;
return this;
}

Expand Down
4 changes: 0 additions & 4 deletions packages/engine-render/src/basics/vector2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -847,10 +847,6 @@ export interface IBoundRect {
}

export interface IBoundRectNoAngle {
/**
* 冻结区域相对 MainCanvas 的物理位置,
* left = n * colWidth + rowHeaderWidth
*/
left: number;
top: number;
right: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,6 @@ export class Font extends SheetExtension {
// return true;
// }

const cellData = worksheet.getCell(rowIndex, columnIndex) as ICellData & ISheetFontRenderExtension || {};
if (cellData.fontRenderExtension?.isSkip) {
return true;
}

// If the cell is overflowing, but the overflowRectangle has not been set,
// then overflowRectangle is set to undefined.
const overflowRectangle = overflowCache.getValue(rowIndex, columnIndex);
Expand All @@ -184,6 +179,11 @@ export class Font extends SheetExtension {
}
}

const cellData = worksheet.getCell(rowIndex, columnIndex) as ICellData & ISheetFontRenderExtension || {};
if (cellData.fontRenderExtension?.isSkip) {
return true;
}

ctx.save();
ctx.beginPath();

Expand Down
13 changes: 9 additions & 4 deletions packages/engine-render/src/components/sheets/spreadsheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class Spreadsheet extends SheetComponent {
const extensions = this.getExtensionsByOrder();
// At this moment, ctx.transform is at topLeft of sheet content, cell(0, 0)
for (const extension of extensions) {
// const timeKey = `extension ${viewportInfo.viewPortKey}:${extension.constructor.name}`;
const _timeKey = `extension ${viewportInfo.viewportKey}:${extension.constructor.name}`;
extension.draw(ctx, parentScale, spreadsheetSkeleton, diffRanges, {
viewRanges,
checkOutOfViewBound: true,
Expand Down Expand Up @@ -377,9 +377,14 @@ export class Spreadsheet extends SheetComponent {

const { viewportKey } = viewportInfo;
// scene --> layer, getObjects --> viewport.render(object) --> spreadsheet
// zIndex 0 spreadsheet this.getObjectsByOrder() ---> [spreadsheet]
// zIndex 2 rowHeader & colHeader & freezeBorder this.getObjectsByOrder() ---> [SpreadsheetRowHeader, SpreadsheetColumnHeader, _Rect]
// zIndex 3 selection this.getObjectsByOrder() ---> [group]
// SHEET_COMPONENT_MAIN_LAYER_INDEX = 0;
// SHEET_COMPONENT_SELECTION_LAYER_INDEX = 1;
// SHEET_COMPONENT_HEADER_LAYER_INDEX = 10;
// SHEET_COMPONENT_HEADER_SELECTION_LAYER_INDEX = 11;
// ......
// SHEET_COMPONENT_MAIN_LAYER_INDEX spreadsheet this.getObjectsByOrder() ---> [spreadsheet]
// SHEET_COMPONENT_HEADER_LAYER_INDEX rowHeader & colHeader & freezeBorder this.getObjectsByOrder() ---> [SpreadsheetRowHeader, SpreadsheetColumnHeader, _Rect..., HeaderMenuResizeShape]
// SHEET_COMPONENT_HEADER_SELECTION_LAYER_INDEX selection this.getObjectsByOrder() ---> [_Rect, Group]

// SpreadsheetRowHeader SpreadsheetColumnHeader is not render by spreadsheet
if (this.sheetContentViewport().includes(viewportKey as SHEET_VIEWPORT_KEY)) {
Expand Down
9 changes: 6 additions & 3 deletions packages/engine-render/src/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,17 @@ export class Group extends BaseObject {
return this._objects;
}

override render(ctx: UniverRenderingContext, bounds?: IViewportInfo) {
override render(ctx: UniverRenderingContext, bounds: IViewportInfo) {
ctx.save();
const m = this.transform.getMatrix();
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
const objects = this.getObjectsByOrder();
for (const object of objects) {
object.render(ctx, this._transformBounds(bounds));

for (let i = 0; i < objects.length; i++) {
const object = objects[i];
object.render(ctx, bounds);
}

ctx.restore();
}

Expand Down
50 changes: 43 additions & 7 deletions packages/engine-render/src/shape/rect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
* limitations under the License.
*/

import type { IKeyValue } from '@univerjs/core';
import { type IKeyValue, Rectangle } from '@univerjs/core';

import type { UniverRenderingContext } from '../context';
import type { IViewportInfo } from '../basics/vector2';
import type { IShapeProps } from './shape';
import { Shape } from './shape';

Expand All @@ -41,21 +42,27 @@ export class Rect<T extends IRectProps = IRectProps> extends Shape<T> {
}

static override drawWith(ctx: UniverRenderingContext, props: IRectProps | Rect) {
let { radius, width, height } = props;
let { radius, left, top, width, height } = props;

radius = radius ?? 0;
width = width ?? 30;
height = height ?? 30;
width = width ?? 0;
height = height ?? 0;
left = left ?? 0;
top = top ?? 0;

ctx.beginPath();

if (props.strokeDashArray) {
ctx.setLineDash(props.strokeDashArray);
} else {
// only dashrect needs top & left(which relative to topleft of viewport)
top = 0;
left = 0;
}

if (!radius) {
// simple rect - don't bother doing all that complicated maths stuff.
ctx.rect(0, 0, width, height);
ctx.rect(left, top, width, height);
lumixraku marked this conversation as resolved.
Show resolved Hide resolved
} else {
let topLeft = 0;
let topRight = 0;
Expand Down Expand Up @@ -92,7 +99,36 @@ export class Rect<T extends IRectProps = IRectProps> extends Shape<T> {
};
}

protected override _draw(ctx: UniverRenderingContext) {
Rect.drawWith(ctx, this);
protected override _draw(ctx: UniverRenderingContext, viewportInfo?: IViewportInfo) {
const { radius, paintFirst, stroke, strokeWidth, fill, strokeScaleEnabled, fillRule, strokeLineCap, strokeDashOffset, strokeLineJoin, strokeMiterLimit, strokeDashArray } = this;
if (!strokeDashArray) {
Rect.drawWith(ctx, this);
} else {
const parentTrans = this.getParent().transform;
// group.transform contains startXY
// selection-shape@_updateControl --> this.selectionShape.translate(startX, startY);

// startXY comes from selecitonModel
// const { startX, startY, endX, endY } = this._selectionModel;
const startX = parentTrans.getMatrix()[4];
const startY = parentTrans.getMatrix()[5];
const endX = startX + this.width;
const endY = startY + this.height;
const rect = { left: startX, top: startY, right: endX, bottom: endY };
let { left, top, right, bottom } = rect;

let width = right - left;
let height = bottom - top;
if (viewportInfo && Rectangle.hasIntersectionBetweenTwoRect(rect, viewportInfo.cacheBound)) {
const intersectRect = Rectangle.getIntersectionBetweenTwoRect(rect, viewportInfo.cacheBound)!;
left = intersectRect.left - startX;
top = intersectRect.top - startY;
right = intersectRect.right;
bottom = intersectRect.bottom;
width = intersectRect.width;
height = intersectRect.height;
}
Rect.drawWith(ctx, { ...{ radius, width, height, paintFirst, stroke, strokeWidth, fill, strokeScaleEnabled, fillRule, strokeLineCap, strokeDashOffset, strokeLineJoin, strokeMiterLimit, strokeDashArray }, ...{ width, height, left, top } });
}
}
}
4 changes: 2 additions & 2 deletions packages/engine-render/src/shape/shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ export abstract class Shape<T extends IShapeProps> extends BaseObject {
const m = this.transform.getMatrix();
mainCtx.save();
mainCtx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
this._draw(mainCtx);
this._draw(mainCtx, bounds);
mainCtx.restore();
this.makeDirty(false);
return this;
Expand Down Expand Up @@ -374,7 +374,7 @@ export abstract class Shape<T extends IShapeProps> extends BaseObject {
};
}

protected _draw(ctx: UniverRenderingContext) {
protected _draw(ctx: UniverRenderingContext, bounds?: IViewportInfo) {
/** abstract */
}

Expand Down
25 changes: 14 additions & 11 deletions packages/engine-render/src/viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -734,14 +734,14 @@ export class Viewport {
}
const mainCtx = parentCtx || (this._scene.getEngine()?.getCanvas().getContext() as UniverRenderingContext);

// this._scene.transform --> [scale, 0, 0, scale, - viewportScrollX * scaleX, - viewportScrollY * scaleY]
// see transform.ts@multiply
const sceneTrans = this._scene.transform.clone();
sceneTrans.multiply(Transform.create([1, 0, 0, 1, -this.viewportScrollX || 0, -this.viewportScrollY || 0]));

// Logical translation & scaling, unrelated to dpr.
const tm = sceneTrans.getMatrix();
const scrollbarTM = this.getScrollBarTransForm().getMatrix();

mainCtx.save();
mainCtx.save();// At this time, mainCtx transform is (dpr, 0, 0, dpr, 0, 0)

if (this._renderClipState) {
mainCtx.beginPath();
Expand All @@ -752,12 +752,13 @@ export class Viewport {
mainCtx.clip();
}

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

objects.forEach((o) => {
o.render(mainCtx, viewPortInfo);
});
for (let i = 0, length = objects.length; i < length; i++) {
objects[i].render(mainCtx, viewPortInfo);
}

this.markDirty(false);
this.markForceDirty(false);
Expand All @@ -770,7 +771,7 @@ export class Viewport {

if (this._scrollBar && isMaxLayer) {
mainCtx.save();

const scrollbarTM = this.getScrollBarTransForm().getMatrix();
mainCtx.transform(scrollbarTM[0], scrollbarTM[1], scrollbarTM[2], scrollbarTM[3], scrollbarTM[4], scrollbarTM[5]);
this._drawScrollbar(mainCtx);
mainCtx.restore();
Expand Down Expand Up @@ -1483,11 +1484,13 @@ export class Viewport {
right: Math.min(prevBound.right, currBound.right),
});
}
const expandX = this.bufferEdgeX;
const expandY = this.bufferEdgeY;
for (const bound of additionalAreas) {
bound.left = bound.left - this.bufferEdgeX;
bound.right = bound.right + this.bufferEdgeX;
bound.top = bound.top - this.bufferEdgeY;
bound.bottom = bound.bottom + this.bufferEdgeY;
bound.left = bound.left - expandX;
bound.right = bound.right + expandX;
bound.top = bound.top - expandY;
bound.bottom = bound.bottom + expandY;
}

return additionalAreas;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ export class SheetRenderController extends RxDisposable implements IRenderModule
const activeViewports = viewports.filter((vp) => vp.isActive && vp.cacheBound);
for (const vp of activeViewports) {
for (const b of dirtyBounds) {
if (Rectangle.hasIntersectionBetweenTwoBounds(vp.cacheBound!, b)) {
if (Rectangle.hasIntersectionBetweenTwoRect(vp.cacheBound!, b)) {
vp.markDirty(true);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export class SelectionRenderModel implements IRangeWithCoord {

private _endRow: number = -1;

/**
* value from { startY, endY, startX, endX } = getCellPositionByIndex in basics/tools
*/
private _startX: number = 0;

private _startY: number = 0;
Expand Down Expand Up @@ -54,18 +57,30 @@ export class SelectionRenderModel implements IRangeWithCoord {
return this._endRow;
}

/**
* value from { startY, endY, startX, endX } = getCellPositionByIndex in basics/tools
*/
get startX() {
return this._startX;
}

/**
* value from { startY, endY, startX, endX } = getCellPositionByIndex in basics/tools
*/
get startY() {
return this._startY;
}

/**
* value from { startY, endY, startX, endX } = getCellPositionByIndex in basics/tools
*/
get endX() {
return this._endX;
}

/**
* value from { startY, endY, startX, endX } = getCellPositionByIndex in basics/tools
*/
get endY() {
return this._endY;
}
Expand Down
Loading
Loading