refactoring

This commit is contained in:
Kulikova Svetlana
2021-07-15 18:48:19 +03:00
parent 72edf8e89d
commit 7abae785cb
6 changed files with 229 additions and 371 deletions

View File

@ -130,10 +130,12 @@
var len = lenArray[0];
len -= 4;
if (len)
this.pages[pageIndex].Glyphs = [];
this.pages[pageIndex].Lines = [];
var buffer = new Uint8Array(Module["HEAP8"].buffer, res + 4 * width * height + 4, len);
var index = 0;
var Line = -1;
var prevY = -1;
while (index < len)
{
var lenRec = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
@ -142,20 +144,37 @@
index += lenRec;
lenRec = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
index += 4;
var _fontSize = "".fromUtf8(buffer, index, lenRec);
var _fontSize = parseFloat("".fromUtf8(buffer, index, lenRec));
index += lenRec;
lenRec = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
index += 4;
var _X = "".fromUtf8(buffer, index, lenRec);
var _X = parseFloat("".fromUtf8(buffer, index, lenRec));
index += lenRec;
lenRec = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
index += 4;
var _Y = "".fromUtf8(buffer, index, lenRec);
var _Y = parseFloat("".fromUtf8(buffer, index, lenRec));
// TODO: близость
if (_Y != prevY)
{
if (Line >= 0)
this.pages[pageIndex].Lines[Line].Glyphs.sort((prev, next) => prev.X - next.X);
Line++;
this.pages[pageIndex].Lines.push({ Glyphs : [] });
prevY = _Y;
}
index += lenRec;
lenRec = buffer[index] | buffer[index + 1] << 8 | buffer[index + 2] << 16 | buffer[index + 3] << 24;
index += 4;
this.pages[pageIndex].Glyphs.push({ fontName : _fontName, fontSize : _fontSize, X : _X, Y : _Y, UChar : lenRec});
this.pages[pageIndex].Lines[Line].Glyphs.push({
fontName : _fontName,
fontSize : _fontSize,
X : _X * 1.015,
Y : _Y * 1.015,
UChar : String.fromCharCode(lenRec)
});
}
if (len > 0)
this.pages[pageIndex].Lines.sort((prev, next) => prev.Glyphs[0].Y - next.Glyphs[0].Y);
return res;
};
CFile.prototype.close = function()

View File

@ -736,44 +736,46 @@ int main()
XPS_Delete(pXpsData);
int* info = XPS_GetInfo(test);
int pages_count = *info;
int width = info[1] * 96 / info[3];
int height = info[2] * 96 / info[3];
BYTE* res = NULL;
if (pages_count > 0)
res = XPS_GetPixmap(test, 0, info[1], info[2]);
res = XPS_GetPixmap(test, 0, width, height);
for (int i = 0; i < 100; i++)
std::cout << (int)res[i] << " ";
CBgraFrame* resFrame = new CBgraFrame();
resFrame->put_Data(res);
resFrame->put_Width(info[1]);
resFrame->put_Height(info[2]);
resFrame->put_Stride(-4 * info[1]);
resFrame->put_Width(width);
resFrame->put_Height(height);
resFrame->put_Stride(-4 * width);
resFrame->put_IsRGBA(true);
resFrame->SaveFile(NSFile::GetProcessDirectory() + L"/res.png", _CXIMAGE_FORMAT_PNG);
resFrame->ClearNoAttack();
DWORD nLength = GetLength(res + info[1] * info[2] * 4);
DWORD nLength = GetLength(res + width * height * 4);
DWORD i = 4;
nLength -= 4;
while (i < nLength)
{
DWORD nPathLength = GetLength(res + info[1] * info[2] * 4 + i);
DWORD nPathLength = GetLength(res + width * height * 4 + i);
i += 4;
std::cout << std::string((char*)(res + info[1] * info[2] * 4 + i), nPathLength) << " ";
std::cout << std::string((char*)(res + width * height * 4 + i), nPathLength) << " ";
i += nPathLength;
nPathLength = GetLength(res + info[1] * info[2] * 4 + i);
nPathLength = GetLength(res + width * height * 4 + i);
i += 4;
std::cout << std::string((char*)(res + info[1] * info[2] * 4 + i), nPathLength) << " ";
std::cout << std::string((char*)(res + width * height * 4 + i), nPathLength) << " ";
i += nPathLength;
nPathLength = GetLength(res + info[1] * info[2] * 4 + i);
nPathLength = GetLength(res + width * height * 4 + i);
i += 4;
std::cout << std::string((char*)(res + info[1] * info[2] * 4 + i), nPathLength) << " ";
std::cout << std::string((char*)(res + width * height * 4 + i), nPathLength) << " ";
i += nPathLength;
nPathLength = GetLength(res + info[1] * info[2] * 4 + i);
nPathLength = GetLength(res + width * height * 4 + i);
i += 4;
std::cout << std::string((char*)(res + info[1] * info[2] * 4 + i), nPathLength) << " ";
std::cout << std::string((char*)(res + width * height * 4 + i), nPathLength) << " ";
i += nPathLength;
nPathLength = GetLength(res + info[1] * info[2] * 4 + i);
nPathLength = GetLength(res + width * height * 4 + i);
i += 4;
std::cout << nPathLength << std::endl;
}

