From 0aa2898570fa077c9c08a8fbbbd5e6d8541097b5 Mon Sep 17 00:00:00 2001 From: zhangw Date: Sat, 23 Mar 2024 11:36:45 +0800 Subject: [PATCH] perf(engine-render): optimize border perf (#1574) * feat: optimize border perf * feat: row count to 100w * fix: border perf * feat: 100w lines * fix(render): mac render border failed --------- Co-authored-by: DR-Univer --- .../sheets/demo/default-workbook-data-demo.ts | 2 +- packages/engine-render/src/basics/draw.ts | 2 + .../src/components/sheets/spreadsheet.ts | 38 ++++++++++++------- packages/engine-render/src/context.ts | 17 +++++++++ 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/examples/src/data/sheets/demo/default-workbook-data-demo.ts b/examples/src/data/sheets/demo/default-workbook-data-demo.ts index 6bda4be8857..59bcef3d057 100644 --- a/examples/src/data/sheets/demo/default-workbook-data-demo.ts +++ b/examples/src/data/sheets/demo/default-workbook-data-demo.ts @@ -13875,7 +13875,7 @@ export const DEFAULT_WORKBOOK_DATA_DEMO: IWorkbookData = { id: 'sheet-0011', tabColor: '', hidden: 0, - rowCount: 1000, + rowCount: 1000000, columnCount: 20, zoomRatio: 1, cellData: { diff --git a/packages/engine-render/src/basics/draw.ts b/packages/engine-render/src/basics/draw.ts index cfd43b5c899..da71a96cf4c 100644 --- a/packages/engine-render/src/basics/draw.ts +++ b/packages/engine-render/src/basics/draw.ts @@ -93,6 +93,7 @@ export function drawLineByBorderType(ctx: UniverRenderingContext, type: BORDER_T ctx.beginPath(); ctx.moveToByPrecision(drawStartX, drawStartY); ctx.lineToByPrecision(drawEndX, drawEndY); + ctx.closePathByEnv(); ctx.stroke(); } @@ -138,6 +139,7 @@ export function drawDiagonalLineByBorderType(ctx: UniverRenderingContext, type: ctx.beginPath(); ctx.moveToByPrecision(drawStartX, drawStartY); ctx.lineToByPrecision(drawEndX, drawEndY); + ctx.closePathByEnv(); ctx.stroke(); } diff --git a/packages/engine-render/src/components/sheets/spreadsheet.ts b/packages/engine-render/src/components/sheets/spreadsheet.ts index 4edb90d7ce7..1a30303e92a 100644 --- a/packages/engine-render/src/components/sheets/spreadsheet.ts +++ b/packages/engine-render/src/components/sheets/spreadsheet.ts @@ -487,51 +487,63 @@ export class Spreadsheet extends SheetComponent { } ctx.save(); - ctx.beginPath(); ctx.setLineWidthByPrecision(1); ctx.strokeStyle = getColor([212, 212, 212]); const columnWidthAccumulationLength = columnWidthAccumulation.length; const rowHeightAccumulationLength = rowHeightAccumulation.length; + const EXTRA_BOUND = 0.4; + const rowCount = endRow - startRow + 1; + const columnCount = endColumn - startColumn + 1; + const extraRowCount = Math.ceil(rowCount * EXTRA_BOUND); + const extraColumnCount = Math.ceil(columnCount * EXTRA_BOUND); - const rowStart = this._allowCache ? startRow : 0; - const rowEnd = this._allowCache ? endRow : rowHeightAccumulationLength - 1; - const columnEnd = this._allowCache ? endColumn : columnWidthAccumulationLength - 1; - const columnStart = this._allowCache ? startColumn : 0; + const rowStart = Math.max(Math.floor(startRow - extraRowCount), 0); + const rowEnd = Math.min(Math.ceil(endRow + extraRowCount), rowHeightAccumulationLength - 1); + const columnEnd = Math.min(Math.ceil(endColumn + (extraColumnCount)), columnWidthAccumulationLength - 1); + const columnStart = Math.max(Math.floor(startColumn - (extraColumnCount)), 0); const startX = columnWidthAccumulation[columnStart - 1] || 0; const startY = rowHeightAccumulation[rowStart - 1] || 0; const endX = columnWidthAccumulation[columnEnd]; const endY = rowHeightAccumulation[rowEnd]; - ctx.translateWithPrecisionRatio(FIX_ONE_PIXEL_BLUR_OFFSET, FIX_ONE_PIXEL_BLUR_OFFSET); + ctx.beginPath(); ctx.moveToByPrecision(startX, startY); ctx.lineToByPrecision(endX, startY); - for (let r = 0; r <= rowEnd; r++) { + ctx.moveToByPrecision(startX, startY); + ctx.lineToByPrecision(startX, endY); + + ctx.closePathByEnv(); + ctx.stroke(); + + for (let r = rowStart; r <= rowEnd; r++) { if (r < 0 || r > rowHeightAccumulationLength - 1) { continue; } const rowEndPosition = rowHeightAccumulation[r]; + ctx.beginPath(); ctx.moveToByPrecision(startX, rowEndPosition); ctx.lineToByPrecision(endX, rowEndPosition); + ctx.closePathByEnv(); + ctx.stroke(); } - ctx.moveToByPrecision(startX, startY); - ctx.lineToByPrecision(startX, endY); - for (let c = 0; c <= endColumn; c++) { + for (let c = columnStart; c <= columnEnd; c++) { if (c < 0 || c > columnWidthAccumulationLength - 1) { continue; } const columnEndPosition = columnWidthAccumulation[c]; + ctx.beginPath(); ctx.moveToByPrecision(columnEndPosition, startY); ctx.lineToByPrecision(columnEndPosition, endY); + ctx.closePathByEnv(); + ctx.stroke(); } // console.log('xx2', scaleX, scaleY, columnTotalWidth, rowTotalHeight, rowHeightAccumulation, columnWidthAccumulation); - ctx.stroke(); - ctx.closePath(); // border?.forValue((rowIndex, columnIndex, borderCaches) => { // if (!borderCaches) { @@ -566,8 +578,6 @@ export class Spreadsheet extends SheetComponent { // }); // Clearing the dashed line issue caused by overlaid auxiliary lines and strokes - - ctx.closePath(); // merge cell this._clearRectangle(ctx, rowHeightAccumulation, columnWidthAccumulation, dataMergeCache); diff --git a/packages/engine-render/src/context.ts b/packages/engine-render/src/context.ts index 611a389c2db..8a102b18b64 100644 --- a/packages/engine-render/src/context.ts +++ b/packages/engine-render/src/context.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { Tools } from '@univerjs/core'; import { fixLineWidthByScale, getColor } from './basics/tools'; export class UniverRenderingContext2D implements CanvasRenderingContext2D { @@ -464,6 +465,22 @@ export class UniverRenderingContext2D implements CanvasRenderingContext2D { this._context.closePath(); } + /** + * Chrome hardware acceleration causes canvas stroke to fail to draw lines on Mac. + */ + closePathByEnv() { + const system = Tools.getSystemType(); + const isMac = system === 'Mac'; + const browser = Tools.getBrowserType(); + const isChrome = browser === 'Chrome'; + + if (isMac && isChrome) { + return; + } + + this._context.closePath(); + } + /** * createImageData function. * @method