-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Progress on reflow smaller with wide chars
- Loading branch information
Showing
4 changed files
with
238 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/** | ||
* Copyright (c) 2019 The xterm.js authors. All rights reserved. | ||
* @license MIT | ||
*/ | ||
import { assert } from 'chai'; | ||
import { BufferLine } from './BufferLine'; | ||
import { reflowSmallerGetNewLineLengths } from './BufferReflow'; | ||
|
||
describe('BufferReflow', () => { | ||
describe('reflowSmallerGetNewLineLengths', () => { | ||
it('should return correct line lengths for a small line with wide characters', () => { | ||
const line = new BufferLine(4); | ||
line.set(0, [null, '汉', 2, '汉'.charCodeAt(0)]); | ||
line.set(1, [null, '', 0, undefined]); | ||
line.set(2, [null, '语', 2, '语'.charCodeAt(0)]); | ||
line.set(3, [null, '', 0, undefined]); | ||
assert.equal(line.translateToString(true), '汉语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 4, 3), [2, 2], 'line: 汉, 语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 4, 2), [2, 2], 'line: 汉, 语'); | ||
}); | ||
it('should return correct line lengths for a large line with wide characters', () => { | ||
const line = new BufferLine(12); | ||
for (let i = 0; i < 12; i += 4) { | ||
line.set(i, [null, '汉', 2, '汉'.charCodeAt(0)]); | ||
line.set(i + 2, [null, '语', 2, '语'.charCodeAt(0)]); | ||
} | ||
for (let i = 1; i < 12; i += 2) { | ||
line.set(i, [null, '', 0, undefined]); | ||
line.set(i, [null, '', 0, undefined]); | ||
} | ||
assert.equal(line.translateToString(), '汉语汉语汉语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 11), [10, 2], 'line: 汉语汉语汉, 语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 10), [10, 2], 'line: 汉语汉语汉, 语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 9), [8, 4], 'line: 汉语汉语, 汉语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 8), [8, 4], 'line: 汉语汉语, 汉语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 7), [6, 6], 'line: 汉语汉, 语汉语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 6), [6, 6], 'line: 汉语汉, 语汉语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 5), [4, 4, 4], 'line: 汉语, 汉语, 汉语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 4), [4, 4, 4], 'line: 汉语, 汉语, 汉语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 3), [2, 2, 2, 2, 2, 2], 'line: 汉, 语, 汉, 语, 汉, 语'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 12, 2), [2, 2, 2, 2, 2, 2], 'line: 汉, 语, 汉, 语, 汉, 语'); | ||
}); | ||
it('should return correct line lengths for a string with wide and single characters', () => { | ||
const line = new BufferLine(6); | ||
line.set(0, [null, 'a', 1, 'a'.charCodeAt(0)]); | ||
line.set(1, [null, '汉', 2, '汉'.charCodeAt(0)]); | ||
line.set(2, [null, '', 0, undefined]); | ||
line.set(3, [null, '语', 2, '语'.charCodeAt(0)]); | ||
line.set(4, [null, '', 0, undefined]); | ||
line.set(5, [null, 'b', 1, 'b'.charCodeAt(0)]); | ||
assert.equal(line.translateToString(), 'a汉语b'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 6, 5), [5, 1], 'line: a汉语b'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 6, 4), [3, 3], 'line: a汉, 语b'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 6, 3), [3, 3], 'line: a汉, 语b'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line], 6, 2), [1, 2, 2, 1], 'line: a, 汉, 语, b'); | ||
}); | ||
it('should return correct line lengths for a wrapped line with wide and single characters', () => { | ||
const line1 = new BufferLine(6); | ||
line1.set(0, [null, 'a', 1, 'a'.charCodeAt(0)]); | ||
line1.set(1, [null, '汉', 2, '汉'.charCodeAt(0)]); | ||
line1.set(2, [null, '', 0, undefined]); | ||
line1.set(3, [null, '语', 2, '语'.charCodeAt(0)]); | ||
line1.set(4, [null, '', 0, undefined]); | ||
line1.set(5, [null, 'b', 1, 'b'.charCodeAt(0)]); | ||
const line2 = new BufferLine(6, undefined, true); | ||
line2.set(0, [null, 'a', 1, 'a'.charCodeAt(0)]); | ||
line2.set(1, [null, '汉', 2, '汉'.charCodeAt(0)]); | ||
line2.set(2, [null, '', 0, undefined]); | ||
line2.set(3, [null, '语', 2, '语'.charCodeAt(0)]); | ||
line2.set(4, [null, '', 0, undefined]); | ||
line2.set(5, [null, 'b', 1, 'b'.charCodeAt(0)]); | ||
assert.equal(line1.translateToString(), 'a汉语b'); | ||
assert.equal(line2.translateToString(), 'a汉语b'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line1, line2], 6, 5), [5, 4, 3], 'lines: a汉语, ba汉, 语b'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line1, line2], 6, 4), [3, 4, 4, 1], 'lines: a汉, 语ba, 汉语, b'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line1, line2], 6, 3), [3, 3, 3, 3], 'lines: a汉, 语b, a汉, 语b'); | ||
assert.deepEqual(reflowSmallerGetNewLineLengths([line1, line2], 6, 2), [1, 2, 2, 2, 2, 2, 1], 'lines: a, 汉, 语, ba, 汉, 语, b'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/** | ||
* Copyright (c) 2019 The xterm.js authors. All rights reserved. | ||
* @license MIT | ||
*/ | ||
|
||
import { BufferLine } from './BufferLine'; | ||
|
||
/** | ||
* Determine how many lines need to be inserted at the end. This is done by finding what each | ||
* wrapping point will be and counting the lines needed This would be a lot simpler but in the case | ||
* of a line ending with a wide character, the wide character needs to be put on the following line | ||
* or it would be cut in half. | ||
* @param wrappedLines The original wrapped lines. | ||
* @param newCols The new column count. | ||
*/ | ||
export function reflowSmallerGetLinesNeeded(wrappedLines: BufferLine[], oldCols: number, newCols: number): number { | ||
const lastLineLength = wrappedLines[wrappedLines.length - 1].getTrimmedLength(); | ||
// const cellsNeeded = (wrappedLines.length - 1) * this._cols + lastLineLength; | ||
|
||
// TODO: Make faster | ||
const cellsNeeded = wrappedLines.map(l => l.getTrimmedLength()).reduce((p, c) => p + c); | ||
|
||
// Lines needed needs to take into account what the ending character of each new line is | ||
let linesNeeded = 0; | ||
let cellsAvailable = 0; | ||
// let currentCol = 0; | ||
|
||
// Use srcCol and srcLine to find the new wrapping point, use that to get the cellsAvailable and | ||
// linesNeeded | ||
let srcCol = -1; | ||
let srcLine = 0; | ||
while (cellsAvailable < cellsNeeded) { | ||
// if (srcLine === wrappedLines.length - 1) { | ||
// cellsAvailable += newCols; | ||
// linesNeeded++; | ||
// break; | ||
// } | ||
|
||
srcCol += newCols; | ||
if (srcCol >= oldCols) { | ||
srcCol -= oldCols; | ||
srcLine++; | ||
} | ||
if (srcLine >= wrappedLines.length) { | ||
linesNeeded++; | ||
break; | ||
} | ||
const endsWithWide = wrappedLines[srcLine].getWidth(srcCol) === 2; | ||
if (endsWithWide) { | ||
srcCol--; | ||
} | ||
cellsAvailable += endsWithWide ? newCols - 1 : newCols; | ||
linesNeeded++; | ||
} | ||
|
||
return linesNeeded; | ||
// return Math.ceil(cellsNeeded / newCols); | ||
} | ||
|
||
/** | ||
* Gets the new line lengths for a given wrapped line. The purpose of this function it to pre- | ||
* compute the wrapping points since wide characters may need to be wrapped onto the following line. | ||
* This function will return an array of numbers of where each line wraps to, the resulting array | ||
* will only contain the values `newCols` (when the line does not end with a wide character) and | ||
* `newCols - 1` (when the line does end with a wide character), except for the last value which | ||
* will contain the remaining items to fill the line. | ||
* | ||
* Calling this with a `newCols` value of `1` will lock up. | ||
* | ||
* @param wrappedLines The wrapped lines to evaluate. | ||
* @param oldCols The columns before resize. | ||
* @param newCols The columns after resize. | ||
*/ | ||
export function reflowSmallerGetNewLineLengths(wrappedLines: BufferLine[], oldCols: number, newCols: number): number[] { | ||
const newLineLengths: number[] = []; | ||
|
||
// TODO: Force cols = 2 to be minimum possible value, this will lock up | ||
|
||
const cellsNeeded = wrappedLines.map(l => l.getTrimmedLength()).reduce((p, c) => p + c); | ||
|
||
// Use srcCol and srcLine to find the new wrapping point, use that to get the cellsAvailable and | ||
// linesNeeded | ||
let srcCol = -1; | ||
let srcLine = 0; | ||
let cellsAvailable = 0; | ||
while (cellsAvailable < cellsNeeded) { | ||
srcCol += newCols; | ||
if (srcCol >= oldCols) { | ||
srcCol -= oldCols; | ||
srcLine++; | ||
} | ||
if (srcLine >= wrappedLines.length) { | ||
// Add the final line and exit the loop | ||
newLineLengths.push(cellsNeeded - cellsAvailable); | ||
break; | ||
} | ||
const endsWithWide = wrappedLines[srcLine].getWidth(srcCol) === 2; | ||
if (endsWithWide) { | ||
srcCol--; | ||
} | ||
const lineLength = endsWithWide ? newCols - 1 : newCols; | ||
newLineLengths.push(lineLength); | ||
cellsAvailable += lineLength; | ||
} | ||
|
||
return newLineLengths; | ||
} |