View File

@ -324,14 +324,63 @@ window.onload = function()
this.OnMouseDown = function(e)
{
if (!this.file.isValid())
return;
let yPos = e.clientY;
let yMax = yPos + this.height;
let lCurrentPage = -1;
let lPagesCount = this.drawingPages.length;
for (let i = 0; i < lPagesCount; i++)
{
let page = this.drawingPages[i];
let pageT = page.Y;
let pageB = page.Y + page.H;
if (yPos > pageT && yPos < pageB)
{
lCurrentPage = i;
break;
}
}
// TODO: координаты относительно страницы
if (lCurrentPage >= 0)
this.file.OnMouseDown(lCurrentPage, e.clientX, e.clientY);
};
this.OnMouseMove = function(e)
{
if (!this.file.isValid())
return;
let yPos = e.clientY;
let yMax = yPos + this.height;
let lCurrentPage = -1;
let lPagesCount = this.drawingPages.length;
for (let i = 0; i < lPagesCount; i++)
{
let page = this.drawingPages[i];
let pageT = page.Y;
let pageB = page.Y + page.H;
if (yPos > pageT && yPos < pageB)
{
lCurrentPage = i;
break;
}
}
// TODO: координаты относительно страницы
if (lCurrentPage >= 0)
this.file.OnMouseMove(lCurrentPage, e.clientX, e.clientY);
};
this.OnMouseUp = function(e)
{
this.file.OnMouseUp();
};
this.paint = function()

View File

