Files
DocumentServer-v-9.2.0/sdkjs/word/Editor/document/document-page-section.js
T
Yajbir Singh f1b860b25c
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

282 lines
9.8 KiB
JavaScript

/*
* (c) Copyright Ascensio System SIA 2010-2025
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
"use strict";
(function()
{
/**
* @constructor
*/
function DocumentPageSection()
{
this.Pos = 0;
this.EndPos = -1;
this.ResetSectionStart = false; // Если секция разбилась внутри блочного контент контрола
this.Y = 0;
this.YLimit = 0;
this.YLimit2 = 0;
this.Index = -1;
this.SectPr = null;
this.Columns = [];
this.ColumnsSep = false;
this.IterationsCount = 0;
this.CurrentY = 0;
this.RecalculateBottomLine = true;
this.CanDecrease = true;
this.WasIncrease = false; // Было ли хоть раз увеличение
this.IterationStep = 10;
this.IterationDirection = 0;
}
/**
* Инициализируем параметры данной секции
* @param {number} nPageAbs
* @param {AscWord.SectPr} oSectPr
* @param {Number} nSectionIndex
*/
DocumentPageSection.prototype.Init = function(nPageAbs, oSectPr, nSectionIndex)
{
var oFrame = oSectPr.GetContentFrame(nPageAbs);
var nX = oFrame.Left;
var nXLimit = oFrame.Right;
for (var nCurColumn = 0, nColumnsCount = oSectPr.GetColumnCount(); nCurColumn < nColumnsCount; ++nCurColumn)
{
this.Columns[nCurColumn] = new AscWord.DocumentPageColumn();
this.Columns[nCurColumn].X = nX;
this.Columns[nCurColumn].XLimit = nColumnsCount - 1 === nCurColumn ? nXLimit : nX + oSectPr.GetColumnWidth(nCurColumn);
nX += oSectPr.GetColumnWidth(nCurColumn) + oSectPr.GetColumnSpace(nCurColumn);
}
this.ColumnsSep = oSectPr.GetColumnSep();
this.Y = oFrame.Top;
this.YLimit = oFrame.Bottom;
this.YLimit2 = oFrame.Bottom;
this.Index = nSectionIndex;
this.SectPr = oSectPr;
};
DocumentPageSection.prototype.GetIndex = function()
{
return this.Index;
};
DocumentPageSection.prototype.GetSectPr = function()
{
return this.SectPr;
};
DocumentPageSection.prototype.Copy = function()
{
var NewSection = new DocumentPageSection();
NewSection.Pos = this.Pos;
NewSection.EndPos = this.EndPos;
NewSection.Y = this.Y;
NewSection.YLimit = this.YLimit;
for (var ColumnIndex = 0, Count = this.Columns.length; ColumnIndex < Count; ++ColumnIndex)
{
NewSection.Columns[ColumnIndex] = this.Columns[ColumnIndex].Copy();
}
return NewSection;
};
DocumentPageSection.prototype.Shift = function(Dx, Dy)
{
this.Y += Dy;
this.YLimit += Dy;
for (var ColumnIndex = 0, Count = this.Columns.length; ColumnIndex < Count; ++ColumnIndex)
{
this.Columns[ColumnIndex].Shift(Dx, Dy);
}
};
DocumentPageSection.prototype.CorrectY = function(y)
{
return (y < this.Y ? this.Y : (y > this.YLimit ? this.YLimit : y));
};
/**
* Происходи ли процесс расчета нижней границы разрыва секции на текущей странице
* @returns {boolean}
*/
DocumentPageSection.prototype.IsCalculatingSectionBottomLine = function()
{
return (this.IterationsCount > 0 && true === this.RecalculateBottomLine);
};
/**
* Можно ли расчитывать нижнюю границу разрыва секции на текущей странице
* @returns {boolean}
*/
DocumentPageSection.prototype.CanRecalculateBottomLine = function()
{
return this.RecalculateBottomLine;
};
/**
* Запрещаем возможность расчета нижней границы разрыва секции на текущей страницы
*/
DocumentPageSection.prototype.ForbidRecalculateBottomLine = function()
{
this.RecalculateBottomLine = false;
};
DocumentPageSection.prototype.GetY = function()
{
return this.Y;
};
DocumentPageSection.prototype.GetYLimit = function()
{
if (0 === this.IterationsCount)
return this.YLimit;
else
return this.CurrentY;
};
/**
* Производим шаг рассчета нижней границы рарзрыва секции
* @param {boolean} isIncrease
* @returns {number}
*/
DocumentPageSection.prototype.IterateBottomLineCalculation = function(isIncrease)
{
// Алгоритм следующий:
// На первом шаге мы прогнозируем положение границы по уже имеющемуся объему текста и
// ширине колонок.
// Далее мы сдвигаем границу на значение IterationStep, вверх или вниз в зависимости
// от результата расчета страницы. При перемене направления сдвига мы всегда уменьшаем шаг
// в 2 раза. Также мы можем уменьшать шаг в 2 раза, если сдвигаем границу вверх, и хотябы
// раз до этого двигали ее вниз. Останавливаем итерацию при попытке подвинуть границу наверх,
// когда шаг итерации становится менее 2мм.
if (0 === this.IterationsCount)
{
// Пытаемся заранее спрогнозировать позицию, где должно быть разделение. Учитывая, что колонки могут быть разной
// ширины, мы расчитываем суммарную занимаемую текстом область. Делим ее по колонкам, с учетом их суммарной
// ширины.
var nSumArea = 0, nSumWidth = 0;
for (var nColumnIndex = 0, nColumnsCount = this.Columns.length; nColumnIndex < nColumnsCount; ++nColumnIndex)
{
var oColumn = this.Columns[nColumnIndex];
if (true !== oColumn.Empty)
nSumArea += (oColumn.Bounds.Bottom - this.Y) * (oColumn.XLimit - oColumn.X);
nSumWidth += oColumn.XLimit - oColumn.X;
}
if (nSumWidth > 0.001)
this.CurrentY = this.Y + nSumArea / nSumWidth;
else
this.CurrentY = this.Y;
}
else
{
if (false === isIncrease)
{
if (this.IterationDirection > 0 || this.WasIncrease)
this.IterationStep /= 2;
this.CurrentY -= this.IterationStep;
this.IterationDirection = -1;
if (this.CurrentY < this.Y)
{
// Такое может быть, когда у нас всего одна строка в начале страницы, которую мы размещаем всегда
this.CurrentY = this.Y;
this.CanDecrease = false;
}
}
else
{
if (this.IterationDirection < 0)
this.IterationStep /= 2;
this.CurrentY += this.IterationStep;
this.IterationDirection = 1;
this.WasIncrease = true;
}
}
if (this.IterationStep < 2)
this.CanDecrease = false;
this.CurrentY = Math.min(this.CurrentY, this.YLimit2);
// // Recalculation LOG
// console.log(`Calculate continuous section count=${this.IterationsCount} step=${this.IterationStep} Y=${this.CurrentY}`);
this.IterationsCount++;
return this.CurrentY;
};
DocumentPageSection.prototype.Reset_Columns = function()
{
for (var ColumnIndex = 0, Count = this.Columns.length; ColumnIndex < Count; ++ColumnIndex)
{
this.Columns[ColumnIndex].Reset();
}
};
/**
* Можем ли мы провести еще одну итерацию с уменьшением нижней границы
* @returns {boolean}
*/
DocumentPageSection.prototype.CanDecreaseBottomLine = function()
{
return this.CanDecrease;
};
DocumentPageSection.prototype.CanIncreaseBottomLine = function()
{
// Данная функция не должна возвращать false, если возвращает, значит неправильно работает алгоритм по вычислению
// нижней границы continuous секции
// if (!(this.YLimit2 - this.CurrentY > 0.001))
// console.log("Bad continuous section calculate");
return (this.YLimit2 - this.CurrentY > 0.001);
};
DocumentPageSection.prototype.GetBottomLimit = function()
{
let bottomLimit = this.Y;
for (let column = 0, columnCount = this.Columns.length; column < columnCount; ++column)
{
bottomLimit = Math.max(bottomLimit, this.Columns[column].Bounds.Bottom);
}
return bottomLimit;
};
//--------------------------------------------------------export----------------------------------------------------
AscWord.DocumentPageSection = DocumentPageSection;
})();