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

fix(sheet): keep consistent with excel rotation #1562

Merged
merged 3 commits into from
Mar 14, 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
4 changes: 2 additions & 2 deletions packages/engine-render/src/basics/text-rotation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import { BooleanNumber, type ITextRotation } from '@univerjs/core';

export const VERTICAL_ROTATE_ANGLE = 90;

export function convertTextRotation(textRotation: ITextRotation) {
const { a: angle = 0, v: isVertical = BooleanNumber.FALSE } = textRotation;
export function convertTextRotation(textRotation?: ITextRotation) {
const { a: angle = 0, v: isVertical = BooleanNumber.FALSE } = textRotation || { a: 0, v: BooleanNumber.FALSE };
let centerAngle = 0;
let vertexAngle = angle;
if (isVertical === BooleanNumber.TRUE) {
Expand Down
53 changes: 31 additions & 22 deletions packages/engine-render/src/components/docs/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import type { UniverRenderingContext } from '../../context';
import type { Scene } from '../../scene';
import type { IExtensionConfig } from '../extension';
import { DocumentsSpanAndLineExtensionRegistry } from '../extension';
import { VERTICAL_ROTATE_ANGLE } from '../../basics/text-rotation';
import { Liquid } from './common/liquid';
import { DocComponent } from './doc-component';
import { DOCS_EXTENSION_TYPE } from './doc-extension';
Expand Down Expand Up @@ -250,6 +251,7 @@ export class Documents extends DocComponent {
pagePaddingRight,
horizontalAlign,
vertexAngleDeg,
centerAngleDeg,
cellValueType
);

Expand Down Expand Up @@ -314,7 +316,8 @@ export class Documents extends DocComponent {
pagePaddingLeft,
pagePaddingRight,
horizontalAlign,
vertexAngle
vertexAngleDeg,
centerAngleDeg
);

const verticalOffset = this._verticalHandler(
Expand Down Expand Up @@ -459,42 +462,48 @@ export class Documents extends DocComponent {
pagePaddingLeft: number,
pagePaddingRight: number,
horizontalAlign: HorizontalAlign,
angle: number = 0,
vertexAngleDeg: number = 0,
centerAngleDeg: number = 0,
cellValueType: Nullable<CellValueType>
) {
let offsetLeft = 0;
if (horizontalAlign === HorizontalAlign.CENTER) {
offsetLeft = (this.width - pageWidth) / 2;
} else if (horizontalAlign === HorizontalAlign.RIGHT) {
offsetLeft = this.width - pageWidth - pagePaddingRight;
} else {
/**
* In Excel, if horizontal alignment is not specified,
* rotated text aligns to the right when rotated downwards and aligns to the left when rotated upwards.
*/
if (horizontalAlign === HorizontalAlign.UNSPECIFIED) {
if (angle > 0) {
return this.width - pageWidth - pagePaddingRight;
}

/**
* In Excel, if horizontal alignment is not specified,
* rotated text aligns to the right when rotated downwards and aligns to the left when rotated upwards.
*/
if (horizontalAlign === HorizontalAlign.UNSPECIFIED) {
if (centerAngleDeg === VERTICAL_ROTATE_ANGLE && vertexAngleDeg === VERTICAL_ROTATE_ANGLE) {
horizontalAlign = HorizontalAlign.CENTER;
} else if ((vertexAngleDeg > 0 && vertexAngleDeg !== VERTICAL_ROTATE_ANGLE) || vertexAngleDeg === -VERTICAL_ROTATE_ANGLE) {
/**
* https://github.com/dream-num/univer-pro/issues/334
*/
horizontalAlign = HorizontalAlign.RIGHT;
} else {
/**
* sheet cell type, In a spreadsheet cell, without any alignment settings applied,
* text should be left-aligned,
* numbers should be right-aligned,
* and Boolean values should be center-aligned.
*/
if (cellValueType === CellValueType.NUMBER) {
offsetLeft = this.width - pageWidth - pagePaddingRight;
horizontalAlign = HorizontalAlign.RIGHT;
} else if (cellValueType === CellValueType.BOOLEAN) {
offsetLeft = (this.width - pageWidth) / 2;
horizontalAlign = HorizontalAlign.CENTER;
} else {
offsetLeft = pagePaddingLeft;
horizontalAlign = HorizontalAlign.LEFT;
}
} else {
offsetLeft = pagePaddingLeft;
}
}

let offsetLeft = 0;
if (horizontalAlign === HorizontalAlign.CENTER) {
offsetLeft = (this.width - pageWidth) / 2;
} else if (horizontalAlign === HorizontalAlign.RIGHT) {
offsetLeft = this.width - pageWidth - pagePaddingRight;
} else {
offsetLeft = pagePaddingLeft;
}

return offsetLeft;
}

Expand Down
28 changes: 21 additions & 7 deletions packages/engine-render/src/components/sheets/extensions/font.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { SpreadsheetExtensionRegistry } from '../../extension';
import type { IFontCacheItem } from '../interfaces';
import type { SheetComponent } from '../sheet-component';
import { getDocsSkeletonPageSize, type SpreadsheetSkeleton } from '../sheet-skeleton';
import { VERTICAL_ROTATE_ANGLE } from '../../../basics/text-rotation';
import { SheetExtension } from './sheet-extension';

const UNIQUE_KEY = 'DefaultFontExtension';
Expand Down Expand Up @@ -123,7 +124,20 @@ export class Font extends SheetExtension {
}

const overflowRectangle = overflowCache.getValue(rowIndex, columnIndex);
const { horizontalAlign, angle } = docsConfig;
const { horizontalAlign, vertexAngle = 0, centerAngle = 0 } = docsConfig;

/**
* https://github.com/dream-num/univer-pro/issues/334
* When horizontal alignment is not set, the default alignment for rotation angles varies to accommodate overflow scenarios.
*/
let horizontalAlignOverFlow = horizontalAlign;
if (horizontalAlign === HorizontalAlign.UNSPECIFIED) {
if (centerAngle === VERTICAL_ROTATE_ANGLE && vertexAngle === VERTICAL_ROTATE_ANGLE) {
horizontalAlignOverFlow = HorizontalAlign.CENTER;
} else if ((vertexAngle > 0 && vertexAngle !== VERTICAL_ROTATE_ANGLE) || vertexAngle === -VERTICAL_ROTATE_ANGLE) {
horizontalAlignOverFlow = HorizontalAlign.RIGHT;
}
}

ctx.save();
ctx.beginPath();
Expand All @@ -132,7 +146,7 @@ export class Font extends SheetExtension {
const leftOffset = cellData.fontRenderExtension?.leftOffset ?? 0;
let isOverflow = true;

if (angle === 0) {
if (vertexAngle === 0) {
startX = startX + leftOffset;
endX = endX - rightOffset;

Expand Down Expand Up @@ -164,7 +178,7 @@ export class Font extends SheetExtension {
cellHeight - 2 / scale
);
} else {
if (horizontalAlign === HorizontalAlign.CENTER) {
if (horizontalAlignOverFlow === HorizontalAlign.CENTER) {
this._clipRectangle(
ctx,
startRow,
Expand All @@ -175,7 +189,7 @@ export class Font extends SheetExtension {
rowHeightAccumulation,
columnWidthAccumulation
);
} else if (horizontalAlign === HorizontalAlign.RIGHT) {
} else if (horizontalAlignOverFlow === HorizontalAlign.RIGHT) {
this._clipRectangle(
ctx,
startRow,
Expand Down Expand Up @@ -235,11 +249,11 @@ export class Font extends SheetExtension {
throw new Error('documents is null');
}

const { documentSkeleton, angle, wrapStrategy } = docsConfig;
const { documentSkeleton, vertexAngle = 0, wrapStrategy } = docsConfig;
const cellWidth = endX - startX;
const cellHeight = endY - startY;

if (wrapStrategy === WrapStrategy.WRAP && angle === 0) {
if (wrapStrategy === WrapStrategy.WRAP && vertexAngle === 0) {
documentSkeleton.getViewModel().getDataModel().updateDocumentDataPageSize(cellWidth);
documentSkeleton.calculate();
} else {
Expand All @@ -249,7 +263,7 @@ export class Font extends SheetExtension {
// Use fix https://github.com/dream-num/univer/issues/927, Set the actual width of the content to the page width of the document,
// so that the divide will be aligned when the skeleton is calculated.
const overflowRectangle = overflowCache.getValue(row, column);
if (!(wrapStrategy === WrapStrategy.WRAP && !overflowRectangle && angle === 0)) {
if (!(wrapStrategy === WrapStrategy.WRAP && !overflowRectangle && vertexAngle === 0)) {
const contentSize = getDocsSkeletonPageSize(documentSkeleton);
const documentStyle = documentSkeleton.getViewModel().getDataModel().getSnapshot().documentStyle;
if (contentSize && documentStyle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export interface IFontCacheItem {
// marginBottom?: number;
// marginRight?: number;
// marginLeft?: number;
angle?: number;
vertexAngle?: number; // Text rotation offset based on the top-left corner.
centerAngle?: number; // Text rotation based on the center point.
verticalAlign: VerticalAlign;
horizontalAlign: HorizontalAlign;
wrapStrategy: WrapStrategy;
Expand Down
59 changes: 29 additions & 30 deletions packages/engine-render/src/components/sheets/sheet-skeleton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,12 +463,7 @@ export class SpreadsheetSkeleton extends Skeleton {

const documentViewModel = new DocumentViewModel(documentModel);

let { a: angle } = textRotation as ITextRotation;
const { v: isVertical = BooleanNumber.FALSE } = textRotation as ITextRotation;

if (isVertical === BooleanNumber.TRUE) {
angle = VERTICAL_ROTATE_ANGLE;
}
const { vertexAngle: angle } = convertTextRotation(textRotation);

const colWidth = data[i]?.w;
if (typeof colWidth === 'number' && wrapStrategy === WrapStrategy.WRAP) {
Expand Down Expand Up @@ -1143,12 +1138,25 @@ export class SpreadsheetSkeleton extends Skeleton {
*/
private _calculateOverflowCell(row: number, column: number, docsConfig: IFontCacheItem) {
// wrap and angle handler
const { documentSkeleton, angle = 0, horizontalAlign, wrapStrategy } = docsConfig;
const { documentSkeleton, vertexAngle = 0, centerAngle = 0, horizontalAlign, wrapStrategy } = docsConfig;

const cell = this.getCellData().getValue(row, column);

const { t: cellValueType = CellValueType.STRING } = cell || {};

let horizontalAlignPos = horizontalAlign;
/**
* https://github.com/dream-num/univer-pro/issues/334
* When horizontal alignment is not set, the default alignment for rotation angles varies to accommodate overflow scenarios.
*/
if (horizontalAlign === HorizontalAlign.UNSPECIFIED) {
if (centerAngle === VERTICAL_ROTATE_ANGLE && vertexAngle === VERTICAL_ROTATE_ANGLE) {
horizontalAlignPos = HorizontalAlign.CENTER;
} else if ((vertexAngle > 0 && vertexAngle !== VERTICAL_ROTATE_ANGLE) || vertexAngle === -VERTICAL_ROTATE_ANGLE) {
horizontalAlignPos = HorizontalAlign.RIGHT;
}
}

/**
* Numerical and Boolean values are not displayed with overflow.
*/
Expand All @@ -1163,13 +1171,13 @@ export class SpreadsheetSkeleton extends Skeleton {
return true;
}

let contentSize = getDocsSkeletonPageSize(documentSkeleton, angle);
let contentSize = getDocsSkeletonPageSize(documentSkeleton, vertexAngle);

if (!contentSize) {
return true;
}

if (angle !== 0) {
if (vertexAngle !== 0) {
const { startY, endY, startX, endX } = getCellByIndex(
row,
column,
Expand All @@ -1182,7 +1190,7 @@ export class SpreadsheetSkeleton extends Skeleton {

if (contentSize.height > cellHeight) {
contentSize = {
width: cellHeight / Math.tan(Math.abs(angle)) + cellWidth,
width: cellHeight / Math.tan(Math.abs(vertexAngle)) + cellWidth,
height: cellHeight,
};
// if (angle > 0) {
Expand All @@ -1193,7 +1201,7 @@ export class SpreadsheetSkeleton extends Skeleton {
}
}

const position = this.getOverflowPosition(contentSize, horizontalAlign, row, column, this.getColumnCount());
const position = this.getOverflowPosition(contentSize, horizontalAlignPos, row, column, this.getColumnCount());

const { startColumn, endColumn } = position;

Expand All @@ -1202,7 +1210,7 @@ export class SpreadsheetSkeleton extends Skeleton {
}

this.appendToOverflowCache(row, column, startColumn, endColumn);
} else if (wrapStrategy === WrapStrategy.WRAP && angle !== 0) {
} else if (wrapStrategy === WrapStrategy.WRAP && vertexAngle !== 0) {
// Merged cells do not support overflow.
if (this.intersectMergeRange(row, column)) {
return true;
Expand All @@ -1219,15 +1227,15 @@ export class SpreadsheetSkeleton extends Skeleton {
const cellHeight = endY - startY;
documentSkeleton.getViewModel().getDataModel().updateDocumentDataPageSize(cellHeight);
documentSkeleton.calculate();
const contentSize = getDocsSkeletonPageSize(documentSkeleton, angle);
const contentSize = getDocsSkeletonPageSize(documentSkeleton, vertexAngle);

if (!contentSize) {
return true;
}

const { startColumn, endColumn } = this.getOverflowPosition(
contentSize,
horizontalAlign,
horizontalAlignPos,
row,
column,
this.getColumnCount()
Expand Down Expand Up @@ -1672,20 +1680,16 @@ export class SpreadsheetSkeleton extends Skeleton {

const fontCache = cache.font![fontString];

let { a: angle } = textRotation as ITextRotation;

const { v: isVertical = BooleanNumber.FALSE } = textRotation as ITextRotation;
if (isVertical === BooleanNumber.TRUE) {
angle = VERTICAL_ROTATE_ANGLE;
}
const { vertexAngle, centerAngle } = convertTextRotation(textRotation);

if (documentViewModel) {
const documentSkeleton = DocumentSkeleton.create(documentViewModel, this._localService);
documentSkeleton.calculate();

const config = {
const config: IFontCacheItem = {
documentSkeleton,
angle,
vertexAngle,
centerAngle,
verticalAlign,
horizontalAlign,
wrapStrategy,
Expand Down Expand Up @@ -1737,7 +1741,7 @@ export class SpreadsheetSkeleton extends Skeleton {
private _getDocumentDataByStyle(content: string, textStyle: ITextStyle, config: ICellOtherConfig) {
const contentLength = content.length;
const {
textRotation = { a: 0, v: BooleanNumber.FALSE },
textRotation,
paddingData = {
t: 2,
r: 2,
Expand All @@ -1750,15 +1754,10 @@ export class SpreadsheetSkeleton extends Skeleton {
cellValueType,
} = config;

const { a: angle = 0, v: isVertical = BooleanNumber.FALSE } = textRotation;
const { t: marginTop, r: marginRight, b: marginBottom, l: marginLeft } = paddingData || {};

let centerAngle = 0;
let vertexAngle = angle;
if (isVertical === BooleanNumber.TRUE) {
centerAngle = VERTICAL_ROTATE_ANGLE;
vertexAngle = VERTICAL_ROTATE_ANGLE;
}
const { vertexAngle, centerAngle } = convertTextRotation(textRotation);

const documentData: IDocumentData = {
id: 'd',
body: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { ICommandInfo, IDocumentBody, IDocumentData, IPosition, ITextRotation, Nullable } from '@univerjs/core';
import type { ICommandInfo, IDocumentBody, IDocumentData, IPosition, Nullable } from '@univerjs/core';
import {
DEFAULT_EMPTY_DOCUMENT_VALUE,
Disposable,
Expand Down Expand Up @@ -45,6 +45,7 @@ import {
} from '@univerjs/docs';
import type { DocumentSkeleton, IDocumentLayoutObject, IEditorInputConfig, Scene } from '@univerjs/engine-render';
import {
convertTextRotation,
DeviceInputEventType,
FIX_ONE_PIXEL_BLUR_OFFSET,
fixLineWidthByScale,
Expand Down Expand Up @@ -171,7 +172,7 @@ export class StartEditController extends Disposable {

const { textRotation, wrapStrategy, documentModel } = documentLayoutObject;

const { a: angle } = textRotation as ITextRotation;
const { vertexAngle: angle } = convertTextRotation(textRotation);

documentModel!.updateDocumentId(editorUnitId);

Expand Down Expand Up @@ -276,7 +277,7 @@ export class StartEditController extends Disposable {

const documentDataModel = documentLayoutObject.documentModel;

const { a: angle } = textRotation as ITextRotation;
const { vertexAngle: angle } = convertTextRotation(textRotation);

const clientWidth = document.body.clientWidth;

Expand Down
Loading