@ -1,5 +1,18 @@
(function(window, undefined) {
function CDocMetaSelection()
{
this.Page1 = 0;
this.Line1 = 0;
this.Glyph1 = 0;
this.Page2 = 0;
this.Line2 = 0;
this.Glyph2 = 0;
this.IsSelection = false;
}
function CFile()
{
this.nativeFile = 0;
@ -8,6 +21,7 @@
this.isUse3d = false;
this.cacheManager = null;
this.logging = true;
this.Selection = new CDocMetaSelection();
}
// interface
@ -45,11 +59,125 @@
var t2 = performance.now();
//console.log("time: " + (t1 - t0) + ", " + (t2 - t1));
}
/*
if (this.pages[pageIndex].Lines)
{
var ctx = image.getContext("2d");
for (let i = 0; i < this.pages[pageIndex].Lines.length; i++)
{
for (let j = 0; j < this.pages[pageIndex].Lines[i].Glyphs.length; j++)
{
let glyph = this.pages[pageIndex].Lines[i].Glyphs[j];
ctx.font = glyph.fontSize + 'px ' + glyph.fontName;
ctx.fillText(glyph.UChar, glyph.X, glyph.Y);
}
}
}
*/
this.free(pixels);
return image;
};
CFile.prototype.GetNearestPos = function(pageIndex, x, y)
{
var _line = -1;
var _glyph = -1;
var minDist = Number.MAX_SAFE_INTEGER;
// TODO: оптимизировать по горизонтальной линии
for (let i = 0; i < this.pages[pageIndex].Lines.length; i++)
{
for (let j = 0; j < this.pages[pageIndex].Lines[i].Glyphs.length; j++)
{
let glyph = this.pages[pageIndex].Lines[i].Glyphs[j];
let d = Math.sqrt(Math.pow(glyph.X - x, 2) + Math.pow(glyph.Y - y, 2));
if (d < minDist)
{
minDist = d;
_line = i;
_glyph = j;
}
}
}
return { Line : _line, Glyph : _glyph };
}
CFile.prototype.OnUpdateSelection = function()
{
// TODO: выделять не после OnMouseUp
if (this.Selection.IsSelection)
return;
var sel = this.Selection;
var page1 = sel.Page1 < sel.Page2 ? sel.Page1 : sel.Page2;
var page2 = sel.Page1 > sel.Page2 ? sel.Page1 : sel.Page2;
var line1 = sel.Line1 < sel.Line2 ? sel.Line1 : sel.Line2;
var line2 = sel.Line1 > sel.Line2 ? sel.Line1 : sel.Line2;
var glyph1 = sel.Glyph1 < sel.Glyph2 ? sel.Glyph1 : sel.Glyph2;
var glyph2 = sel.Glyph1 > sel.Glyph2 ? sel.Glyph1 : sel.Glyph2;
for (let page = page1; page <= page2; page++)
{
// TODO: если страница не последняя, то выделить целиком
for (let line = line1; line <= line2; line++)
{
let Glyphs = this.pages[page].Lines[line].Glyphs;
let x = Glyphs[0].X;
let y = Glyphs[0].Y;
let w = Glyphs[Glyphs.length - 1].X;
let h = x + Glyphs[0].fontSize;
// если последняя строка
if (line == line2)
w = Glyphs[glyph2].X;
// TODO: поступить аналогично _pixelsToCanvas2d
let canvas = document.getElementById("main");
let ctx = canvas.getContext("2d");
ctx.globalAlpha = 0.5;
ctx.fillStyle = "#0000FF";
ctx.fillRect(x, y, w, h);
ctx.globalAlpha = 1;
}
}
}
CFile.prototype.OnMouseDown = function(pageIndex, x, y)
{
var ret = this.GetNearestPos(pageIndex, x, y);
var sel = this.Selection;
sel.Page1 = pageIndex;
sel.Line1 = ret.Line;
sel.Glyph1 = ret.Glyph;
sel.Page2 = pageIndex;
sel.Line2 = ret.Line;
sel.Glyph2 = ret.Glyph;
sel.IsSelection = true;
//this.OnUpdateSelection();
}
CFile.prototype.OnMouseMove = function(pageIndex, x, y)
{
if (false === this.Selection.IsSelection)
return;
var ret = this.GetNearestPos(pageIndex, x, y);
var sel = this.Selection;
sel.Page2 = pageIndex;
sel.Line2 = ret.Line;
sel.Glyph2 = ret.Glyph;
//this.OnUpdateSelection();
}
CFile.prototype.OnMouseUp = function()
{
this.Selection.IsSelection = false;
this.OnUpdateSelection();
}
CFile.prototype.getPageBase64 = function(pageIndex, width, height)
{
var _canvas = this.getPage(pageIndex, width, height);

View File

@ -1,348 +0,0 @@
(function(window, undefined) {
function CDocMetaSelection()
{
this.Page1 = 0;
this.Line1 = 0;
this.Glyph1 = 0;
this.Page2 = 0;
this.Line2 = 0;
this.Glyph2 = 0;
this.IsSelection = false;
}
function CSpan()
{
this.fontName = 0;
this.fontSize = 0;
this.colorR = 0;
this.colorG = 0;
this.colorB = 0;
this.inner = "";
this.CreateDublicate = function()
{
var ret = new CSpan();
ret.fontName = this.fontName;
ret.fontSize = this.fontSize;
ret.colorR = this.colorR;
ret.colorG = this.colorG;
ret.colorB = this.colorB;
ret.inner = this.inner;
return ret;
}
}
function CDocMeta()
{
this.Pages = null;
this.stream = null;
this.Selection = new CDocMetaSelection();
}
CDocMeta.prototype =
{
getStreamPage : function(pageNum)
{
return this.stream;
},
GetNearestPos : function(pageNum, x, y)
{
var page = this.Pages[pageNum];
var s = this.getStreamPage(pageNum);
s.Seek(page.start);
// textline parameters
var _line = -1;
var _glyph = -1;
var _minDist = 0xFFFFFF;
// textline parameters
var _lineX = 0;
var _lineY = 0;
var _lineEx = 0;
var _lineEy = 0;
var _lineAscent = 0;
var _lineDescent = 0;
var _lineWidth = 0;
var _lineGidExist = false;
var _linePrevCharX = 0;
var _lineCharCount = 0;
var _lineLastGlyphWidth = 0;
var _arrayGlyphOffsets = [];
var _numLine = -1;
var _lenGls = 0;
var tmp = 0;
while (s.pos < page.end)
{
var command = s.GetUChar();
switch (command)
{
case 80:
{
if (0 != _lineCharCount)
_linePrevCharX += s.GetDouble2();
_arrayGlyphOffsets[_lineCharCount] = _linePrevCharX;
_lineCharCount++;
if (_lineGidExist)
s.Skip(4);
else
s.Skip(2);
if (0 == _lineWidth)
_lineLastGlyphWidth = s.GetDouble2();
else
s.Skip(2);
break;
}
case 160:
{
// textline
_linePrevCharX = 0;
_lineCharCount = 0;
_lineWidth = 0;
_arrayGlyphOffsets.splice(0, _arrayGlyphOffsets.length);
++_numLine;
var mask = s.GetUChar();
_lineX = s.GetDouble();
_lineY = s.GetDouble();
if ((mask & 0x01) != 0)
{
_lineEx = 1;
_lineEy = 0;
}
else
{
_lineEx = s.GetDouble();
_lineEy = s.GetDouble();
}
_lineAscent = s.GetDouble();
_lineDescent = s.GetDouble();
if ((mask & 0x04) != 0)
_lineWidth = s.GetDouble();
if ((mask & 0x02) != 0)
_lineGidExist = true;
else
_lineGidExist = false;
break;
}
case 162:
{
// textline end
// все подсчитано
if (0 == _lineWidth)
_lineWidth = _linePrevCharX + _lineLastGlyphWidth;
// в принципе код один и тот же. Но почти всегда линии горизонтальные.
// а для горизонтальной линии все можно пооптимизировать
if (_lineEx == 1 && _lineEy == 0)
{
var _distX = x - _lineX;
if (y >= (_lineY - _lineAscent) && y <= (_lineY + _lineDescent) && _distX >= 0 && _distX <= _lineWidth)
{
// попали внутрь линии. Теперь нужно найти глиф
_line = _numLine;
_lenGls = _arrayGlyphOffsets.length;
for (_glyph = 0; _glyph < _lenGls; _glyph++)
{
if (_arrayGlyphOffsets[_glyph] > _distX)
break;
}
if (_glyph > 0)
--_glyph;
return { Line : _line, Glyph : _glyph };
}
if (_distX >= 0 && _distX <= _lineWidth)
tmp = Math.abs(y - _lineY);
else if (_distX < 0)
{
tmp = Math.sqrt((x - _lineX) * (x - _lineX) + (y - _lineY) * (y - _lineY));
}
else
{
var _xx1 = _lineX + _lineWidth;
tmp = Math.sqrt((x - _xx1) * (x - _xx1) + (y - _lineY) * (y - _lineY));
}
if (tmp < _minDist)
{
_minDist = tmp;
_line = _numLine;
if (_distX < 0)
_glyph = -2;
else if (_distX > _lineWidth)
{
_glyph = -1;
}
else
{
_lenGls = _arrayGlyphOffsets.length;
for (_glyph = 0; _glyph < _lenGls; _glyph++)
{
if (_arrayGlyphOffsets[_glyph] > _distX)
break;
}
if (_glyph > 0)
_glyph--;
}
}
// Ничего не надо делать, уже найдена более "ближняя" линия
}
else
{
// определяем точки descent линии
var ortX = -_lineEy;
var ortY = _lineEx;
var _dx = _lineX + ortX * _lineDescent;
var _dy = _lineY + ortY * _lineDescent;
// теперь проекции (со знаком) на линию descent
var h = -((x - _dx) * ortX + (y - _dy) * ortY);
var w = (x - _dx) * _lineEx + (y - _dy) * _lineEy;
if (w >= 0 && w <= _lineWidth && h >= 0 && h <= (_lineDescent + _lineAscent))
{
// попали внутрь линии. Теперь нужно найти глиф
_line = _numLine;
_lenGls = _arrayGlyphOffsets.length;
for (_glyph = 0; _glyph < _lenGls; _glyph++)
{
if (_arrayGlyphOffsets[_glyph] > w)
break;
}
if (_glyph > 0)
_glyph--;
return { Line : _line, Glyph : _glyph };
}
if (w >= 0 && w <= _lineWidth)
tmp = Math.abs(h - _lineDescent);
else if (w < 0)
{
tmp = Math.sqrt((x - _lineX) * (x - _lineX) + (y - _lineY) * (y - _lineY));
}
else
{
var _tmpX = _lineX + _lineWidth * _lineEx;
var _tmpY = _lineY + _lineWidth * _lineEy;
tmp = Math.sqrt((x - _tmpX) * (x - _tmpX) + (y - _tmpY) * (y - _tmpY));
}
//tmp = Math.abs(h - _lineDescent);
if (tmp < _minDist)
{
_minDist = tmp;
_line = _numLine;
if (w < 0)
_glyph = -2;
else if (w > _lineWidth)
_glyph = -1;
else
{
_lenGls = _arrayGlyphOffsets.length;
for (_glyph = 0; _glyph < _lenGls; _glyph++)
{
if (_arrayGlyphOffsets[_glyph] > w)
break;
}
if (_glyph > 0)
_glyph--;
}
}
// Ничего не надо делать, уже найдена более "ближняя" линия
}
break;
}
}
}
return { Line : _line, Glyph : _glyph };
},
OnMouseDown : function(page, x, y)
{
var ret = this.GetNearestPos(page, x, y);
var sel = this.Selection;
sel.Page1 = page;
sel.Line1 = ret.Line;
sel.Glyph1 = ret.Glyph;
sel.Page2 = page;
sel.Line2 = ret.Line;
sel.Glyph2 = ret.Glyph;
sel.IsSelection = true;
this.OnUpdateSelection();
},
OnMouseMove : function(page, x, y)
{
if (false === this.Selection.IsSelection)
return;
var ret = this.GetNearestPos(page, x, y);
var sel = this.Selection;
sel.Page2 = page;
sel.Line2 = ret.Line;
sel.Glyph2 = ret.Glyph;
this.OnUpdateSelection();
},
OnMouseUp : function()
{
this.Selection.IsSelection = false;
},
OnUpdateSelection : function()
{
editor.WordControl.m_oOverlayApi.Show();
editor.WordControl.OnUpdateOverlay();
},
}
})(window, undefined);

View File

@ -715,15 +715,23 @@ namespace XPS
m_pGlyphs = new CData();
m_pGlyphs->SkipLen();
}
double _dX = dXorigin;
double _dY = dYorigin;
double pdA, pdB, pdC, pdD, pdE, pdF;
pRenderer->GetTransform(&pdA, &pdB, &pdC, &pdD, &pdE, &pdF);
Aggplus::CMatrix oTransform(pdA, pdB, pdC, pdD, pdE, pdF);
oTransform.TransformPoint(_dX, _dY);
std::wstring wsFontName;
pRenderer->get_FontName(&wsFontName);
std::string sFontName = U_TO_UTF8(wsFontName);
m_pGlyphs->WriteString((BYTE*)sFontName.c_str(), sFontName.length());
std::string sFontSize = std::to_string(dFontSize * 0.75);
std::string sFontSize = std::to_string(dFontSize * pdA + pdE);
m_pGlyphs->WriteString((BYTE*)sFontSize.c_str(), sFontSize.length());
std::string sX = std::to_string(xpsUnitToMM(dXorigin));
std::string sX = std::to_string(_dX);
m_pGlyphs->WriteString((BYTE*)sX.c_str(), sX.length());
std::string sY = std::to_string(xpsUnitToMM(dYorigin));
std::string sY = std::to_string(_dY);
m_pGlyphs->WriteString((BYTE*)sY.c_str(), sY.length());
m_pGlyphs->AddInt(oEntry.nUnicode);
m_pGlyphs->WriteLen();