Skip to content

Commit

Permalink
feat: support for tilting the cursor when italicized (#1932)
Browse files Browse the repository at this point in the history
* feat: support for tilting the cursor when italicized

* feat: add system highlight color as seleciton color

* fix: stroke width

* fix: add default value of opacity
  • Loading branch information
Jocs committed Jun 1, 2024
1 parent cfc2e0a commit ac62428
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 13 deletions.
1 change: 1 addition & 0 deletions packages/core/src/shared/color/color-kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ const rgbNormalize = (val: number) => {
return val <= 0.03928 ? val / 12.92 : ((val + 0.055) / 1.055) ** 2.4;
};

// eslint-disable-next-line max-lines-per-function
const toColor: (color: string | Color) => Color | undefined = (color) => {
if (isObject(color)) {
if ('r' in color) {
Expand Down
2 changes: 1 addition & 1 deletion packages/engine-render/src/basics/range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface ITextSelectionStyle {
}

export const NORMAL_TEXT_SELECTION_PLUGIN_STYLE: ITextSelectionStyle = {
strokeWidth: 1,
strokeWidth: 1.5,
stroke: 'rgba(0, 0, 0, 0)',
strokeActive: 'rgba(0, 0, 0, 1)',
fill: 'rgba(0, 0, 0, 0.2)',
Expand Down
19 changes: 18 additions & 1 deletion packages/engine-render/src/basics/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import type {
LocaleService,
Nullable,
} from '@univerjs/core';
import { BaselineOffset, DEFAULT_STYLES, FontStyleType, Rectangle, Tools } from '@univerjs/core';
import { BaselineOffset, ColorKit, DEFAULT_STYLES, FontStyleType, Rectangle, Tools } from '@univerjs/core';
import * as cjk from 'cjk-regex';

import { FontCache } from '../components/docs/layout/shaping-engine/font-cache';
Expand Down Expand Up @@ -833,3 +833,20 @@ export function clampRanges(range: IRange) {
endColumn: Math.max(0, range.endColumn),
};
}

// Get system highlight color in rgb format.
export function getSystemHighlightColor() {
const hiddenEle = document.createElement('div');
hiddenEle.style.width = '0';
hiddenEle.style.height = '0';
hiddenEle.style.backgroundColor = 'highlight';
document.body.append(hiddenEle);

const highlightColor = getComputedStyle(hiddenEle).backgroundColor;

hiddenEle.remove();

const colorParser = new ColorKit(highlightColor);

return colorParser.toRgb();
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
*/

import type { ITextRange, Nullable } from '@univerjs/core';
import { COLORS, Tools } from '@univerjs/core';
import { BooleanNumber, COLORS, Tools } from '@univerjs/core';

import type { INodePosition } from '../../../basics/interfaces';
import type { ISuccinctTextRangeParam, ITextSelectionStyle } from '../../../basics/range';
import { NORMAL_TEXT_SELECTION_PLUGIN_STYLE, RANGE_DIRECTION } from '../../../basics/range';
Expand All @@ -27,6 +28,7 @@ import { RegularPolygon } from '../../../shape/regular-polygon';
import type { ThinScene } from '../../../thin-scene';
import type { DocumentSkeleton } from '../layout/doc-skeleton';
import type { Documents } from '../document';
import type { IDocumentSkeletonGlyph } from '../../../basics';
import {
compareNodePosition,
compareNodePositionLogic,
Expand Down Expand Up @@ -318,7 +320,11 @@ export class TextRange {
const { contentBoxPointGroup, cursorList } = convertor.getRangePointData(anchor, anchor);

this._setCursorList(cursorList);
contentBoxPointGroup.length > 0 && this._createOrUpdateAnchor(contentBoxPointGroup, docsLeft, docsTop);

if (contentBoxPointGroup.length > 0) {
const glyphAtCursor = _docSkeleton.findGlyphByPosition(anchor);
this._createOrUpdateAnchor(contentBoxPointGroup, docsLeft, docsTop, glyphAtCursor);
}

return;
}
Expand Down Expand Up @@ -388,26 +394,44 @@ export class TextRange {
this._scene.addObject(polygon, TEXT_RANGE_LAYER_INDEX);
}

private _createOrUpdateAnchor(pointsGroup: IPoint[][], docsLeft: number, docsTop: number) {
private _createOrUpdateAnchor(pointsGroup: IPoint[][], docsLeft: number, docsTop: number, glyph: Nullable<IDocumentSkeletonGlyph>) {
const bounding = getAnchorBounding(pointsGroup);
const { left, top, height } = bounding;
const { left: boundingLeft, top: boundingTop, height } = bounding;
const ITALIC_DEGREE = 12;
let left = boundingLeft + docsLeft;
const top = boundingTop + docsTop;
const isItalic = glyph?.ts?.it === BooleanNumber.TRUE;

if (isItalic) {
left += height * Math.tan((ITALIC_DEGREE * Math.PI) / 180) / 2;
}

if (this._anchorShape) {
this._anchorShape.transformByState({ left: left + docsLeft, top: top + docsTop, height });
this._anchorShape.transformByState({ left, top, height });
this._anchorShape.show();

if (isItalic) {
this._anchorShape.skew(-ITALIC_DEGREE, 0);
} else {
this._anchorShape.skew(0, 0);
}

return;
}

const anchor = new Rect(TEXT_ANCHOR_KEY_PREFIX + Tools.generateRandomId(ID_LENGTH), {
left: left + docsLeft,
top: top + docsTop,
left,
top,
height,
strokeWidth: this.style?.strokeWidth || 1,
strokeWidth: this.style?.strokeWidth || 1.5,
stroke: this.style?.strokeActive || getColor(COLORS.black, 1),
evented: false,
});

if (isItalic) {
anchor.skew(-ITALIC_DEGREE, 0);
}

this._anchorShape = anchor;

this._scene.addObject(anchor, TEXT_RANGE_LAYER_INDEX);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { ScrollTimer } from '../../../scroll-timer';
import type { IScrollObserverParam, Viewport } from '../../../viewport';
import type { DocumentSkeleton } from '../layout/doc-skeleton';
import type { Documents } from '../document';
import { getSystemHighlightColor } from '../../../basics/tools';
import { cursorConvertToTextRange, TextRange } from './text-range';

export function getCanvasOffsetByEngine(engine: Nullable<Engine>) {
Expand Down Expand Up @@ -256,6 +257,8 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel
super();

this._initDOM();

this._setSystemHighlightColorToStyle();
}

__getEditorContainer(): HTMLElement {
Expand Down Expand Up @@ -290,7 +293,10 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel
const { _scene: scene, _docSkeleton: docSkeleton } = this;

for (const range of ranges) {
const textSelection = cursorConvertToTextRange(scene!, range, docSkeleton!, this._document!);
const textSelection = cursorConvertToTextRange(scene!, {
style: this._selectionStyle,
...range,
}, docSkeleton!, this._document!);

this._add(textSelection);
}
Expand Down Expand Up @@ -491,7 +497,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel
if (evt.shiftKey && this._getActiveRangeInstance()) {
this._updateActiveRangeFocusPosition(position);
} else if (evt.ctrlKey || this._isEmpty()) {
const newTextSelection = new TextRange(scene, this._document!, this._docSkeleton!, position);
const newTextSelection = new TextRange(scene, this._document!, this._docSkeleton!, position, undefined, this._selectionStyle);

this._addTextRange(newTextSelection);
} else {
Expand Down Expand Up @@ -577,6 +583,20 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel
this.deactivate();
}

private _setSystemHighlightColorToStyle() {
const { r, g, b, a } = getSystemHighlightColor();

// Only set selection use highlight color.
const style: ITextSelectionStyle = {
strokeWidth: 1.5,
stroke: 'rgba(0, 0, 0, 0)',
strokeActive: 'rgba(0, 0, 0, 1)',
fill: `rgba(${r}, ${g}, ${b}, ${a ?? 0.2})`,
};

this.setStyle(style);
}

private _getAllTextRanges() {
return this._rangeList;
}
Expand Down Expand Up @@ -753,7 +773,7 @@ export class TextSelectionRenderManager extends RxDisposable implements ITextSel
let lastRange = this._rangeList.pop();

if (!lastRange) {
lastRange = new TextRange(this._scene, this._document!, this._docSkeleton!, position);
lastRange = new TextRange(this._scene, this._document!, this._docSkeleton!, position, undefined, this._selectionStyle);
}

this._removeAllTextRanges();
Expand Down

0 comments on commit ac62428

Please sign in to comment.