The basis of the rasterization algorithm is taken from freetype, as this is a high-quality, time-tested open font engine. The algorithms themselves changed a bit so that the execution speed was higher exactly in the browser, since we write in javascript.Oleg, lead programmer
But, for example, we had to write a cache of letters in two versions: for Internet Explorer and for all others. Due to the specifics of the browser in IE, the first implementation was slow.
There are two main scenarios for using Excel:Alexander, leading programmer
- financial calculations
- creating forms (invoices) for further filling and printing.
A large number of forms were created before the appearance of our table editor, so our task was not only to learn how to open them correctly, but also correctly calculate column widths and row heights. Otherwise, when printing, the form might not get on the sheet.
For example, the standard column width in Microsoft Excel is 8.43 characters. It is calculated from the default width of 8 characters, which is converted to pixels depending on the Normal style. Then, as it turned out, the resulting number is rounded to the nearest multiple of 8.
Another feature is the height of the line. In Excel, you cannot set the line spacing, as, for example, in Word, so the calculation of the height of a line in Excel is different from the calculation of the height of a line in Word. For example, the comparison in the Cambria Math 11 font:
As a result, we implemented the calculation so that not a single character was cut off.
Most of the spreadsheets one way or another contains the formula. To solve the problems of parsing and counting formulas, a parser and a calculator were implemented. Also in the work with formulas, the construction of dependencies between cells deserves special attention. For this purpose, a topological sorting algorithm was used, which allows building a dependency tree traversal order.Dmitry, programmer
To test the ONLYOFFICE installation, we deployed it and started the familiar process. In total, about 15,000 tests ran, which run on 80 machines. By the way, we host them now on the Digital Ocean and in the near future we will tell how the entire test structure was transferred there.Stas, Head of Testing
Are we afraid of someone borrowing our code for personal gain? Not. The use of the ONLYOFFICE code is clearly stated in the license, and here we are protected by international law.Alexandra, head of the promotion department
Do we think that someone will “watch” and make a similar product? Of course, we think. But the guys will take at least 3 years to do this, so we don’t really worry too much. However, we have long been accustomed to be and survive in a highly competitive environment.
Any text editor begins with splitting the text into lines and rendering. The first working version consisted of 150 lines of code and was implemented as follows:
// ParaText function ParaText(value) { this.Value = value; this.Type = para_Text; this.Width = 0; this.Height = 0; } ParaText.prototype.Draw = function(X, Y, Context); ParaText.prototype.Measure = function(Context);
// ParaSpace function ParaSpace() { this.Type = para_Space; this.Width = 0; this.Height = 0; } ParaSpace.prototype.Draw = function(X,Y, Context); ParaSpace.prototype.Measure = function(Context); // ParaNewLineRendered function ParaNewLineRendered() { this.Type = para_NewLineRendered; this.Width = 0; this.Height = 0; } ParaNewLineRendered.prototype.Draw = function(); ParaNewLineRendered.prototype.Measure = function(); // Paragraph function CParagraph() { //................... // this.X = 0; this.Y = 0; // this.XLimit = 0; // , ParaText, ParaSpace ParaNewLineRendered this.Content = new Array(); // . this.dLineHeight = 0; //................... } CParagraph.prototype.Recalculate = function() { // . ParaNewLineRendered //.............................. // var X = this.X, Y = this.Y; // var CurLine = 0; var bNewLine = false; var bFirstItemOnLine = true; var bWord = false; var nWordStartPos = 0; var dWordLen = 0; for ( var nPos = 0; nPos < this.Content.length; nPos++ ) { var Item = this.Content[nPos]; switch( Item.Type ) { case para_Text: { var dLetterLen = Item.Measure( Context ).Width; if ( !bWord ) { // , , . if ( !bFirstItemOnLine ) { if ( X + dLetterLen > this.XLimit ) { // - this.Content.splice( nPos, 0, new ParaNewLineRendered() ); bNewLine = true; } } if ( !bNewLine ) { nWordStartPos = nPos; dWordLen = dLetterLen; bWord = true; } } else { if ( X + dWordLen + dLetterLen > this.XLimit ) { if ( bFirstItemOnLine ) { // // . . X += dWordLen; this.Content.splice( nPos, 0, new ParaNewLineRendered() ); bNewLine = true; } else { // this.Content.splice( nWordStartPos, 0, new ParaNewLineRendered() ); nPos = nWordStartPos; bNewLine = true; } } if ( !bNewLine ) { dWordLen += dLetterLen; } } break; } case para_Space: { bFirstItemOnLine = false; var dSpaceLen = Item.Measure( Canvas ).Width; if ( bWord ) { // , - X += dWordLen; bWord = false; dWordLen = 0; } if ( X + dSpaceLen > this.XLimit ) { bNewLine = true; } else X += dSpaceLen; break; } } // if ( bNewLine ) { bNewLine = false; bFirstItemOnLine = true; bWord = false; dWordLen = 0; // , X = this.X; Y += this.dLineHeight; CurLine++; } } } CParagraph.prototype.Draw = function(Context) { var Y = this.Y; var X = this.X; var nCount = this.Content.length; for ( var nPos = 0; nPos < nCount; nPos++ ) { var Item = this.Content[nPos]; Item.Draw( X, Y, Context ); X += Item.Width; if ( para_NewLineRendered == Item.Type ) { Y += this.dLineHeight; X = this.X; } } }
Source: https://habr.com/ru/post/231747/
All Articles