From d17af8296c1d4b181474a36a62aab82d4bd87544 Mon Sep 17 00:00:00 2001 From: Shachar <34343793+ShaMan123@users.noreply.github.com> Date: Fri, 6 Jan 2023 23:47:01 +0200 Subject: [PATCH] fix(IText): make clear contextTop always from the main render cycle (#8560) --- CHANGELOG.md | 3 + src/canvas/canvas.class.ts | 27 ++- src/canvas/canvas_events.ts | 4 + src/shapes/Object/InteractiveObject.ts | 2 +- src/shapes/itext.class.ts | 37 +-- src/shapes/textbox.class.ts | 1 - test/lib/visualTestLoop.js | 2 +- test/visual/freedraw.js | 217 +++--------------- test/visual/golden/mesh_withText.png | Bin 0 -> 11039 bytes test/visual/golden/textSelectionClearing.png | Bin 0 -> 12455 bytes test/visual/golden/textSelectionClearing2.png | Bin 0 -> 12642 bytes test/visual/golden/textSelectionClearing3.png | Bin 0 -> 14955 bytes test/visual/golden/top_ctx_withText.png | Bin 0 -> 8467 bytes test/visual/text.js | 96 ++++++++ 14 files changed, 161 insertions(+), 228 deletions(-) create mode 100644 test/visual/golden/mesh_withText.png create mode 100644 test/visual/golden/textSelectionClearing.png create mode 100644 test/visual/golden/textSelectionClearing2.png create mode 100644 test/visual/golden/textSelectionClearing3.png create mode 100644 test/visual/golden/top_ctx_withText.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 760899de8da..97eba9b1b9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ - feat(): DrawShape, DrawOval, DrawPoly [#8430](https://github.com/fabricjs/fabric.js/pull/8430) - fix(): `_initRetinaScaling` initializaing the scaling regardless of settings in Canvas. [#8565](https://github.com/fabricjs/fabric.js/pull/8565) - fix(): regression of canvas migration with pointer and sendPointToPlane [#8563](https://github.com/fabricjs/fabric.js/pull/8563) +- fix(IText): refactor clearing context top logic of itext to align with brush pattern, using the canvas rendering cycle in order to guard from edge cases #8560 +- fix(Canvas): `_initRetinaScaling` initializaing the scaling regardless of settings in Canvas. [#8565](https://github.com/fabricjs/fabric.js/pull/8565) +- fix(Canvas): regression of canvas migration with pointer and sendPointToPlane [#8563](https://github.com/fabricjs/fabric.js/pull/8563) - chore(TS): Use exports from files to build fabricJS, get rid of HEADER.js [#8549](https://github.com/fabricjs/fabric.js/pull/8549) - chore(): rm `fabric.filterBackend` => `getFilterBackend` [#8487](https://github.com/fabricjs/fabric.js/pull/8487) - chore(TS): migrate text SVG export mixin [#8486](https://github.com/fabricjs/fabric.js/pull/8486) diff --git a/src/canvas/canvas.class.ts b/src/canvas/canvas.class.ts index 0438dbf40a2..6bce735f1cc 100644 --- a/src/canvas/canvas.class.ts +++ b/src/canvas/canvas.class.ts @@ -10,7 +10,21 @@ import { TPointerEvent, Transform, } from '../EventTypeDefs'; -import { Point } from '../point.class'; +import { + addTransformToObject, + saveObjectTransform, +} from '../util/misc/objectTransforms'; +import { StaticCanvas, TCanvasSizeOptions } from './static_canvas.class'; +import { + isActiveSelection, + isCollection, + isFabricObjectCached, +} from '../util/types'; +import { invertTransform, transformPoint } from '../util/misc/matrix'; +import { isTransparent } from '../util/misc/isTransparent'; +import { TOriginX, TOriginY, TSize } from '../typedefs'; +import { degreesToRadians } from '../util/misc/radiansDegreesConversion'; +import { getPointer, isTouchEvent } from '../util/dom_event'; import type { IText } from '../shapes/itext.class'; import { FabricObject } from '../shapes/Object/FabricObject'; import type { Textbox } from '../shapes/textbox.class'; @@ -1655,17 +1669,6 @@ export class SelectableCanvas< super._setSVGObject(markup, instance, reviver); instance.set(originalProperties); } - - setViewportTransform(vpt: TMat2D) { - if ( - this.renderOnAddRemove && - isInteractiveTextObject(this._activeObject) && - this._activeObject.isEditing - ) { - this._activeObject.clearContextTop(); - } - super.setViewportTransform(vpt); - } } Object.assign(SelectableCanvas.prototype, { diff --git a/src/canvas/canvas_events.ts b/src/canvas/canvas_events.ts index 037f9af3e4a..61ebae5af99 100644 --- a/src/canvas/canvas_events.ts +++ b/src/canvas/canvas_events.ts @@ -342,10 +342,12 @@ export class Canvas extends SelectableCanvas { source?: FabricObject, target?: FabricObject ) { + let dirty = false; const ctx = this.contextTop; if (source) { source.clearContextTop(true); source.renderDragSourceEffect(e); + dirty = true; } if (target) { if (target !== source) { @@ -354,8 +356,10 @@ export class Canvas extends SelectableCanvas { target.clearContextTop(true); } target.renderDropTargetEffect(e); + dirty = true; } ctx.restore(); + dirty && (this.contextTopDirty = true); } /** diff --git a/src/shapes/Object/InteractiveObject.ts b/src/shapes/Object/InteractiveObject.ts index 475146f04e5..6851bf5edb5 100644 --- a/src/shapes/Object/InteractiveObject.ts +++ b/src/shapes/Object/InteractiveObject.ts @@ -512,7 +512,7 @@ export class InteractiveFabricObject< * Clears the canvas.contextTop in a specific area that corresponds to the object's bounding box * that is in the canvas.contextContainer. * This function is used to clear pieces of contextTop where we render ephemeral effects on top of the object. - * Example: blinking cursror text selection, drag effects. + * Example: blinking cursor text selection, drag effects. * @todo discuss swapping restoreManually with a renderCallback, but think of async issues * @param {Boolean} [restoreManually] When true won't restore the context after clear, in order to draw something else. * @return {CanvasRenderingContext2D|undefined} canvas.contextTop that is either still transformed diff --git a/src/shapes/itext.class.ts b/src/shapes/itext.class.ts index a3d5f55128d..6a0b5e63520 100644 --- a/src/shapes/itext.class.ts +++ b/src/shapes/itext.class.ts @@ -221,7 +221,6 @@ export class IText extends ITextClickBehaviorMixin { */ initDimensions() { this.isEditing && this.initDelayedCursor(); - this.clearContextTop(); super.initDimensions(); } @@ -272,7 +271,6 @@ export class IText extends ITextClickBehaviorMixin { * @param {CanvasRenderingContext2D} ctx Context to render on */ render(ctx: CanvasRenderingContext2D) { - this.clearContextTop(); super.render(ctx); // clear the cursorOffsetCache, so we ensure to calculate once per renderCursor // the correct position but not at every cursor animation. @@ -280,14 +278,6 @@ export class IText extends ITextClickBehaviorMixin { this.renderCursorOrSelection(); } - /** - * @private - * @param {CanvasRenderingContext2D} ctx Context to render on - */ - _render(ctx: CanvasRenderingContext2D) { - super._render(ctx); - } - /** * Renders cursor or selection (depending on what exists) * it does on the contextTop. If contextTop is not available, do nothing. @@ -306,19 +296,10 @@ export class IText extends ITextClickBehaviorMixin { } else { this.renderSelection(ctx, boundaries); } + this.canvas!.contextTopDirty = true; ctx.restore(); } - /** - * Renders cursor on context Top, outside the animation cycle, on request - * Used for the drag/drop effect. - * If contextTop is not available, do nothing. - */ - renderCursorAt(selectionStart) { - const boundaries = this._getCursorBoundaries(selectionStart, true); - this._renderCursor(this.canvas.contextTop, boundaries, selectionStart); - } - /** * Returns cursor boundaries (left, top, leftOffset, topOffset) * left/top are left/top of entire text box @@ -406,6 +387,16 @@ export class IText extends ITextClickBehaviorMixin { return boundaries; } + /** + * Renders cursor on context Top, outside the animation cycle, on request + * Used for the drag/drop effect. + * If contextTop is not available, do nothing. + */ + renderCursorAt(selectionStart: number) { + const boundaries = this._getCursorBoundaries(selectionStart, true); + this._renderCursor(this.canvas.contextTop, boundaries, selectionStart); + } + /** * Renders cursor * @param {Object} boundaries @@ -468,11 +459,7 @@ export class IText extends ITextClickBehaviorMixin { * Renders drag start text selection */ renderDragSourceEffect() { - if ( - this.__isDragging && - this.__dragStartSelection && - this.__dragStartSelection - ) { + if (this.__isDragging && this.__dragStartSelection) { this._renderSelection( this.canvas.contextTop, this.__dragStartSelection, diff --git a/src/shapes/textbox.class.ts b/src/shapes/textbox.class.ts index a30ab866ad7..d7c9f4aac73 100644 --- a/src/shapes/textbox.class.ts +++ b/src/shapes/textbox.class.ts @@ -52,7 +52,6 @@ export class Textbox extends IText { return; } this.isEditing && this.initDelayedCursor(); - this.clearContextTop(); this._clearCache(); // clear dynamicMinWidth as it will be different after we re-wrap line this.dynamicMinWidth = 0; diff --git a/test/lib/visualTestLoop.js b/test/lib/visualTestLoop.js index d8c24f186c2..f6587b21ed1 100644 --- a/test/lib/visualTestLoop.js +++ b/test/lib/visualTestLoop.js @@ -188,7 +188,7 @@ } await fabricCanvas.dispose(); done(); - }); + }, assert); }); } } diff --git a/test/visual/freedraw.js b/test/visual/freedraw.js index fe0b609d412..3f8d053c908 100644 --- a/test/visual/freedraw.js +++ b/test/visual/freedraw.js @@ -3,15 +3,14 @@ canvas.freeDrawingBrush = brush; } var options = { e: { pointerId: 1 } }; - async function pointDrawer(points, brush, onComplete = false) { - const canvas = brush.canvas; - canvas.calcViewportBoundaries(); - setBrush(canvas, brush); + function pointDrawer(points, brush, fireUp = false, onMove = undefined) { + setBrush(brush.canvas, brush); brush.onMouseDown(points[0], options); for (var i = 1; i < points.length; i++) { points[i].x = parseFloat(points[i].x); points[i].y = parseFloat(points[i].y); brush.onMouseMove(points[i], options); + onMove && onMove(points[i], i, points); } if (onComplete) { await new Promise(resolve => { @@ -2243,195 +2242,37 @@ QUnit.module('Free Drawing', hooks => { } }); - function generatePointsToCover(width, height, step) { - const out = []; - for (let y = -height, side = 0; y < height; y = y + step) { - side++; - out.push(new fabric.Point(side % 2 ? -width : width, y)); - } - return out; + function withText(canvas) { + canvas.add(new fabric.IText('This textbox should NOT\nclear the brush during rendering')); + const brush = new fabric.PencilBrush(canvas); + brush.color = 'red'; + brush.width = 25; + pointDrawer(points, brush, false, (point, index, points) => index === points.length - 1 && canvas.renderAll()); } - const pointsToCover = generatePointsToCover(500, 500, 30); - - [fabric.PencilBrush, fabric.PatternBrush, /*fabric.CircleBrush, fabric.SprayBrush*/].forEach(builder => { - [true, false].forEach(vpt => { - [true, false].forEach(absolutePositioned => { - [true, false].forEach(inverted => { - tests.push({ - test: `clipping ${builder.name}${vpt ? ' vpt' : ''}${absolutePositioned ? ' absolutePositioned' : ''}${inverted ? ' inverted' : ''}`, - build: canvas => { - const brush = new builder(canvas); - brush.width = 30; - brush.color = 'red'; - const clipPath = new fabric.Circle({ - radius: 50, - absolutePositioned, - inverted, - canvas - }); - clipPath.viewportCenter(); - brush.clipPath = clipPath; - canvas.freeDrawingBrush = brush; - canvas.isDrawingMode = true; - vpt && canvas.setViewportTransform([1, fabric.util.degreesToRadians(45), 0, 1, 0, -100]); - return pointDrawer(pointsToCover, brush); - }, - name: `clipping/${builder.name.toLowerCase().replace('brush', '')}${vpt ? '_vpt' : ''}${vpt && absolutePositioned ? '_abs' : ''}${inverted ? '_inv' : ''}`, - percentage: 0.09, - width: 200, - height: 200, - targets: { - mesh: true - } - }); - }); - }); - }); - }); - - async function erase(canvas, brush, { inverted, clip }) { - if (inverted) { - brush.width = 8; - await new Promise(resolve => { - canvas.once('after:render', resolve); - pointDrawer(pointsToCover, brush, () => { - // run mouse up but don't add the path to canvas - }); - }); - brush.inverted = true; - } - if (clip) { - const clipPath = new fabric.Circle({ - radius: 50, - inverted: clip === 'inverted', - canvas - }); - clipPath.center(); - brush.clipPath = clipPath; + tests.push({ + test: 'textbox should not clear brush', + build: withText, + golden: 'withText.png', + percentage: 0.02, + width: 200, + height: 250, + fabricClass: 'Canvas', + targets: { + top: true, + main: false, + mesh: true, + result: false, + compare: false } - brush.width = 16; - return pointDrawer(points, brush); - } - - function eraser(canvas, { reverse = false, group = false, alpha = false, inverted = false, clip = false } = {}) { - const brush = new fabric.EraserBrush(canvas); - alpha && (brush.color = 'rgba(0,0,0,0.7)'); - const objects = [ - new fabric.Rect({ width: 100, height: 100, fill: 'blue' }), - new fabric.Rect({ width: 100, height: 100, left: 50, top: 50, fill: 'magenta', erasable: false }), - new fabric.Circle({ radius: 200 }), - new fabric.Rect({ width: 100, height: 100, left: 100, top: 100, fill: 'red', erasable: false, opacity: 0.8 }), - new fabric.Rect({ width: 100, height: 100, left: 0, top: 100, fill: 'red', erasable: false }), - new fabric.Circle({ radius: 50, left: 100, top: 100, fill: 'cyan' }), - new fabric.Group([ - new fabric.Circle({ - radius: 50, - left: 0, - top: 100, - fill: 'cyan', - clipPath: new fabric.Circle({ radius: 50, left: -12, top: -12, originX: 'center', originY: 'center' }) - }) - ], { - erasable: !group || group, - clipPath: new fabric.Circle({ radius: 50, left: 12, top: 12, originX: 'center', originY: 'center' }) - }), - ]; - canvas.add(...(group ? [new fabric.Group(objects, { erasable: group })] : objects)); - reverse && (canvas._objectsToRender = canvas.getObjects().reverse()); - return erase(canvas, brush, { inverted, clip }); - } - - function eraseBackground(canvas, { alpha = false, inverted = false, vpt = false, clip = false } = {}) { - const brush = new fabric.EraserBrush(canvas); - alpha && (brush.color = 'rgba(0,0,0,0.7)'); - canvas.setViewportTransform([1, fabric.util.degreesToRadians(45), 0, 1, 0, -100]) - canvas.backgroundImage = new fabric.Rect({ - width: canvas.width, - height: canvas.height, - fill: 'blue' - }); - canvas.backgroundVpt = vpt; - return erase(canvas, brush, { inverted, clip }); - } - - [{ alpha: true }, { alpha: false }, { inverted: true }].forEach(({ alpha, inverted }) => { - [true, false, 'inverted'].forEach(clip => { - const getName = (name = '') => `eraser/${name}${alpha ? '_alpha' : ''}${inverted ? '_inverted' : ''}${clip ? '_clipped' : ''}${clip==='inverted' ? 'inverted' : ''}`; - const getTestName = name => `${name} (${JSON.stringify({ alpha, inverted, clip }, null, 2)})`; - const main = !alpha && !inverted; - tests.push({ - test: getTestName('Eraser brush'), - build: canvas => eraser(canvas, { alpha, inverted, clip }), - name: getName(), - width: 200, - height: 250, - targets: { - main - }, - onComplete: undefined - }); - - tests.push({ - test: getTestName('Eraser brush - custom stack ordering'), - build: canvas => eraser(canvas, { alpha, inverted, clip, reverse: true }), - name: getName('custom_stack'), - width: 200, - height: 250, - targets: { - main - }, - onComplete: undefined - }); - - tests.push({ - test: getTestName('Eraser brush - group with `erasable = true`'), - build: canvas => eraser(canvas, { alpha, inverted, clip, group: true }), - name: getName('group'), - width: 200, - height: 250, - targets: { - top: false, - }, - onComplete: undefined - }); - - tests.push({ - test: getTestName('Eraser brush - group with `erasable = deep` should propagate eraser'), - build: canvas => eraser(canvas, { alpha, inverted, clip, group: 'deep' }), - name: getName(), - width: 200, - height: 250, - targets: { - main - }, - onComplete: undefined - }); - - [true, false].forEach(vpt => - tests.push({ - test: getTestName('Eraser brush - backgroundVpt'), - build: async canvas => eraseBackground(canvas, { alpha, inverted, clip, vpt }), - name: `${getName('background')}${vpt ? '_vpt' : ''}`, - width: 200, - height: 250, - targets: { - main: (inverted || alpha) && !vpt, - top: inverted && !vpt - }, - onComplete: undefined - }) - ); - }); }); - tests.forEach(({ name, targets, test: testName, ...test }) => { - const { top, main, mesh, result, onComplete = () => { }, ...options } = { ...freeDrawingTestDefaults, ...test, ...targets }; - QUnit.module(testName, () => { - top && visualTester({ - ...options, - test: 'top context', - golden: `freedrawing/${name}_top_ctx.png`, + tests.forEach(function (test) { + var options = Object.assign({}, freeDrawingTestDefaults, test.targets); + if (options.top) { + visualTester(Object.assign({}, test, { + test: `${test.test} (top context)`, + golden: `top_ctx_${test.golden}`, code: async function (canvas, callback) { canvas.on('interaction:completed', ({ result }) => { canvas.cancelRequestedRender(); diff --git a/test/visual/golden/mesh_withText.png b/test/visual/golden/mesh_withText.png new file mode 100644 index 0000000000000000000000000000000000000000..49ca9acb182d60dcf10d2bcb3693e2690556a8bf GIT binary patch literal 11039 zcmV+)E8x_LP)PyA07*naRCr$Poe8)mMRoUoH7qJ_0aOssKt#a}G#E`3*AGP56p$Sai6C(W#6$psXFJ>Ifjlp4s;wC$N|&wrsF`zfx#T;0MhM_jsrtD&;g{|9vufdfOLDH z<3KeIbP}W*-?~~;!hsGTQ?k(AG^=r-14uQ#b+x9119br8DZnnk+kj64Umug#n#0b( zzXMkS{|sC=W}990;v9Gaur2UU!1sZJi&t%a$qXQC`i;6(;30p^Gi(9y9AH1-?}5kr ze)b9gkiP`J0ld_=sRjBtuq^Ogy5?p%kgexFz?*?J{GYP*o)}*B1IQnN9{`v2Y%(!H z%y_Dw{W-uzJ)98Gwg6t(!>~PpzXF~P?AigO_4{W_;FZ8*fW4;yAR7V;fg6DL0=M;9 z!i|7aflWtzE%bGHJ#Z}WUEqDd!@kbyzzM((0VRk){zl+1f3)h3Sn2ThD1WqlPZbGb z;RPOOT0haNfZzF_MZlTBw+-m`S}2ns+WbcYn&`CyMp6_Ys;+h=H8%Hvd&sw`FV1KE zQA__6;)qoX;|g^8Sm48czV{R;-^3zC=I~MA6J-Em9S{x&UQ}?>pVP6q4xr=#vXj3w z4?4S-0f^?UyMZp^p9C_1JR0~6@Q#2Iq#%!z7ke@A5#S$zwgRNc9CYG1vM4|-d=q$6 zh1HN0*}=dME7YxAB?HK2z%zi;hO|@`Agg&vaXfH;uHF0>XHq4Ijvj{q&-0SBjQ}Y+ z2b~m79t98!e*yf$@3YDq7WfAP|1nMjW$Knu^OgdLg#&=){(kT$;77pk4LmC+k|z}) zukoAaiWUQ;=p2dyL=xbMWj5!KvdKUa6d=}}xj%sWTJ&w(!t(23!9M_(Oy(Wr*}#dw zOMvgS2_P2M*U|VRu=1f!0v4IWNPt*pmy#kV6bWpvHcrzTm4X1oy8Fgez~jn{_8$1% zn(!(EHIo^~#AsbuRaIpnjS{wIS_}>A z!gu;KUYR$!wr1uz7C(wNc6D^h|F9%4|z2u0Av;x!z=?OZNxQgHMd(E^!XA}xd%F6(|qng7)WfRqQi(u@L#K7c2A!=*H9wx>Pycbs=y zDGQK18+5$7#Q#H)BbF@El9G}V@+Zp!Q{D@o+64BMXn7snvIQ(!#f@F+_}>HPUI~BL z#QC>rju}AYv5=QkD?bSLt_IRBj!U;0SkE_-2Z$u-Z^g$A;lAr2CO&4YhpW5&A@?HL z*Lp#sA?kFYkKRz;c=sgDMITBjlxC7XyKHmXRIKM*Ie zdg;l2Q_ICg)K7xs4U{ro{SI`&DT&5&1%O3H~Js}^D2U9jYn zuAwHzwvTC($rsW+!y#2IV8(vMMnmyi+f35#G?Q?&J6-c{!A)^ z=;;H-F2k7m(UGpq5i8$ZQ3;X(Qm#0!^`5X9Fuv&TDrMGZ#TYd3ec_?6J0s=7#c<22 zvtRs>%O;S#GiL|U29-C)-PYabLP)Ej>!)NrWc1~@%*+fGtSv@V{f?B8GP7LrHK1V9w53GXi%#Zf1AP>t&|UD`wPsbgE4+E_+#_t1zSZc~ zaMQU?p&`;oQoeruDE~py-?b0k?(68(Fh_!C4U`7RwXmryeUWK(9+_#bVQM+EjzMFDWhYXn0ZIwxfGQk+shFz>swxXKliu%z~hPDoER$u7%&46>wNGc ze@9)1yTkblodgz*Qn0KI=>D1AowfEi`#Y=@BlD;{H5#Zz%FgV zqFI1k>NRtv+bUaOKls|0-Njl|Mk$g>9cc=6|L99)_WDL!!P)19wTKSohx}A@S@K^CdHpqTZ1R(0`Y2JDAEqyxvPjAN z^9+v>CMPwl?r_pRiiUkiv+h^&uTG^g6zQlXE$H|XWFcI->+I{X2=ndVq`pvh!D(x| zvwANTIb!AONIx#Eg^mL+?`cdDMQ2f6HkVuXcio5dKuBs$JuemMJS(G}j&9lvvVYtw zJH}OT_2=L%{vbT;i#7w0J>j8~oz||^q%~SF3y{1DJ?6ahRzxuxK@R z2NIYn)BUh?862~^dneyZI<_CGOVyJq_t310N5Pr^#$>eX*050e>q((I;m)<4$8HLVnAu?z=O8;`Nh-^JHb{c$gD8{0{{Fdm zW*n9$ge>TiK67kjrS2dNkRbE+l7(w`higuqwUqWV6iRI>6`l0uhp zsqm#<7l?X~Thb~DaQf)ZP?-&}Q4;}@O+>~6Df_SJZ%G$Gj?q`V_o8o|Sd}It73t3M zECY8v=#FxQtmLT%H)cQDbY=Eb zs2m6GG4ARnZwo0@^wAMW^kT7>vU`UdLgz?_TtV4UbbrxNYmVDW8GvlLEu4Q=xrx+S zS{f<2Y#d=gsyzj$Q|v5><gPfvuj3>9o1TnE z0?9$c_IfX>W-3aarPATWT1|m`Ed6b)fpzVUna@h*FSQU{Z|KBt!h@ m?TscAbKbh z%q=^~OuJ4dfdflSVy#~#fOsh)kjS7iNqYQA*hG^&ho6|)DE>+2Ss5T6By#3cG!Q-d z>8RsCYz}N~2CHhL^gR|pvJqMMzns%ol!11QPCW;fdwW(=Mg#$fmnMqV{r;q*?>d_% z4#+qt%Xv}?1`rPt1qt{{XJ$ychSSnnQteg7)Sv*#UEcM)I%F)?Y1stbJo|ItAybpr zLvVoP?j?Etj#khIzV#AF8R$UN=ZlaIk4gaYMr}vsVMmq&d?i;O8{F7B>_lI znkcfmvREm!R?@y};coFxvuKj;lj*_{DTrN1@CuVC##TRO*Rn}{J`s7IcV}*xcLBBT zU38ZBeVRe?h)MT^w=bV-0Z2}w$X#XHk6tI3*|@@z9tvnSZfvee0o6$c`o%CyHosZ{ z(sT5ZfB$om&Ab^M&2zr9E|E~3p_Q7!nVK)>850@-kQ`9-_0*GC#b3}f*-0loyVZjq zX=(IMUGJbxfnNe$Hbk}(~4n)X3Q*HphbYlUMlPU_y zBO_6#`mD6Xt*w;&?MGv@SXGwHOBBT{QXuh;rh@}ZP0jC(8ZSY5_kndWBNW2(8Qpn( zDo|1@NLmMwo(sJsiULos(|Hh2G+1f_NoxVpN3!U3qjHQZO5RhaL<=_2sOXv8VpGG* z)rkQ}AHc}1MM0^R+apCXmucFpbBI z&;U`Maphd_qW`3=IL#}+&%HgJS=pZU|#PVNl`B3eoQJo;sIxm0&fO~-x`;59@nrJz@D!5@UDYv1LzV^M8>iMTYA(!%B0bd6G z*T3wO+sJ!;Yf8xe5uY}<9~XxL#KL?0SGtb(9pb0%8~XYwx{8hmim;;0sXOF?x9#;1 zJZDuna6yg1%SLX|*#er^J}_f<%8axns#h+0mhr&>>ja6u=I6T1XJ`BP21?*5=T*_5 zJnC|ZlE0o@kushQ1c)|@vVk7z9sQ037U$TeU;@W@uUY-GewW)uzeI|C0peXfzS*D@ z$V)DUZ@&VRLtS3L3c#I3HNt?UOwliP<9$VZXfT*0-`&jQHrT-rYklnn*IL{|t|5G1^C>i^4{@?Ea zw!>|%UYZ9G>%P{zgkGIM?Ja)g{I;BG&T{2m+zklw7geF3sQ za5C^RA64Y^0UJ+ob`@_oBZ;){i~@*tVoYx~8c+HvNGu)?7y7TtZM}oG?(F)3nzL*D z`Dd`}OJILs3xC|zk>Yb_In5E4j9k_t;KA)>_pai)QZeAaro??|k_OT2eSqb(qpd(>lvNKYB=G}=RA*T9b z-vzwOk83sHD1Z0R7&RW9Hl(1CQX{6OGS8EIkm)u3F=wm9Vyrh3V=#c^Ma&NYHGKP+ zn{8%rX93%e*-!(jOH=j(-ML0+z_clKNq)7Lmg|MspwQ_20$6fLp!}`~A1GTvj?idyq)8m5MSC z+c^L^502T&Wgd%7y{Qs{0c0cG1$xu`MQ_a6?70+9ZmQO2%(-RNb%fDZegA@Q6N)aF z+Sgt165ml}fGmdJt(sQlD=DHQpEOC*rd=*6W!gq_?VCId>pdFu0Zc^-_$GsIFF>TAi7iE<0Yp+? zkB7umkBWl4Z7)yP@OR0U|T@=yLUT;3s`%q;zk?rK2R z+fR9^qcd>^5IKFly8&y|4WUL3+yD zkX1buooU>Ao?g-uYAK=Qr7Zy&|!5Ty)fN zpbieKu9uA=I}QzyUo&6Cg&c3!R>y%s9C+A7xci0%h@ALRKK1OjOUHqX1E(6$gTJ5@ z8X(eW>3u>+9S4$fAXZk~&;XI&QJ1VH>DK5vQ-nw3a?A&(&;XfM2gTqE(=}L%1KSul zr&NuCg@XaaIt%-a1^exabsPxAfnN8LQ0>mN6A~bY>peu!(e-ak!6f7+p4)n&riZZ&808yAAh3Fd-t%*sOm?8?&uwE;6bUkH!2V*d7`(xF6_Y`c+g8*S zDLCpnlCDUz5P6;}nh&<q=j7wsCoAl2b^4v|fUA;7GpzigcL7-Z5w(Apz2A31Zztuey#9 zMK;Q`mPumoNCA-6N)RtOlz$^(0FG(h@1^FQ%-)d#Aj*2AxLPskHUmmZ6O^orY@wjh z9W{po#~BydvsMau#JZU@YPem7r9>;sP3tl@MR|=@b}U`_6&yI(6boJ$on;{baux90 z=p%OVxPqwsES%}pmkEa5by1K55183B+y$$|D;5$UDcs#NPAGMmVyRXp3(p@nNl@j^ zyNbg&u$_Uko5G@y07)IR`kSU=&ULS`((~Y8^KZ(6wtO7FH7?J2V<^}Lu`Xbo0>`DK z(@cddu3i3;luJ~quc)sBOO3=A4h9glmpCtXHs4R164|UQ+(HCRSQX}Xb>?uOQFo7Q zWT63ar_ZyHa_x0#-?fNl%eqXyyQCak*H>WQxc31CLjy#S-xU!)HI3A4S@?b~ zNonfwb^VRzz+%(D$7-PgB5&R-6V+&zge|ei40zFK;auQ#VY};E3(bMD5o<#C->_Dx;p4;Ayu4U%2fR905$8K< z0SBf6AYO{3@XH#t`ZopO%lAi?r7PqzIRamx(Hlr}UNHKy`ERWvO1W14wn= z^{W{bAYO{d{-7hqG|*C0|O1agM>8Bnb9wd6|s!*2E6$A-3?fs?!;Ylrg8`wU< ze4}>J0mQR+LVTnY)Ok$r+OUrs}KowvM? zIi32ecL3>G1MA!{QiKW$z4`|kI4pFdW!tl`HSpcC^_p6~14y5hv9JVKrKyY7XIy(5 z_*xUjYh5hi4Vo~P5M$^7(jOqwY+YYt)}k_N`*j0*m8lS`tcCRfg)W*H>HsoeDSZ$( zdAK$?C&y(5Uf7h~XyI01-KLBu#5g*D4B?^&iQ;P2mH%$o8sBN+r?@V>$EQPhy5A7yv0g1NV|2tagUc8 zK^8XgkF6T@VGG2ZS~E!vnnPn5ZQ;YfAvIdu&oHoKpv4c;%!G$by~?f4=twT1CNv7qdncB;C zdenM}avboc0BT_+{@Jo_r^9}`-@+Nd8z&hVer`9JhJFNEal{&N{Lq{CL;X|J)e2nd z<%O%fgr@`YsjAf*chKA{d=mJ`6o5lh+{VB;O`L1%0n$XKjyt9)iznPj17Ws?9YDt2 z&4KG%cs&jMng*U~*4#-3-V&+pv77AxGByjtH85q8LyWVg+5UI!yrhTQlFeyp3MGe_ zf39(FS{h581Zlw1OrhkM;d&FjcYC)(2auWpG9mBtt8j5%vZE@E#IDmgfcOogx9SqT ztK&j>mKmqixDNxr0gg6sVr(W>ZQt8-q;j6bSYe~svVnodCpRjy@kUL!(%=0iksV_v z;7Ji4P032W(7+y*1{krDg-MS#If#4b7}zEvYlAgi8$i74_J1Xe$RWwHhjFQ(YbOie z0Cul^An6D22=L^l8fY7F2eB@Pq2f8!LAATF`&d?W=5efp?^&PgH_aJz7&DSe5P!eW z+jBV`)=9rI@jZhF&TqosbqrhAOANfc&V?`AcQSx9FqzI31~x6ruyM;zN|?|Jd}yr4 zZtW7pgF|lH$pBe!0nazERl%}j7n|@Wv!nR)-h3{_QH7iG_vjn81$zEuQ4**4Xw|5| z7iGW~6(9|k9C;o|4J@7fO=TEYw(OL-ujkpbOzQi#XswcJu`Gx=O%4W^@#7Z;{-*4v zFH^onyeKoRB4t~pwMqsM3wqx@lgGOy6wR`0U4ZFEJLN@MqazG_AX3{&nvHVAvM%!Z zfk|c%u9Gtj>=3TG*_PU#JFp^8?lu#UlQI@SWVMdccE!aiQtd$lk1JBJOqnT_9<9E2 z=)LR!zKZ^}QoDKo)xs+?v*AtZswmIk(R5YnQP` zRITzCfwxzyI(DtM8u;qitu&;8pc2G;=KiT6bE`6p%MHAsO2vM4YSLT@98z7^k+c1S z1`ZF!zb3R38X!jl?{31xDvlvogbfRI@ZwtrcDC>bB^a&9gR0feGcMr7L{Vsf)DcHF z^nwIAW?A=W>rtTxH>AB4!Pl&lASvmOCOsgN%r7)R{s(wTl99*l;)R~YxcXCf&yKorLFi4(>to#)?N1}KR$_s%)qBzA~=w}E3OY`y19 zCp17F1QZ{45=kkSUo*<7(ZZ{M3llP6j?KZs(nLWZt}*cJg!8PWtIz;>0C;RIGfC5_ z&iW@03zca>QRnwdGaPO@3i^(#E=&;Xg_BUUd{p|AlY<(W+ua69QI3W;fKI0BW;Q{G^=|_^e4u{-0~X&5P#z2NiS;O~1C8bvGDSuQj{-U=LF=Y*!9@1Y@dEd0?&#cv`j z6m=0P)8x`6{iEV4?>D?*|@}ps%KMQRv;b zg*$7EYBCP5RMiT=u+s`3A8&Yf$?mJ!ySh4{0P#{JMew*4IVYyfNcnqHAgrr}e*{hly?Yb3w_DvHi3yM-v3c`na{tx5AYtCa zgnMOPS4EFn{|5YPodX@CZ+&F{s?Ot9On{sPY&!;XidK~{}OYUQ%V{u{hSe$}cydcw{5VA3+uMq-|Qi+VUGl z14zP)`mqMyHF9_O0v;%zY^ipq-!w}HZL^^K^g9;iSwqTw-oSfOk0mxhQUtOtBtd!^ zYvBmseW@89slUQfB=$FAQQC~XJwN3Q>E zQ6!p?_MZ@-$hQ$2ASoOdOC7QLND_hM+O})EinyQ*+B_CM0m!%;bw32yyvb8ZM`ehG z`-zaXsfW>Hr*ZZQg}YlWNj_to+f8M%a60hD1_R|(1G`n8V1d6ljbbFdNHo)<)}YF`#o*|5qE@q5Op?UPY#fTXyCjCI871CqA-FD)^FjiS~C z?%pcdZXDgw!~rBlAh}PNfUXo?l3dZo_+I1OLx$W>bOQLLTs}tc-{>X&%fOqW_mb-% zwggF`<_#u6dZdZ8ThB#YSgwO#u+=j#dh@nwkcNTa7u8 zpaAg(Hw7*W+HN2QNMZ1OpH58{{?gR+J4tMS)cB0|QUfn5yQ|C&po0@9TTJ=sc zBtTN<2T!$NCk;#c>^IS$YkuebV-vwn<4*!$-qu~qnkfhP|t z>eZju0FN%#T+mXA9kphRoaNRXGgG9L>t#q3X;_8p9YBh6O&f6=<6OY|k_8>h)+yd( zkdp5-E_rBBvhL2IyGLqTWMK8woet_R7(o0{qb?Vdl>A)gt@C^LyU1HOR~oTI13J+} zu*rCdI8sRwX^#7v24yJ=4Upr2{UR~0iOtGuV0!~U&JWH9tJABzm}mDWVQ{Pqt#edO z%)Z++%#IcsAd{f#t+F@t_FfvikL9iNkg^ZfD{J9D<%&~<0fFk24qp_g-+|2p z1&BXpeUrqmzG5?}Li^gp@+{U%JlR%W8%Ua52JBG8MpJgo7UWg1N!fY<%SX|~jXS>J z0P!GEgpenVJGid?3H>_0HSxyay3u=;;c?yc70dlfHiYLU#*o$wW0vTOOY4g9vVF^ z(%8FZCxZj$8rZt2Q;7x;4-!cdxoXt;(7&m?@5bdg&<j2V6x_lJa&gVvN^?a%?V=HPFPFvli*-X@ivQ9&$;BFH&uO@AnF~)L;aapWdMH9J^ zEPNRFc#D(av}zL-80?j%UPs6RL+oEH?#UUgQ>F+Zd7LqmR5o2OU64GR?nLQE1V(dC8(!ylYLk|CbyMmEZB;ve~#w zvbS-?JAedQ5`TA*SFs`!>fOrITkH!aKq#ZsuYkjii%v6@)Bz;&vRmh*_jcI_e3V7~ z|0;lN29I*K%bDnl3f`vQm5o<1eYG|Ul&#=!+22&B_it)Lq)hOS52axhS>uO992ReXE(PDQ~Ezf}tAmw@1)tDj< Z{C^0(gNnd16ukfd002ovPDHLkV1fsR5Q6{! literal 0 HcmV?d00001 diff --git a/test/visual/golden/textSelectionClearing.png b/test/visual/golden/textSelectionClearing.png new file mode 100644 index 0000000000000000000000000000000000000000..153240362693027a0f35afeecc944ac427d8a797 GIT binary patch literal 12455 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 Ja#{1>{{yY4b(R1C literal 0 HcmV?d00001 diff --git a/test/visual/golden/textSelectionClearing2.png b/test/visual/golden/textSelectionClearing2.png new file mode 100644 index 0000000000000000000000000000000000000000..d0b46b55ad558217377776f7fa8ee271bdb0555b GIT binary patch literal 12642 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 literal 0 HcmV?d00001 diff --git a/test/visual/golden/textSelectionClearing3.png b/test/visual/golden/textSelectionClearing3.png new file mode 100644 index 0000000000000000000000000000000000000000..a0bf1191492e7aba8b6548cdd6757c2a8166c4c8 GIT binary patch literal 14955 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 literal 0 HcmV?d00001 diff --git a/test/visual/golden/top_ctx_withText.png b/test/visual/golden/top_ctx_withText.png new file mode 100644 index 0000000000000000000000000000000000000000..00fec78a57c484ff6fdc1bfb1e46280d3c0a3a5c GIT binary patch literal 8467 zcma)i^-~*Mur`nY!L>LvXmN@|(cqSpB0&O_BE_}EHQ}XDT#CCF_ux`0xE9w?0<^eO z3Z)d3|?zOtcmd=!S;c) zKw`)U3oocewXgMsK;$Ts~DA)dJqX;1t@SpFeVgF!qYP_TwVp0<6)D9T=Bc%ZDG zv)c%6%+aLqy+43$p9PUdk6I+2B|#c96W`gk)ps|&>PT4w;L-UOng1%lsSzt5kwd;g z{w2$uFV`k{Lhe+#Y$RGaCQT;)-63*oFFOZJw@wgjO%Cw@NQvodi4jIaW6T%ne%By= z?bG$(`iG_(Zw&18x9v+!aTLIl3!|<&KtGTy06oD52)lMH-%LYvqiG5W>Lv#I**JDwmD2ew5`M-6fv-mET_QuXEUdBT!9a58`F44dn#*-oCyp7^v zMd>8c;VPdmGI7q#-<^ZQm2iU?WHeYC3lo#gy;_(!D>-o#}dGutRCHG561{R24XW{=%^Mbp?OXiS$F&n+kvko z$G#qt<02Kz!&8pj4W7UThZ4FwyLtLO5RI=$PfF=gMB(`q+{k(SwnOh4=$UzZw~Uk;qEEn{mh)tUMGn9X~C z+da#tkF%>ZU~aK9B)$7M6PP*J_1?%-#8IrVSG+DWmUy5;<@)PNR!ffPa&@Us!Jzn^Zw<*1aGZS zgb<6Cz2Q74kuJhBo>8o)!Be8aB{tAosQ5O60jvM-TGCVB5zGVyAsFA4t=d38tNyvC zXPPpp@zwFHo5`|QUCP66U#nX?R%Y~pyGm3nkG%TPYWPwOVRpEuoAaisriCY7IJ8|K#3w!B53iIkiGpAl4w{p!A&4M1&Or^>Z`+dGkTQAN`RlLZlq&(AX1mXLZW9m}suR zGqdYfL<=nK9UUF=n91LHY`v8yn)7{4P#@l^K>1Wz?K%e~G)Pj}Ul>Ko-*{q(dC|j) zo;hUzsm)mha7QDc*xK81(IkGi3u>feM#Sfzfo70*@Dzpc=O5(WS-~(IqR8dkL6N^>D!Pl9GT|PcsCGa%+S1$RE|WIz zKsiT%ypYb_eUrNnVCgFK;}K7hYAi31(Hx4ky^`5A5pZ6qjd}w6WWUZOG-RaoadJs! z?QCY`JJgio)G$&{Ogqox3=s*{vln_+dW(3!tTlIp^}B}dYRb8VT) zhCbGs`Fx{%AP5pWySyvR6=`Q+INUtc&{pV5dqSzOJ|pMz^=Qahk9y!^`_E(T#e0MA zOXTljQv||;)it2;K2CkOc#YlZW7K>I6lpELw@;OBaXGGv!)4E%q6e_J?=J(P<`s~U zBc`~q*U;+AIokq9o+j`};{67*&pWWHTJmR5$4RjN1VSw_we;ASn_GJqB<5YX5K|mo zyH7{*BXZ}3SjyXUaLM;ik^K5v)?YvRTR(5HCK-=Oo>+6I?zXUGK*h1gjhSOVm^UiG ze|^_8$Mh0VWQxbE4N%*)mk5vbvmdQC^`BSJTXucv*Jun}CV99piV(jtcRa;0o-G5$yvdp4?UPf^g6ABdZ^`ts%MK>Y5avGAG47Al_vsE~M(4|abPAY5pj zji30Z*@T@dlyJ2#G}&4PUINuFi>g{UQKD|$g$|$ zRR%7ksFPL-EO5cZZ%>da3XZN{-ZEvWB#CM*?-fmSg&?~zm)(Y^8*Y~v0ds7HXlCeW ze|m2t3`Ti9mrj;uMdhp{@L3gC=$z6?_hR|T-A{3<*F;GGJK$#2$Z>ILp!m1IhHCGh zgy}N>FOR>lpzRHS5?-%$)%mwsyG^Gf3j;P+Xq3)YBO0%ahetc)V~7h>+Ts z2h9Ms{h6!7(f;-CdJJORBbDVbulhKaoCTP~Q;w|&5*R>9(Om0fj3u>Tx(Phmy#85vNw;!`1E%LMEytkp~fXvo4N@ zqyMu_txbR1BlqH<+w|qZ2Hve+>L{yL3%>@VEuZRG=DnuXaCeXmDS3XRA%oeyZODu~ zniIOT5S}^Lq!KAM=t?%qIpcnsJp>C|!&A zJ3mr6ryllpvKSHi_n-1*Rl%i0gY?3tRhW^xME&x@KbO|WcZ{ZVKR5U*I_+e^0;mr= zY=D~d%HTEl8+v8(5!G^c$}e#9ybx867kd*-$o=tX#^8ql{H?nEWHRtfgUWsOrX{jo zhF*_-Wikxk>s!>!*oRpUAh~42Bn}?J39Hh_Jp6Lp1#(|uwQ$_=B9Owu5z}~dcglpB z0)6!N!(uES4tFT76L2(~I6Q#q7Lgj{e16Ty+nfKmfsj8Bp*hF-GyIx)ogYk7`q96K;zeZx0p1FuOsz)mH?wZ4F9U!2 zAH{R?;uGVYvt!n}?Mzt;fU>5?>^u7|wKIVZXR6i;7y>_+`kdS9wSU937Cal?u}c1* zOsapRRHlMh>@kmuxURL6c>Tao3R`rb;9H3k$LGhNRpZqw+gS0|j}=vF!GEeemg^E* zb>l;7;cYFE5v%<4qqka?(>lGrpj=1m3Sag8w6hM>P@2P(qf$7%^fg^?yaPq>B}TYI zo&&Q+I4`plOpRs2AlYykOy(#^<%dm}>0m(gBsQz6-u<#HAG}Gf@#$Qfk~MSt8;{+y z72wH)qrk?Cz-I7SWaumnbwTfJPX+S%x1X*HpfgFp**uj*#}r|K_mOw^D_WzU_eP;{ zNK0Fvg%!-o2yS+6X`~(mp5%nr710xX68M>)OBuPJ?)QjK#vlM@M)jKAQ^~~W*lo(q z=LuC{>?3=8#zNcb6*K(b2X9hbiY>8(iv!91Z14NqN4P-oyQyH3R+MQHr%e5%G!0bn z@pwLk{7dsM(d3;`+v!B#3HZ8A{%{Sc)PN@hVyyB}hQ=H|Ef5(Vq>8vm)+;C~_ znk1rNXbJ(?x%|eIyWc31!>pnn;T>EpZ^Ko!pIQ zV5B321`D#D42X1o5nBFwbRbL3Uw203%Ai!mnlE3=-TF6A^m@b)_KQo8B&2Iv?`d0` zF=Y^bvk0FpFgvj3{q&<_nx%oXepMTgQh9u=-uAkKy7#10qBhraCp0cz2>Z~Ek(H_e zcUHH&wg(|c)IXiMjYy|9df>F9S@f$6Nf#Rnpz8<6E@@r#*{vw(;yu`0eS$w#{24`Q z%}K9Y!d&b+<(FCxQM|!HrY`g$uT;D1Y$?}N47%#}P5$jIRk+dCpOS*hAXyCa-9OKJ zuRfC`J<%VW0NleFy!G)}0hCON#beoMTVe4n3Ih0Zc0Km!m$MPVg9;&K(l6Ey{C<90 zfP;R}Zx;f+s-uq{w|xDn+WDO;*njTw>1xl44cTGr?GM4gH-O#JKh&n}z{RJ=x98{; z1gbp^YmUJ^M`e25eAe6EkT%n?6Wpuq3waVfpsK6-hQcFy$8g$@OkT1~hR&BDL6`4y zx7&60Ly2LgmU6e;-+2y82pB~q>B!32_VN7PQ-H8&U(6cU2}THjvPog1-O@RvtEuKP zjEhC~kDK@&p7_oN;#!KG4G;oIm*>7h$9!m|gp)*qRmFz~f{=b?xfXBGd9zy^N$*Y! z{LU2}{ATDyfQ*a)MAoY>o{z9W7uVvRg~vKM^A4{NnA!4e@9~!)vDbEjtGG2O`-Snz zE`ET535XRUl5-JEXcj!A4-(4<&$wFVKXrbQ+W5BynIX+b$zLCNiQ6G;o@oRUd&Qea zBW>2c!;-os56HoaF$-DX*JQ-XD`I(pS*T*p_jk@^F=5hfabdOtQSEgKgRb@yDHk?P z=!Q%2bvLnYwTV69fy%J5wBcWRVr@C!|GcsDov35xg8kb3(e*b=q5IO?u5_())hIEe zNsEq+&`}_JE^3@cMw?R`x~Ga(M)=E}-2a!lsRob>UOp_Uh~uY=|Y!Il*ctR<;*b|@6G;4ZBi|{Bw~`$KWjH|w{8ON$J%*rioI}1t+;B+ ziBf1QW+Cq$iZC}thM{%b-paUNA!MlhKXHhEzC6@P{iRt*gQ#I#q38+tM}Iwgp(sgy z*)(8mF+hW}WW?S2EpJwuE z`J)Jb;jB=of}fB6+6w|Js*gt<)k455W|go<7p~isp7U6@u!V8e&OW}Z=THR;S>XMz z^1$yYZu|mT1ghUZr`Zx+vef!%R;aRT*`Nf6ZttXc>u3)?Lb;1Z?KCN+UtPd0b&r{h z>g02V_#}_q`X|FxNrU+%qTTlWu4N5mMT+Yi%o<#+G4#!1W%nVe@9EXx(%NqmPgSfB zaT3el>ON$M41!<%ENSMZZ#_~|r)0Fk3Q?)=Ngn^Umr|l7>~##@OeIN=?HcIR`|U?x)arY9?5n$ z^z*6xvxWcKNb?u_@WU2F-7F@h8q`OS9?QNGC_4tdT|7Xd2k~O}4gFWBBMD1W>msxl zCF4EhD#yg`LXI&Zb+r^fUR|QQ8$J*WUYB6e^@8tMggy=)@Kv6CJg#e#*akO~?R8Y? zEd&nxZ!>(;a<=}3t#`$<_};A`{_^p=UH8i4uHx31s;^C8Pj6oW>He)Kg8SZIr5-7L zs-_aZ;CbD7Gv?}?(fB>bRxw*^$+QQr7vSXO%~B&I5*m-iPSTZqG%KZs=tklBlh^Sx zfUx*nJ8R9bxxZmh%S6^i>eT%)yf3As>Xd8dgq2;})^mKm)kx!gJJ*zoifYY@N!HI> z`ytdTBQl=XJgK}H-RxuaG<9rE=jKnS(0Ph}|M3hRPT)yTFOJRCEXeGln{ES7EvQ=s zf*Bh8x{BXqEPwBRvRlWUO8fwwC&aF=vo31m8FrZ$+o7Ml?5UmV)W|FA48ORBRU;!p zHZxQedWpP2C!H+M<_!ou*rWtY`+uAh_@X^~@Z!*43f&sT^|n22ic&mKr6(o(LCW2( z&90Y@`}w_*IR+cVyDn&Rh)p@OUa*SBuL2L$9mNTjHzmpq8$qx>kA4sI7*mgy^g$eU z|JcVhubHj9W`#mdp-I(9pB&<3r+Xz_IYyb1%3wO1FkUzVo_RZH@nhxK8*Er-<@&Xt z-5Hd!>ilLK`w9eSeTH{m873Jtqjfcln`Q!OcdC8?ADyu6=q z3@Lvo*jpRrp!&M6)_f9ya|%!x+u${3*%j8#V9f@!%1@h1i9!h0{`Q*1k=XXVv?195 z=2JNuye%@%(?uzX=D$uaAcCwWq!!>j8}qy3n7$@Hd)!~$`7~8da4WCe`=^4GdT(hB z$rfwBQXId;9vv)eQW|mvOwd{?Vrx;Di%f`Q&NaDXDM~U%xo>1R-Fwr%1*dwThRPf> zHX^X{aKKW!-f~3^*wT~Ii|k}pm}RGj`iq-9{WP1vlOKALkPcQ6bCdLAnj4)LPwT?huGHoKnYCF7KdXCtHTNLGozN^W~tzMpklJy6CRQ) zV*p~CtIZG9?w0PFHXk=N4G5P8TqjJyg`u;7*KV8AL_OJK5otBakF!Rdsbj$ZNFC4K z!E~b(9ISdFKfj4pg_U#Hp2r3UaCJT1m>M#-Szswf;bAc2mM;}lV(`dye3f+!1 zV(lcu@ZE7-*jll9j7g_|(;VINgjCx=x=MlO#9#py$+4<2l?-j~W^G4ywiIw<`gLV; zte`6(clDJ=;`g0@lcaZtf~a<(dSUwQU!sed3&|z+`2f=HYWt;*7<_=hkCkY1;VZXo zH>>Iqg&h^az5xV7l2TLFup4Cived=A&+e2gf{N=0W8>L$p7Da|+{L!RZWI8Bbx6uZe(2#eVLjY87nd)R+OP6=p{O4heMva^#+_TAqUCA3{ft5Dj3 zQzOTbB}l?afnApEh`39M02I|1_+~pS2N2h(p7^xEWNi$3<|Aa|p@oVImRHog6jpo} zJGWV0GRQ%sLfHoG;7E~DL%LtsC%-Dbw%g?FXYMv(DI72bCjTTFKy27k^XjWmaTzlJ z`S5Aieo=0DT{fj{iMxq5!5SZ0I)c`*L)N+W)H2)`FiMgFLMsNwZm;oS7K_kKyP@mN zPJ$3a^6F*b*Q{S92_UYmttmNki%!K|b4e(F?&vPh)Ge|4%RoG3;s|j|8OgO1X;?>r z_CqUYQ+)lH!QXrf_gue!Uk#mR@>RI~E?G5Ve7W1Gd5#9&<1;L*4vr2!ROImj3Af zSNZ$xjT`AtR0BMQ#kn>?&m=3{kCqM#*+KdMPctj7Vzm?9gsVrGArJJER_n?(mk2gS z^y8GXc;3cRjDF&H>1SO?u*#6lX6qM<>w~qovNBG%KKFr>ttrmeR`Vm`L7r zgtPU{th3VZ*+_KPM^1mGt z+ikMkLYA&cUFlrHD_RXf1|GC^(w_gc&GP=7+hD9NtIo4^drRhtshU^eD`O1o+Zwn; zO-yJ=4`r#Mb9VGf)(9}zwW-i;sq?b>BIUfboS1D-@_`mAYSuh>TY{9dk$zUG-~seP z#2fMOh@N(@tW6v%9)UeJ-#UHaAiChA!N9)NMvJG>BLB2!4D;$_d7vK3%4d|GvT%WF zBr9pIxM1!Zc!fy-`}GlI6|*?fI??w8@Ag^hl0x=F!a-HFjjv9v1Ua3oO9sn5cBH7U zU9VORwimi<)AL%!!BpzmUaRLX=b6TvJOs=6Q?<~`M@*%3moC(!O{OBJZ`;mTo>vbC z^e6ZnIcATzLg4s`F6I-q_u%aIfbDY_r6zR%$SlZeQ|E>oc;rphr3m1CI_=4Fwb_0^ zY+5Q*kdpsQV9oF6Mw1eAC_7*L%4lWqEsRuv)rqv+nTT`vDLP9ZI4$=&D|;~1E1i0D z##atlV+Q-<+Y01=^xp$4TFTrjnyy0HiOdNT;8id$N-fj@IUo20ICYkDY4Fbifh+Yo zVx*v+4iA}zK8lp7)fmjGa3NByUG()So_7AU6eH@PRnHLv|6q7&>V$1rQrk)K6QxY@ z^~j^-5mVfJuaorZQy%*&1Qy#=BsZn2S`rZ=))9}ALFUlH_vkkc@Osa>Q0ZdfE` z+-{TGB-e}L5i%{-dsPDQo4AICbV}T^hME9i%P{RV4NPh|b0|r={zN{wN(1*Cp@+6c4Sn84rW>?(oW~i_^(h zi)qf~oSyN>%T98GdQkBv@8jCb6W+I;({+>a0a&Gpe%+l)a7I%P=L6(9Bf<;d7_;}J z8S;A4P>CzsVHG|5Kb!%N_g0DSV9JgvW`U=7wB&}X?nURq|0hRS4waA&^a5K<&9Aow zNt(-;4$awzKpYbzzhi|Tx=s$yUS3$;ZxbZAsaKQJ^3zz4fICPuE2B-0`%S;moiY>T zKkAxZJbZ+jRbF-KCC5eU9F%sxYx&fCN9=C}dVcna+vA9Q5cx0|@acbM0j3`ach#v? z#G?+nkTirDHr6i>zwKX2QPB@MwkZiF6IK7_Q7h07C#}^bb@ZwDjoXhh*&dw1(N>44)u~vc{vXfn`bPi& literal 0 HcmV?d00001 diff --git a/test/visual/text.js b/test/visual/text.js index 20cc2ffbd59..fde1662a968 100644 --- a/test/visual/text.js +++ b/test/visual/text.js @@ -491,5 +491,101 @@ percentage: 0.092, }); + + // sinon could have spied this w/o effort and in one line + class TestTextbox extends fabric.Textbox { + __calledInitDimensions = 0; + initDimensions() { + super.initDimensions(); + this.initialized && this.__calledInitDimensions++; + } + } + + function selectionClearingEdgeCases(canvas, callback, assert) { + const text = new TestTextbox('lorem ipsum dolor sit Amet consectgetur', { + width: 200, + centeredRotation: true + }); + canvas.add(text); + canvas.setActiveObject(text); + text.enterEditing(); + text.selectAll(); + canvas.renderAll(); + text.rotate(90); + text.scale(0.8); + canvas.centerObject(text); + canvas.renderAll(); + assert.equal(text.__calledInitDimensions, 0, 'initDimensions was not called'); + canvas.getContext().drawImage(canvas.upperCanvasEl, 0, 0); + callback(canvas.lowerCanvasEl); + } + + tests.push({ + test: 'Text selection clearing edge cases: transform', + code: selectionClearingEdgeCases, + width: 200, + height: 200, + disabled: fabric.getEnv().isLikelyNode, + golden: 'textSelectionClearing.png', + percentage: 0.02, + fabricClass: 'Canvas' + }); + + function selectionClearingEdgeCases2(canvas, callback, assert) { + const text = new TestTextbox('lorem ipsum dolor sit Amet sit Amet', { + width: 200, + }); + canvas.add(text); + canvas.setActiveObject(text); + text.enterEditing(); + text.selectAll(); + assert.ok(canvas.contextTopDirty, 'flagged as dirty'); + canvas.renderAll(); + text.width = 150; + text._forceClearCache = true; + canvas.renderAll(); + assert.equal(text.__calledInitDimensions, 1, 'initDimensions was called'); + canvas.getContext().drawImage(canvas.upperCanvasEl, 0, 0); + callback(canvas.lowerCanvasEl); + } + + tests.push({ + test: 'Text selection clearing edge cases: changing width, `initDimensions`', + code: selectionClearingEdgeCases2, + width: 200, + height: 200, + disabled: fabric.getEnv().isLikelyNode, + golden: 'textSelectionClearing2.png', + percentage: 0.02, + fabricClass: 'Canvas' + }); + + function selectionClearingEdgeCases3(canvas, callback, assert) { + const text = new TestTextbox('lorem ipsum dolor sit Amet consectgetur', { + width: 200 + }); + canvas.add(text); + canvas.setActiveObject(text); + text.enterEditing(); + text.selectAll(); + canvas.renderAll(); + canvas.setViewportTransform([0.8, 0, 0, 1, 0, 0]); + canvas.renderAll(); + assert.equal(text.__calledInitDimensions, 0, 'initDimensions was not called'); + canvas.getContext().drawImage(canvas.upperCanvasEl, 0, 0); + callback(canvas.lowerCanvasEl); + } + + tests.push({ + test: 'Text selection clearing edge cases: vpt', + code: selectionClearingEdgeCases3, + width: 200, + height: 200, + disabled: fabric.getEnv().isLikelyNode, + golden: 'textSelectionClearing3.png', + percentage: 0.03, + fabricClass: 'Canvas' + }); + tests.forEach(visualTestLoop(QUnit)); })();