mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
add DjVu GetGlyphs
This commit is contained in:
@ -484,6 +484,382 @@ BYTE* CDjVuFileImplementation::GetPageLinks (int nPageIndex)
|
||||
catch (...) {}
|
||||
return NULL;
|
||||
}
|
||||
void CDjVuFileImplementation::GetGlyphs(IRenderer* m_pRenderer, const std::wstring& bsUnicodeText, unsigned int* pGids, double x, double y)
|
||||
{
|
||||
// m_pInternal->GetUnicodes(bsUnicodeText);
|
||||
int nLen = (int)bsUnicodeText.length();
|
||||
int* pTempUnicodes = new int[nLen];
|
||||
int nTempUnicodesLen = 0;
|
||||
const wchar_t* pWchars = bsUnicodeText.c_str();
|
||||
|
||||
if (sizeof(wchar_t) == 2)
|
||||
{
|
||||
for (int i = 0; i < nLen; i++)
|
||||
{
|
||||
int code = (int)pWchars[i];
|
||||
if (code >= 0xD800 && code <= 0xDFFF && (i + 1) < nLen)
|
||||
code = 0x10000 + (((code & 0x3FF) << 10) | (0x03FF & pWchars[++i]));
|
||||
pTempUnicodes[nTempUnicodesLen++] = code;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (int i = 0; i < nLen; i++)
|
||||
pTempUnicodes[nTempUnicodesLen++] = (int)pWchars[i];
|
||||
|
||||
// m_pInternal->m_oWriter.WriteText(pTempUnicodes, (const int*)pGids, nTempUnicodesLen, x, y, w, h, m_pInternal->m_bIsChangedFontParamBetweenDrawText);
|
||||
bool bIsDumpFont = false;
|
||||
double dFontSize;
|
||||
m_pRenderer->get_FontSize(&dFontSize);
|
||||
if (m_lCurrentFont || (dFontSize != m_dCurrentFontSize))
|
||||
{
|
||||
m_lCurrentFont = 0;
|
||||
m_dCurrentFontSize = dFontSize;
|
||||
bIsDumpFont = true;
|
||||
}
|
||||
|
||||
// m_oSmartText.CommandText(pTempUnicodes, (const int*)pGids, nTempUnicodesLen, x, y, w, h, bIsDumpFont, this);
|
||||
// 1) сначала определяем точку отсчета и направление baseline
|
||||
double _x1 = x;
|
||||
double _y1 = y;
|
||||
double _x2 = x + 1;
|
||||
double _y2 = y;
|
||||
// m_pTransform->TransformPoint(_x1, _y1);
|
||||
// m_pTransform->TransformPoint(_x2, _y2);
|
||||
|
||||
LONG nCountChars = m_oLine.GetCountChars();
|
||||
bool bIsNewLine = 0 == nCountChars;
|
||||
if (bIsNewLine && (nCountChars != 0))
|
||||
{
|
||||
// не совпала baseline. поэтому просто скидываем линию в поток
|
||||
DumpLine();
|
||||
}
|
||||
|
||||
// теперь нужно определить сдвиг по baseline относительно destination точки
|
||||
nCountChars = m_oLine.GetCountChars();
|
||||
double dOffsetX = 0;
|
||||
if (nCountChars == 0)
|
||||
{
|
||||
m_oLine.m_bIsConstX = false;
|
||||
|
||||
m_oLine.m_dX = _x1;
|
||||
m_oLine.m_dY = _y1;
|
||||
|
||||
m_oLine.m_ex = _x2 - _x1;
|
||||
m_oLine.m_ey = _y2 - _y1;
|
||||
|
||||
m_oLine.m_dEndX = _x1;
|
||||
m_oLine.m_dEndY = _y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
double _sx = _x1 - m_oLine.m_dEndX;
|
||||
double _sy = _y1 - m_oLine.m_dEndY;
|
||||
double len = sqrt(_sx * _sx + _sy * _sy);
|
||||
|
||||
if (_sx * m_oLine.m_ex >= 0 && _sy * m_oLine.m_ey >= 0)
|
||||
{
|
||||
// продолжаем линию
|
||||
dOffsetX = len;
|
||||
|
||||
// теперь посмотрим, может быть нужно вставить пробел??
|
||||
NSWasm::CHChar* pLastChar = m_oLine.GetTail();
|
||||
if (dOffsetX > (pLastChar->width + 0.5))
|
||||
{
|
||||
// вставляем пробел. Пробел у нас будет не совсем пробел. А специфический
|
||||
NSWasm::CHChar* pSpaceChar = m_oLine.AddTail();
|
||||
pSpaceChar->x = pLastChar->width;
|
||||
pSpaceChar->width = dOffsetX - pLastChar->width;
|
||||
pSpaceChar->unicode = 0xFFFF;
|
||||
pSpaceChar->gid = 0xFFFF;
|
||||
dOffsetX -= pLastChar->width;
|
||||
|
||||
m_oMeta.WriteBYTE(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// буква сдвинута влево относительно предыдущей буквы
|
||||
// на такую ситуацию реагируем просто - просто начинаем новую линию,
|
||||
// предварительно сбросив старую
|
||||
DumpLine();
|
||||
|
||||
m_oLine.m_bIsConstX = false;
|
||||
|
||||
m_oLine.m_dX = _x1;
|
||||
m_oLine.m_dY = _y1;
|
||||
|
||||
m_oLine.m_ex = _x2 - _x1;
|
||||
m_oLine.m_ey = _y2 - _y1;
|
||||
}
|
||||
|
||||
m_oLine.m_dEndX = _x1;
|
||||
m_oLine.m_dEndY = _y1;
|
||||
}
|
||||
|
||||
// смотрим, совпадает ли главная часть матрицы.
|
||||
bool bIsTransform = !(fabs(m_pLastTransform.sx() - 1.0) < 0.001 &&
|
||||
fabs(m_pLastTransform.sy() - 1.0) < 0.001 &&
|
||||
fabs(m_pLastTransform.shx()) < 0.001 &&
|
||||
fabs(m_pLastTransform.shy()) < 0.001);
|
||||
if (bIsTransform)
|
||||
bIsDumpFont = true;
|
||||
|
||||
LONG nColor1 = 0, nAlpha1 = 255;
|
||||
bool bIsColor = ((nColor1 != m_nLastBrushColor1) || (nAlpha1 != m_nLastBrushAlpha1));
|
||||
|
||||
BYTE nLenMetaCommands = 0;
|
||||
if (bIsColor)
|
||||
nLenMetaCommands += 5;
|
||||
if (bIsTransform)
|
||||
nLenMetaCommands += 17;
|
||||
if (bIsDumpFont)
|
||||
nLenMetaCommands += 13;
|
||||
|
||||
m_oMeta.WriteBYTE(nLenMetaCommands);
|
||||
|
||||
double _dumpSize = dFontSize;
|
||||
double _dumpMtx[4];
|
||||
_dumpMtx[0] = 1.0;
|
||||
_dumpMtx[1] = 0.0;
|
||||
_dumpMtx[2] = 0.0;
|
||||
_dumpMtx[3] = 1.0;
|
||||
|
||||
double dTextScale = std::min(sqrt(_dumpMtx[2] * _dumpMtx[2] + _dumpMtx[3] * _dumpMtx[3]),
|
||||
sqrt(_dumpMtx[0] * _dumpMtx[0] + _dumpMtx[1] * _dumpMtx[1]));
|
||||
|
||||
if ((_dumpSize < 0.1 && dTextScale > 10) || (_dumpSize > 10 && dTextScale < 0.1))
|
||||
{
|
||||
_dumpSize *= dTextScale;
|
||||
|
||||
_dumpMtx[0] /= dTextScale;
|
||||
_dumpMtx[1] /= dTextScale;
|
||||
_dumpMtx[2] /= dTextScale;
|
||||
_dumpMtx[3] /= dTextScale;
|
||||
}
|
||||
|
||||
if (bIsDumpFont)
|
||||
{
|
||||
m_oMeta.WriteBYTE(41); // CMetafile::ctFontName
|
||||
m_oMeta.AddInt(0); // nCurrentFont
|
||||
m_oMeta.AddInt(0); // get_FontStyle
|
||||
m_oMeta.WriteDouble(_dumpSize);
|
||||
}
|
||||
if (bIsTransform)
|
||||
{
|
||||
m_pLastTransform.SetElements(1.0, 0.0, 0.0, 1.0);
|
||||
|
||||
m_oLine.m_bIsSetUpTransform = true;
|
||||
m_oLine.m_sx = 1.0;
|
||||
m_oLine.m_shx = 0.0;
|
||||
m_oLine.m_shy = 0.0;
|
||||
m_oLine.m_sy = 1.0;
|
||||
|
||||
m_oMeta.WriteBYTE(161); // CMetafile::ctCommandTextTransform
|
||||
m_oMeta.WriteDouble(_dumpMtx[0]);
|
||||
m_oMeta.WriteDouble(_dumpMtx[1]);
|
||||
m_oMeta.WriteDouble(_dumpMtx[2]);
|
||||
m_oMeta.WriteDouble(_dumpMtx[3]);
|
||||
}
|
||||
if (bIsColor)
|
||||
{
|
||||
m_nLastBrushColor1 = nColor1;
|
||||
m_nLastBrushAlpha1 = nAlpha1;
|
||||
|
||||
m_oMeta.WriteBYTE(22); // CMetafile::ctBrushColor1
|
||||
|
||||
LONG lBGR = nColor1;
|
||||
m_oMeta.WriteBYTE((BYTE)(lBGR & 0xFF));
|
||||
m_oMeta.WriteBYTE((BYTE)((lBGR >> 8) & 0xFF));
|
||||
m_oMeta.WriteBYTE((BYTE)((lBGR >> 16) & 0xFF));
|
||||
m_oMeta.WriteBYTE((BYTE)nAlpha1);
|
||||
}
|
||||
|
||||
NSFonts::IFontManager *m_pFontManager = ((NSGraphics::IGraphicsRenderer*)m_pRenderer)->GetFontManager();
|
||||
// все, baseline установлен. теперь просто продолжаем линию
|
||||
if (bIsDumpFont)
|
||||
{
|
||||
m_pFontManager->LoadFontFromFile(L"DjvuEmptyFont", 0, dFontSize, 72.0, 72.0);
|
||||
m_pFontManager->AfterLoad();
|
||||
}
|
||||
|
||||
double dKoef = dFontSize * 25.4 / (72 * abs(m_pFontManager->GetUnitsPerEm()));
|
||||
double dAscender = abs(m_pFontManager->GetAscender()) * dKoef;
|
||||
double dDescender = abs(m_pFontManager->GetDescender()) * dKoef;
|
||||
|
||||
if (m_oLine.m_dAscent < dAscender)
|
||||
m_oLine.m_dAscent = dAscender;
|
||||
if (m_oLine.m_dDescent < dDescender)
|
||||
m_oLine.m_dDescent = dDescender;
|
||||
|
||||
double dPlusOffset = 0;
|
||||
int* input = NULL;
|
||||
if (pGids)
|
||||
{
|
||||
input = (int*)pGids;
|
||||
m_pFontManager->SetStringGID(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
input = pTempUnicodes;
|
||||
m_pFontManager->SetStringGID(FALSE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < nTempUnicodesLen; i++)
|
||||
{
|
||||
// double dW = m_oFontManager.MeasureString((const unsigned int*)(input + lIndex), 1, 0, 0, dBoxX, dBoxY, dBoxW, dBoxH);
|
||||
m_pFontManager->LoadString1((unsigned int*)(input + i), 1, 0, 0);
|
||||
TBBox _box = m_pFontManager->MeasureString2();
|
||||
double dBoxW = abs(_box.fMaxX - _box.fMinX) * 25.4 / 72.0;
|
||||
|
||||
NSWasm::CHChar* pChar = m_oLine.AddTail();
|
||||
pChar->unicode = pTempUnicodes[i];
|
||||
pChar->gid = pGids ? pGids[i] : 0xFFFF;
|
||||
|
||||
pChar->x = dOffsetX;
|
||||
if (i != 0)
|
||||
dPlusOffset += dOffsetX;
|
||||
dOffsetX = dBoxW;
|
||||
|
||||
pChar->width = dBoxW;
|
||||
|
||||
if (i != 0)
|
||||
m_oMeta.WriteBYTE(0);
|
||||
|
||||
if (i == (nTempUnicodesLen - 1))
|
||||
{
|
||||
m_oLine.m_dEndX += dPlusOffset * m_oLine.m_ex;
|
||||
m_oLine.m_dEndY += dPlusOffset * m_oLine.m_ey;
|
||||
}
|
||||
}
|
||||
|
||||
RELEASEARRAYOBJECTS(pTempUnicodes);
|
||||
}
|
||||
void CDjVuFileImplementation::DumpLine()
|
||||
{
|
||||
if (m_oLine.m_bIsSetUpTransform)
|
||||
{
|
||||
// выставится трансформ!!!
|
||||
// cравнивать нужно с ним!!!
|
||||
m_pLastTransform.SetElements(m_oLine.m_sx, m_oLine.m_shy, m_oLine.m_shx, m_oLine.m_sy);
|
||||
}
|
||||
|
||||
// скидываем линию в поток pMeta
|
||||
BYTE mask = 0;
|
||||
if (fabs(m_oLine.m_ex - 1.0) < 0.001 && fabs(m_oLine.m_ey) < 0.001)
|
||||
mask |= 0x01;
|
||||
|
||||
LONG lCountSpaces = 0;
|
||||
LONG lCountSymbols = 0;
|
||||
LONG lCountWords = 0;
|
||||
bool bIsLastSymbol = false;
|
||||
bool bIsGidExist = false;
|
||||
|
||||
LONG nCount = m_oLine.GetCountChars();
|
||||
for (LONG i = 0; i < nCount; i++)
|
||||
{
|
||||
NSWasm::CHChar* pChar = &m_oLine.m_pChars[i];
|
||||
if (pChar->gid != 0xFFFF)
|
||||
{
|
||||
mask |= 0x02;
|
||||
bIsGidExist = true;
|
||||
}
|
||||
|
||||
if (0xFFFF == pChar->unicode || L' ' == pChar->unicode || L'\t' == pChar->unicode)
|
||||
{
|
||||
lCountSpaces++;
|
||||
if (bIsLastSymbol)
|
||||
{
|
||||
bIsLastSymbol = false;
|
||||
lCountWords++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bIsLastSymbol = true;
|
||||
lCountSymbols++;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIsLastSymbol)
|
||||
lCountWords++;
|
||||
|
||||
if (0 == nCount)
|
||||
{
|
||||
m_oLine.Clear();
|
||||
m_oMeta.ClearNoAttack();
|
||||
return;
|
||||
}
|
||||
|
||||
if (nCount > 1)
|
||||
mask |= 0x04;
|
||||
|
||||
m_pPageMeta.WriteBYTE(160); // CMetafile::ctCommandTextLine
|
||||
m_pPageMeta.WriteBYTE(mask);
|
||||
|
||||
m_pPageMeta.WriteDouble(m_oLine.m_dX);
|
||||
m_pPageMeta.WriteDouble(m_oLine.m_dY);
|
||||
|
||||
if ((mask & 0x01) == 0)
|
||||
{
|
||||
m_pPageMeta.WriteDouble(m_oLine.m_ex);
|
||||
m_pPageMeta.WriteDouble(m_oLine.m_ey);
|
||||
}
|
||||
|
||||
m_pPageMeta.WriteDouble(m_oLine.m_dAscent);
|
||||
m_pPageMeta.WriteDouble(m_oLine.m_dDescent);
|
||||
|
||||
LONG _position = 0;
|
||||
if (nCount > 1)
|
||||
{
|
||||
_position = m_pPageMeta.GetSize();
|
||||
m_pPageMeta.AddInt(0);
|
||||
}
|
||||
|
||||
BYTE* pBufferMeta = m_oMeta.GetBuffer();
|
||||
double dWidthLine = 0;
|
||||
|
||||
double dCurrentGlyphLineOffset = 0;
|
||||
for (LONG lIndexChar = 0; lIndexChar < nCount; lIndexChar++)
|
||||
{
|
||||
NSWasm::CHChar* pChar = &m_oLine.m_pChars[lIndexChar];
|
||||
|
||||
// все настроки буквы (m_oMeta)
|
||||
BYTE lLen = *pBufferMeta;
|
||||
pBufferMeta++;
|
||||
if (lLen > 0)
|
||||
m_pPageMeta.Write(pBufferMeta, lLen);
|
||||
pBufferMeta += lLen;
|
||||
// смещение относительно предыдущей буквы (у всех, кроме первой)
|
||||
// юникодное значение
|
||||
// гид (если bIsGidExist == true)
|
||||
// ширина буквы
|
||||
|
||||
m_pPageMeta.WriteBYTE(80); // CMetafile::ctDrawText
|
||||
if (lIndexChar)
|
||||
m_pPageMeta.WriteDouble2(pChar->x);
|
||||
|
||||
m_pPageMeta.WriteWCHAR(pChar->unicode);
|
||||
if (bIsGidExist)
|
||||
m_pPageMeta.WriteUSHORT(pChar->gid);
|
||||
m_pPageMeta.WriteDouble2(pChar->width);
|
||||
|
||||
if (lIndexChar)
|
||||
dCurrentGlyphLineOffset += pChar->x;
|
||||
|
||||
if (lIndexChar == (nCount - 1))
|
||||
dWidthLine = dCurrentGlyphLineOffset + pChar->width;
|
||||
}
|
||||
|
||||
if (nCount > 1)
|
||||
{
|
||||
int* pWidthBuf = (int*)(m_pPageMeta.GetBuffer() + _position);
|
||||
*pWidthBuf = (int)(dWidthLine * 10000);
|
||||
}
|
||||
|
||||
m_oLine.Clear();
|
||||
m_oMeta.ClearNoAttack();
|
||||
m_pPageMeta.WriteBYTE(162); // CMetafile::ctCommandTextLineEnd
|
||||
}
|
||||
#endif
|
||||
void CDjVuFileImplementation::CreateFrame(IRenderer* pRenderer, GP<DjVuImage>& pPage, int nPage, XmlUtils::CXmlNode& text)
|
||||
{
|
||||
@ -684,6 +1060,9 @@ void CDjVuFileImplementation::CreateFrame(IRenderer* pRenderer, GP
|
||||
{
|
||||
TextToRenderer(pRenderer, text, dPixToMM / nDpi);
|
||||
}
|
||||
#ifdef BUILDING_WASM_MODULE
|
||||
TextToRenderer(pRenderer, text, dPixToMM / nDpi);
|
||||
#endif
|
||||
|
||||
pRenderer->DrawImage((IGrObject*)&oImage, 0, 0, dRendWidth, dRendHeight);
|
||||
pRenderer->EndCommand(c_nPageType);
|
||||
@ -1152,6 +1531,9 @@ void CDjVuFileImplementation::DrawPageText(IRenderer* pRenderer, d
|
||||
(float)(pdCoords[3]),
|
||||
(float)(pdCoords[2] - pdCoords[0]),
|
||||
(float)(pdCoords[1] - pdCoords[3]));
|
||||
#ifdef BUILDING_WASM_MODULE
|
||||
GetGlyphs(pRenderer, wsText, NULL, pdCoords[0], pdCoords[3]);
|
||||
#endif
|
||||
}
|
||||
void CDjVuFileImplementation::ParseCoords(const std::wstring& wsCoordsStr, double* pdCoords, double dKoef)
|
||||
{
|
||||
|
||||
@ -54,6 +54,9 @@
|
||||
#include "../DesktopEditor/xml/include/xmlutils.h"
|
||||
#include "../DesktopEditor/graphics/IRenderer.h"
|
||||
#include "../DesktopEditor/graphics/pro/Fonts.h"
|
||||
#ifdef BUILDING_WASM_MODULE
|
||||
#include "../../DesktopEditor/graphics/pro/js/wasm/src/serialize.h"
|
||||
#endif
|
||||
|
||||
class CDjVuFileImplementation
|
||||
{
|
||||
@ -83,6 +86,18 @@ public:
|
||||
BYTE* GetStructure();
|
||||
BYTE* GetPageGlyphs(int nPageIndex);
|
||||
BYTE* GetPageLinks (int nPageIndex);
|
||||
void GetGlyphs(IRenderer* pRenderer, const std::wstring& bsUnicodeText, unsigned int* pGids, double x, double y);
|
||||
void DumpLine();
|
||||
NSWasm::CData m_pPageMeta;
|
||||
|
||||
private:
|
||||
double m_dCurrentFontSize = 0.0;
|
||||
NSWasm::CHLine m_oLine;
|
||||
NSWasm::CData m_oMeta;
|
||||
Aggplus::CMatrix m_pLastTransform;
|
||||
LONG m_lCurrentFont = -1;
|
||||
LONG m_nLastBrushColor1 = -1;
|
||||
LONG m_nLastBrushAlpha1 = -1;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user