396 lines
12 KiB
JavaScript
396 lines
12 KiB
JavaScript
/*
|
||
* (c) Copyright Ascensio System SIA 2010-2024
|
||
*
|
||
* 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(window)
|
||
{
|
||
/**
|
||
* Данный класс рассчитывает текстовые настройки шрифта для выделенного текста
|
||
* @constructor
|
||
*/
|
||
function CFontCalculator()
|
||
{
|
||
this.Bold = null;
|
||
this.Italic = null;
|
||
this.FontSize = null;
|
||
this.FontName = null;
|
||
this.Lang = null;
|
||
|
||
// Для случая, когда в выделение попали только элементы со слотом AscWord.fontslot_Unknown
|
||
// (например, только знак конца параграфа)
|
||
this.BoldUnknown = null;
|
||
this.ItalicUnkown = null;
|
||
this.FontSizeUnknown = null;
|
||
this.FontNameUnknown = null;
|
||
this.LangUnknown = null;
|
||
}
|
||
CFontCalculator.prototype.Calculate = function(oDocContent, oTextPr)
|
||
{
|
||
this.Reset();
|
||
|
||
if (oDocContent.IsNumberingSelection())
|
||
this.HandleNumberingSelection(oDocContent);
|
||
else if (oDocContent.IsTextSelectionUse() && !oDocContent.IsSelectionEmpty())
|
||
this.HandleRegularSelection(oDocContent);
|
||
else
|
||
this.HandleNoSelection(oDocContent);
|
||
|
||
this.CheckResult();
|
||
|
||
oTextPr.Bold = this.Bold;
|
||
oTextPr.Italic = this.Italic;
|
||
oTextPr.FontSize = this.FontSize;
|
||
oTextPr.FontFamily = {Name : this.FontName, Index : -1};
|
||
oTextPr.Lang.Val = this.Lang;
|
||
};
|
||
//------------------------------------------------------------------------------------------------------------------
|
||
CFontCalculator.prototype.Reset = function()
|
||
{
|
||
this.Bold = null;
|
||
this.Italic = null;
|
||
this.FontSize = null;
|
||
this.FontName = null;
|
||
this.Lang = null;
|
||
|
||
this.BoldUnknown = null;
|
||
this.ItalicUnkown = null;
|
||
this.FontSizeUnknown = null;
|
||
this.FontNameUnknown = null;
|
||
this.LangUnknown = null;
|
||
};
|
||
CFontCalculator.prototype.HandleNumberingSelection = function(docContent)
|
||
{
|
||
let paragraph = docContent.GetCurrentParagraph();
|
||
if (!paragraph)
|
||
return;
|
||
|
||
let textPr = paragraph.GetNumberingTextPr();
|
||
|
||
this.Bold = textPr.Bold;
|
||
this.Italic = textPr.Italic;
|
||
this.FontSize = textPr.FontSize;
|
||
this.FontName = textPr.RFonts.Ascii ? textPr.RFonts.Ascii.Name : null;
|
||
this.Lang = textPr.Lang.Val;
|
||
};
|
||
CFontCalculator.prototype.HandleRegularSelection = function(oDocContent)
|
||
{
|
||
let oThis = this;
|
||
oDocContent.CheckSelectedRunContent(function(oRun, nStartPos, nEndPos)
|
||
{
|
||
if (oThis.IsStop())
|
||
return true;
|
||
|
||
if (oRun.IsEmpty())
|
||
return false;
|
||
|
||
let oTextPr;
|
||
if (oRun.IsParaEndRun() && oRun.GetParagraph())
|
||
oTextPr = oRun.GetParagraph().GetParaEndCompiledPr();
|
||
else
|
||
oTextPr = oRun.Get_CompiledPr(false);
|
||
|
||
let oParagraph = oRun.GetParagraph();
|
||
if (oParagraph)
|
||
oTextPr.ReplaceThemeFonts(oParagraph.GetTheme().themeElements.fontScheme);
|
||
|
||
let nFontSlot = oRun.GetFontSlotInRange(nStartPos, nEndPos);
|
||
if (AscWord.fontslot_None !== nFontSlot)
|
||
{
|
||
// TODO: Пока оставим эту проверку здесь. Проблема в том, что настройки в последнем ране не совпадают
|
||
// с настройками конца параграфа (если это исправится, тогда здесь можно просто оставить
|
||
// простое получение компилированных настроек рана)
|
||
nFontSlot = oThis.CheckUnknownFontSlot(nFontSlot, oTextPr);
|
||
|
||
if (nFontSlot & AscWord.fontslot_CS)
|
||
{
|
||
oThis.CheckBold(oTextPr.BoldCS);
|
||
oThis.CheckItalic(oTextPr.ItalicCS);
|
||
oThis.CheckFontSize(oTextPr.FontSizeCS);
|
||
oThis.CheckFontName(oTextPr.RFonts.CS.Name);
|
||
}
|
||
|
||
if (nFontSlot !== AscWord.fontslot_CS && nFontSlot !== AscWord.fontslot_None)
|
||
{
|
||
oThis.CheckBold(oTextPr.Bold);
|
||
oThis.CheckItalic(oTextPr.Italic);
|
||
oThis.CheckFontSize(oTextPr.FontSize);
|
||
}
|
||
|
||
if (nFontSlot & AscWord.fontslot_ASCII)
|
||
oThis.CheckFontName(oTextPr.RFonts.Ascii.Name);
|
||
|
||
if (nFontSlot & AscWord.fontslot_HAnsi)
|
||
oThis.CheckFontName(oTextPr.RFonts.HAnsi.Name);
|
||
|
||
if (nFontSlot & AscWord.fontslot_EastAsia)
|
||
oThis.CheckFontName(oTextPr.RFonts.EastAsia.Name);
|
||
}
|
||
|
||
let direction = oRun.GetDirectionFlagInRange(nStartPos, nEndPos);
|
||
if (AscBidi.DIRECTION_FLAG.None !== direction)
|
||
{
|
||
if (direction & AscBidi.DIRECTION_FLAG.Other)
|
||
oThis.CheckLangUnknown(oParagraph && oParagraph.isRtlDirection() ? oTextPr.Lang.Bidi : oTextPr.Lang.Val);
|
||
|
||
if (direction & AscBidi.DIRECTION_FLAG.LTR)
|
||
oThis.CheckLang(oTextPr.Lang.Val);
|
||
|
||
if (direction & AscBidi.DIRECTION_FLAG.RTL)
|
||
oThis.CheckLang(oTextPr.Lang.Bidi);
|
||
}
|
||
|
||
return false;
|
||
});
|
||
};
|
||
CFontCalculator.prototype.HandleNoSelection = function(oDocContent)
|
||
{
|
||
let oParagraph = oDocContent.GetCurrentParagraph();
|
||
if (!oParagraph)
|
||
return;
|
||
|
||
let oParaContentPos = oParagraph.Get_ParaContentPos(false, false);
|
||
if (!oParaContentPos)
|
||
return;
|
||
|
||
let oRun = oParagraph.GetClassByPos(oParaContentPos);
|
||
if (!oRun || !(oRun instanceof AscWord.ParaRun))
|
||
return;
|
||
|
||
let oTextPr = oRun.Get_CompiledPr(false);
|
||
let nInRunPos = oParaContentPos.Get(oParaContentPos.GetDepth());
|
||
let nFontSlot = this.CheckUnknownFontSlot(oRun.GetFontSlotByPosition(nInRunPos), oTextPr);
|
||
|
||
oTextPr.ReplaceThemeFonts(oParagraph.GetTheme().themeElements.fontScheme);
|
||
|
||
if (AscWord.fontslot_None === nFontSlot)
|
||
nFontSlot = AscWord.fontslot_ASCII;
|
||
|
||
if (nFontSlot & AscWord.fontslot_ASCII)
|
||
this.FontName = oTextPr.RFonts.Ascii.Name;
|
||
else if (nFontSlot & AscWord.fontslot_HAnsi)
|
||
this.FontName = oTextPr.RFonts.HAnsi.Name;
|
||
else if (nFontSlot & AscWord.fontslot_EastAsia)
|
||
this.FontName = oTextPr.RFonts.EastAsia.Name;
|
||
|
||
if (nFontSlot & AscWord.fontslot_CS)
|
||
{
|
||
this.Bold = oTextPr.BoldCS;
|
||
this.Italic = oTextPr.ItalicCS;
|
||
this.FontSize = oTextPr.FontSizeCS;
|
||
this.FontName = oTextPr.RFonts.CS.Name;
|
||
}
|
||
else if (nFontSlot & AscWord.fontslot_ASCII
|
||
|| nFontSlot & AscWord.fontslot_HAnsi
|
||
|| nFontSlot & AscWord.fontslot_EastAsia)
|
||
{
|
||
this.Bold = oTextPr.Bold;
|
||
this.Italic = oTextPr.Italic;
|
||
this.FontSize = oTextPr.FontSize;
|
||
}
|
||
|
||
let nextEl = oParagraph.GetNextRunElement();
|
||
let prevEl = oParagraph.GetPrevRunElement();
|
||
|
||
let dir = AscBidi.DIRECTION_FLAG.None;
|
||
if (!nextEl && !prevEl)
|
||
{
|
||
// Use paragraph flag
|
||
}
|
||
else if (!nextEl || !prevEl)
|
||
{
|
||
let el = nextEl ? nextEl : prevEl;
|
||
dir = el.GetDirectionFlag();
|
||
}
|
||
else
|
||
{
|
||
let prevDir = prevEl.GetDirectionFlag();
|
||
let nextDir = nextEl.GetDirectionFlag();
|
||
if (prevDir === nextDir || prevDir === AscBidi.DIRECTION_FLAG.LTR || prevDir === AscBidi.DIRECTION_FLAG.RTL)
|
||
dir = prevDir;
|
||
else
|
||
dir = nextDir;
|
||
}
|
||
|
||
if (AscBidi.DIRECTION_FLAG.LTR === dir)
|
||
this.Lang = oTextPr.Lang.Val;
|
||
else if (AscBidi.DIRECTION_FLAG.RTL === dir)
|
||
this.Lang = oTextPr.Lang.Bidi;
|
||
else
|
||
this.Lang = oParagraph.isRtlDirection() ? oTextPr.Lang.Bidi : oTextPr.Lang.Val;
|
||
};
|
||
CFontCalculator.prototype.IsStop = function()
|
||
{
|
||
return (undefined === this.Bold
|
||
&& undefined === this.Italic
|
||
&& undefined === this.FontSize
|
||
&& undefined === this.FontName
|
||
&& undefined === this.Lang);
|
||
};
|
||
CFontCalculator.prototype.CheckBold = function(isBold)
|
||
{
|
||
if (undefined === this.Bold)
|
||
return;
|
||
|
||
if (null === this.Bold)
|
||
this.Bold = isBold;
|
||
else if (this.Bold !== isBold)
|
||
this.Bold = undefined;
|
||
};
|
||
CFontCalculator.prototype.CheckItalic = function(isItalic)
|
||
{
|
||
if (undefined === this.Italic)
|
||
return;
|
||
|
||
if (null === this.Italic)
|
||
this.Italic = isItalic;
|
||
else if (this.Italic !== isItalic)
|
||
this.Italic = undefined;
|
||
};
|
||
CFontCalculator.prototype.CheckFontSize = function(nFontSize)
|
||
{
|
||
if (undefined === this.FontSize)
|
||
return;
|
||
|
||
if (null === this.FontSize)
|
||
this.FontSize = nFontSize;
|
||
else if (this.FontSize !== nFontSize)
|
||
this.FontSize = undefined;
|
||
};
|
||
CFontCalculator.prototype.CheckFontName = function(sFontName)
|
||
{
|
||
if (undefined === this.FontName)
|
||
return;
|
||
|
||
if (null === this.FontName)
|
||
this.FontName = sFontName;
|
||
else if (this.FontName !== sFontName)
|
||
this.FontName = undefined;
|
||
};
|
||
CFontCalculator.prototype.CheckLang = function(lang)
|
||
{
|
||
if (undefined === this.Lang)
|
||
return;
|
||
|
||
if (null === this.Lang)
|
||
this.Lang = lang;
|
||
else if (this.Lang !== lang)
|
||
this.Lang = undefined;
|
||
};
|
||
CFontCalculator.prototype.CheckBoldUnknown = function(isBold)
|
||
{
|
||
if (null === this.BoldUnknown)
|
||
this.BoldUnknown = isBold;
|
||
};
|
||
CFontCalculator.prototype.CheckItalicUnknown = function(isItalic)
|
||
{
|
||
if (null === this.ItalicUnkown)
|
||
this.ItalicUnkown = isItalic;
|
||
};
|
||
CFontCalculator.prototype.CheckFontSizeUnknown = function(nFontSize)
|
||
{
|
||
if (null === this.FontSizeUnknown)
|
||
this.FontSizeUnknown = nFontSize;
|
||
};
|
||
CFontCalculator.prototype.CheckFontNameUnknown = function(sFontName)
|
||
{
|
||
if (null === this.FontNameUnknown)
|
||
this.FontNameUnknown = sFontName;
|
||
};
|
||
CFontCalculator.prototype.CheckLangUnknown = function(lang)
|
||
{
|
||
if (undefined === this.LangUnknown)
|
||
return;
|
||
|
||
if (null === this.LangUnknown)
|
||
this.LangUnknown = lang;
|
||
else if (lang !== this.LangUnknown)
|
||
this.LangUnknown = undefined;
|
||
};
|
||
CFontCalculator.prototype.CheckUnknownFontSlot = function(nFontSlot, oTextPr)
|
||
{
|
||
let _nFontSlot = nFontSlot;
|
||
if (AscWord.fontslot_Unknown === nFontSlot)
|
||
{
|
||
if (oTextPr.CS || oTextPr.RTL)
|
||
{
|
||
this.CheckBoldUnknown(oTextPr.BoldCS);
|
||
this.CheckItalicUnknown(oTextPr.ItalicCS);
|
||
this.CheckFontSizeUnknown(oTextPr.FontSizeCS);
|
||
this.CheckFontNameUnknown(oTextPr.RFonts.CS.Name);
|
||
}
|
||
else
|
||
{
|
||
this.CheckBoldUnknown(oTextPr.Bold);
|
||
this.CheckItalicUnknown(oTextPr.Italic);
|
||
this.CheckFontSizeUnknown(oTextPr.FontSize);
|
||
this.CheckFontNameUnknown(oTextPr.RFonts.Ascii.Name);
|
||
}
|
||
|
||
_nFontSlot = AscWord.fontslot_None;
|
||
}
|
||
else if ((AscWord.fontslot_Unknown | AscWord.fontslot_CS) === nFontSlot)
|
||
{
|
||
_nFontSlot = AscWord.fontslot_CS;
|
||
}
|
||
|
||
return _nFontSlot;
|
||
};
|
||
CFontCalculator.prototype.CheckResult = function()
|
||
{
|
||
if (null === this.Bold)
|
||
{
|
||
if (null !== this.BoldUnknown)
|
||
{
|
||
this.Bold = this.BoldUnknown;
|
||
this.Italic = this.ItalicUnkown;
|
||
this.FontSize = this.FontSizeUnknown;
|
||
this.FontName = this.FontNameUnknown;
|
||
}
|
||
else
|
||
{
|
||
this.Bold = undefined;
|
||
this.Italic = undefined;
|
||
this.FontSize = undefined;
|
||
this.FontName = undefined;
|
||
}
|
||
}
|
||
|
||
if (null === this.Lang)
|
||
this.Lang = this.LangUnknown ? this.LangUnknown : undefined;
|
||
};
|
||
//--------------------------------------------------------export----------------------------------------------------
|
||
window['AscWord'] = window['AscWord'] || {};
|
||
window['AscWord'].FontCalculator = new CFontCalculator();
|
||
|
||
})(window);
|