/* * (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, undefined) { function CGlyphRect() { this.fX = 0; this.fY = 0; this.fWidth = 0; this.fHeight = 0; } function CGlyphBounds() { this.fLeft = 0; this.fTop = 0; this.fRight = 0; this.fBottom = 0; } CGlyphBounds.prototype.checkPoint = function(x, y) { if (x < this.fLeft) this.fLeft = x; if (x > this.fRight) this.fRight = x; if (y < this.fTop) this.fTop = y; if (y > this.fBottom) this.fBottom = y; }; function CGlyph() { this.lUnicode = 0; // Юникод this.fX = 0; // Позиция глифа this.fY = 0; // на BaseLine this.fLeft = 0; // this.fTop = 0; // BBox this.fRight = 0; // this.fBottom = 0; // this.oMetrics = null; this.eState = AscFonts.EGlyphState.glyphstateNormal; this.bBitmap = false; this.oBitmap = null; this.Clear = function() { this.bBitmap = false; this.eState = AscFonts.EGlyphState.glyphstateNormal; }; } function CGlyphString() { this.m_fX = 0; this.m_fY = 0; this.m_fEndX = 0; this.m_fEndY = 0; this.m_nGlyphIndex = -1; this.m_nGlyphsCount = 0; this.m_pGlyphsBuffer = new Array(100); this.m_arrCTM = []; this.m_dIDet = 1; this.m_fTransX = 0; this.m_fTransY = 0; this.GetFirstGlyph = function() { if (!this.m_pGlyphsBuffer[0]) this.m_pGlyphsBuffer[0] = new CGlyph(); return this.m_pGlyphsBuffer[0]; }; this.SetString = function(wsString, fX, fY) { this.m_fX = fX + this.m_fTransX; this.m_fY = fY + this.m_fTransY; this.m_nGlyphsCount = wsString.length; this.m_nGlyphIndex = 0; for (var nIndex = 0; nIndex < this.m_nGlyphsCount; ++nIndex) { if (undefined == this.m_pGlyphsBuffer[nIndex]) this.m_pGlyphsBuffer[nIndex] = new CGlyph(); else this.m_pGlyphsBuffer[nIndex].Clear(); this.m_pGlyphsBuffer[nIndex].lUnicode = wsString.charCodeAt(nIndex); } }; this.SetStringGID = function(gid, fX, fY) { this.m_fX = fX + this.m_fTransX; this.m_fY = fY + this.m_fTransY; this.m_nGlyphsCount = 1; this.m_nGlyphIndex = 0; if (undefined == this.m_pGlyphsBuffer[0]) this.m_pGlyphsBuffer[0] = new CGlyph(); else this.m_pGlyphsBuffer[0].Clear(); this.m_pGlyphsBuffer[0].lUnicode = gid; }; this.GetLength = function() { return this.m_nGlyphsCount; }; this.GetAt = function(nIndex) { if (this.m_nGlyphsCount <= 0) return null; var nCurIndex = (nIndex < 0) ? 0 : nIndex; if (nCurIndex >= this.m_nGlyphsCount) nCurIndex = this.m_nGlyphsCount - 1; return this.m_pGlyphsBuffer[nCurIndex]; }; this.SetStartPoint = function(nIndex, fX, fY) { if (this.m_nGlyphsCount <= 0) return; var nCurIndex = (nIndex < 0) ? 0 : nIndex; if (nCurIndex >= this.m_nGlyphsCount) nCurIndex = this.m_nGlyphsCount - 1; this.m_pGlyphsBuffer[nCurIndex].fX = fX; this.m_pGlyphsBuffer[nCurIndex].fY = fY; }; this.SetState = function(nIndex, eState) { if (this.m_nGlyphsCount <= 0) return; var nCurIndex = (nIndex < 0) ? 0 : nIndex; if (nCurIndex >= this.m_nGlyphsCount) nCurIndex = this.m_nGlyphsCount - 1; this.m_pGlyphsBuffer[nCurIndex].eState = eState; }; this.SetBBox = function (nIndex, fLeft, fTop, fRight, fBottom) { if (this.m_nGlyphsCount <= 0) return; var nCurIndex = (nIndex < 0) ? 0 : nIndex; if (nCurIndex >= this.m_nGlyphsCount) nCurIndex = this.m_nGlyphsCount - 1; var _g = this.m_pGlyphsBuffer[nCurIndex]; _g.fLeft = fLeft; _g.fTop = fTop; _g.fRight = fRight; _g.fBottom = fBottom; }; this.SetMetrics = function (nIndex, fWidth, fHeight, fHoriAdvance, fHoriBearingX, fHoriBearingY, fVertAdvance, fVertBearingX, fVertBearingY) { if (this.m_nGlyphsCount <= 0) return; var nCurIndex = (nIndex < 0) ? 0 : nIndex; if (nCurIndex >= this.m_nGlyphsCount) nCurIndex = this.m_nGlyphsCount - 1; var _g = this.m_pGlyphsBuffer[nCurIndex]; _g.oMetrics.fHeight = fHeight; _g.oMetrics.fHoriAdvance = fHoriAdvance; _g.oMetrics.fHoriBearingX = fHoriBearingX; _g.oMetrics.fHoriBearingY = fHoriBearingY; _g.oMetrics.fVertAdvance = fVertAdvance; _g.oMetrics.fVertBearingX = fVertBearingX; _g.oMetrics.fVertBearingY = fVertBearingY; _g.oMetrics.fWidth = fWidth; }; this.ResetCTM = function() { var m = this.m_arrCTM; m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; this.m_dIDet = 1; }; this.GetBBox = function(nIndex, nType) { var oPoint = new CGlyphBounds(); if (typeof nIndex == "undefined") nIndex = -1; if (typeof nType == "undefined") nType = 0; var nCurIndex = 0; if (nIndex < 0) { if (this.m_nGlyphsCount <= 0 || this.m_nGlyphIndex < 1 || this.m_nGlyphIndex > this.m_nGlyphsCount) return oPoint; nCurIndex = this.m_nGlyphIndex - 1; } else { if (this.m_nGlyphsCount <= 0) return oPoint; nCurIndex = (nIndex < 0) ? 0 : nIndex; if (nCurIndex >= this.m_nGlyphsCount) nCurIndex = this.m_nGlyphsCount - 1; } var _g = this.m_pGlyphsBuffer[nCurIndex]; var m = this.m_arrCTM; var fBottom = -_g.fBottom; var fRight = _g.fRight; var fLeft = _g.fLeft; var fTop = -_g.fTop; if (0 == nType && !(1 == m[0] && 0 == m[1] && 0 == m[2] && 1 == m[3] && 0 == m[4] && 0 == m[5])) { // Применяем глобальную матрицу преобразования и пересчитываем BBox var arrfX =[fLeft, fLeft, fRight, fRight]; var arrfY = [fTop, fBottom, fBottom, fTop]; var fMinX = (arrfX[0] * m[0] + arrfY[0] * m[2]); var fMinY = (arrfX[0] * m[1] + arrfY[0] * m[3]); var fMaxX = fMinX; var fMaxY = fMinY; for (var nIndex = 1; nIndex < 4; ++nIndex) { var fX = (arrfX[nIndex] * m[0] + arrfY[nIndex] * m[2]); var fY = (arrfX[nIndex] * m[1] + arrfY[nIndex] * m[3]); fMaxX = Math.max(fMaxX, fX); fMinX = Math.min(fMinX, fX); fMaxY = Math.max(fMaxY, fY); fMinY = Math.min(fMinY, fY); } fLeft = fMinX; fRight = fMaxX; fTop = fMinY; fBottom = fMaxY; } oPoint.fLeft = fLeft + _g.fX + this.m_fX; oPoint.fRight = fRight + _g.fX + this.m_fX; oPoint.fTop = fTop + _g.fY + this.m_fY; oPoint.fBottom = fBottom + _g.fY + this.m_fY; return oPoint; }; this.GetBBox2 = function() { var oPoint = new CGlyphBounds(); if (this.m_nGlyphsCount <= 0) return oPoint; var fBottom = 0; var fRight = 0; var fLeft = 0; var fTop = 0; for (var nIndex = 0; nIndex < this.m_nGlyphsCount; ++nIndex) { fBottom = Math.max(fBottom, -this.m_pGlyphsBuffer[nIndex].fBottom); fTop = Math.min(fTop, -this.m_pGlyphsBuffer[nIndex].fTop); } var m = this.m_arrCTM; if (!(1 == m[0] && 0 == m[1] && 0 == m[2] && 1 == m[3] && 0 == m[4] && 0 == m[5])) { // Применяем глобальную матрицу преобразования и пересчитываем BBox var arrfX = [fLeft, fLeft, fRight, fRight]; var arrfY = [fTop, fBottom, fBottom, fTop]; var fMinX = (arrfX[0] * m[0] + arrfY[0] * m[2]); var fMinY = (arrfX[0] * m[1] + arrfY[0] * m[3]); var fMaxX = fMinX; var fMaxY = fMinY; for (var nIndex = 1; nIndex < 4; ++nIndex) { var fX = (arrfX[nIndex] * m[0] + arrfY[nIndex] * m[2]); var fY = (arrfX[nIndex] * m[1] + arrfY[nIndex] * m[3]); fMaxX = Math.max (fMaxX, fX); fMinX = Math.min (fMinX, fX); fMaxY = Math.max (fMaxY, fY); fMinY = Math.min (fMinY, fY); } fLeft = fMinX; fRight = fMaxX; fTop = fMinY; fBottom = fMaxY; } fLeft += this.m_fX; fRight += this.m_fX; fTop += this.m_fY; fBottom += this.m_fY; oPoint.fLeft = Math.min (fLeft, Math.min (this.m_fX, this.m_fEndX)); oPoint.fRight = Math.max (fRight, Math.max (this.m_fX, this.m_fEndX)); oPoint.fTop = Math.min (fTop, Math.min (this.m_fY, this.m_fEndY)); oPoint.fBottom = Math.max (fBottom, Math.max (this.m_fY, this.m_fEndY)); return oPoint; }; this.GetNext = function() { if (this.m_nGlyphIndex >= this.m_nGlyphsCount || this.m_nGlyphIndex < 0) return undefined; return this.m_pGlyphsBuffer[this.m_nGlyphIndex++]; }; this.SetTrans = function(fX, fY) { var m = this.m_arrCTM; this.m_fTransX = this.m_dIDet * (fX * m[3] - m[2] * fY); this.m_fTransY = this.m_dIDet * (fY * m[0] - m[1] * fX); }; this.SetCTM = function(fA, fB, fC, fD, fE , fF) { var m = this.m_arrCTM; m[0] = fA; m[1] = fB; m[2] = fC; m[3] = fD; m[4] = fE; m[5] = fF; var dDet = fA * fD - fB * fC; if (dDet < 0.001 && dDet >= 0) dDet = 0.001; else if (dDet > - 0.001 && dDet < 0) dDet = -0.001; this.m_dIDet = 1 / dDet; }; } window['AscFonts'] = window['AscFonts'] || {}; window['AscFonts'].CGlyphRect = CGlyphRect; window['AscFonts'].CGlyphBounds = CGlyphBounds; window['AscFonts'].CGlyphString = CGlyphString; })(window, undefined);