#include "DjVuFileImplementation.h" #include "../DesktopEditor/common/File.h" #include "../DesktopEditor/common/Directory.h" #include "../DesktopEditor/graphics/IRenderer.h" #include "../DesktopEditor/raster/BgraFrame.h" #include "../DesktopEditor/graphics/Image.h" #include "../DesktopEditor/common/String.h" #include "../DesktopEditor/fontengine/FontManager.h" #include "../DesktopEditor/fontengine/ApplicationFonts.h" #include "../DesktopEditor/raster/BgraFrame.h" #include "../DesktopEditor/graphics/GraphicsRenderer.h" #include "../PdfWriter/PdfRenderer.h" #include "../DesktopEditor/raster/JBig2/source/Encoder/jbig2enc.h" #include "../DesktopEditor/raster/JBig2/source/LeptonLib/allheaders.h" #define VER_DPI 96 #define HOR_DPI 96 #include namespace NSDjvu { static GUTF8String MakeUTF8String(const std::wstring& wsText) { std::string sText = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsText); GUTF8String utf8String(sText.c_str()); return utf8String; } static CString MakeCString(GUTF8String& strText) { std::string sString(strText.getbuf()); std::wstring wsString = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)sString.c_str(), sString.length()); return CString(wsString.c_str()); } static int GetInteger(const std::wstring& wsString) { if (wsString.size() < 1) return 0; try { return _ttoi(wsString.c_str()); } catch (...) { } try { return static_cast(_wtoi64(wsString.c_str())); } catch (...) { return 0; } } } CDjVuFileImplementation::CDjVuFileImplementation() { m_pDoc = NULL; std::wstring wsTempPath = NSFile::CFileBinary::GetTempPath(); wsTempPath += L"DJVU\\"; m_wsTempDirectory = wsTempPath; NSDirectory::CreateDirectory(m_wsTempDirectory); } CDjVuFileImplementation::~CDjVuFileImplementation() { NSDirectory::DeleteDirectory(m_wsTempDirectory); } bool CDjVuFileImplementation::LoadFromFile(const std::wstring& wsSrcFileName, const std::wstring& wsXMLOptions) { m_pDoc = NULL; try { GUTF8String utf8; GURL url = GURL::Filename::UTF8(NSDjvu::MakeUTF8String(wsSrcFileName)); m_pDoc = DjVuDocument::create(url); m_pDoc->wait_get_pages_num(); } catch (...) { return false; } return true; } void CDjVuFileImplementation::Close() { } std::wstring CDjVuFileImplementation::GetTempDirectory() const { return m_wsTempDirectory; } void CDjVuFileImplementation::SetTempDirectory(const std::wstring& wsDirectory) { NSDirectory::DeleteDirectory(m_wsTempDirectory); m_wsTempDirectory = wsDirectory; m_wsTempDirectory += L"\\DJVU\\"; NSDirectory::CreateDirectory(m_wsTempDirectory); } int CDjVuFileImplementation::GetPagesCount() const { if (!m_pDoc) return 0; return m_pDoc->get_pages_num(); } void CDjVuFileImplementation::GetPageInfo(int nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY) const { if (!m_pDoc) { *pdWidth = 0; *pdHeight = 0; *pdDpiX = 96; *pdDpiY = 96; } GP pPage = m_pDoc->get_page(nPageIndex); pPage->wait_for_complete_decode(); pPage->set_rotate(0); *pdWidth = pPage->get_real_width(); *pdHeight = pPage->get_real_height(); *pdDpiX = pPage->get_dpi(); *pdDpiY = pPage->get_dpi(); } void CDjVuFileImplementation::DrawPageOnRenderer(IRenderer* pRenderer, int nPageIndex, bool* pBreak) { if (!m_pDoc) return; try { GP pPage = m_pDoc->get_page(nPageIndex); pPage->wait_for_complete_decode(); pPage->set_rotate(0); long lRendererType = c_nUnknownRenderer; pRenderer->get_Type(&lRendererType); if (false)//c_nGrRenderer == lRendererType) { CreateGrFrame(pRenderer, pPage, pBreak); } else if (c_nPDFWriter == lRendererType) { XmlUtils::CXmlNode oText = ParseText(pPage); CreatePdfFrame(pRenderer, pPage, nPageIndex, oText); } else { XmlUtils::CXmlNode oText = ParseText(pPage); CreateFrame(pRenderer, pPage, nPageIndex, oText); } } catch (...) { // белая страница } } void CDjVuFileImplementation::ConvertToRaster(CApplicationFonts* pAppFonts, int nPageIndex, const std::wstring& wsDstPath, int nImageType) { CFontManager *pFontManager = pAppFonts->GenerateFontManager(); CFontsCache* pFontCache = new CFontsCache(); pFontCache->SetStreams(pAppFonts->GetStreams()); pFontManager->SetOwnerCache(pFontCache); CGraphicsRenderer oRenderer; oRenderer.SetFontManager(pFontManager); double dPageDpiX, dPageDpiY; double dWidth, dHeight; GetPageInfo(nPageIndex, &dWidth, &dHeight, &dPageDpiX, &dPageDpiX); int nWidth = (int)dWidth * 96 / dPageDpiX; int nHeight = (int)dHeight * 96 / dPageDpiX; BYTE* pBgraData = new BYTE[nWidth * nHeight * 4]; if (!pBgraData) return; memset(pBgraData, 0xff, nWidth * nHeight * 4); CBgraFrame oFrame; oFrame.put_Data(pBgraData); oFrame.put_Width(nWidth); oFrame.put_Height(nHeight); oFrame.put_Stride(-4 * nWidth); oRenderer.CreateFromBgraFrame(&oFrame); oRenderer.SetSwapRGB(false); oRenderer.put_Width(dWidth); oRenderer.put_Height(dHeight); bool bBreak = false; DrawPageOnRenderer(&oRenderer, nPageIndex, &bBreak); oFrame.SaveFile(wsDstPath, nImageType); RELEASEINTERFACE(pFontManager); } void CDjVuFileImplementation::ConvertToPdf(CApplicationFonts* pAppFonts, const std::wstring& wsDstPath) { CPdfRenderer oPdf(pAppFonts); bool bBreak = false; for (int nPageIndex = 0, nPagesCount = GetPagesCount(); nPageIndex < nPagesCount; nPageIndex++) { oPdf.NewPage(); double dPageDpiX, dPageDpiY; double dWidth, dHeight; GetPageInfo(nPageIndex, &dWidth, &dHeight, &dPageDpiX, &dPageDpiY); dWidth *= 25.4 / dPageDpiX; dHeight *= 25.4 / dPageDpiY; oPdf.put_Width(dWidth); oPdf.put_Height(dHeight); DrawPageOnRenderer(&oPdf, nPageIndex, &bBreak); #ifdef _DEBUG printf("%d of %d pages\n", nPageIndex + 1, nPagesCount); #endif } oPdf.SaveToFile(wsDstPath); } void CDjVuFileImplementation::CreateFrame(IRenderer* pRenderer, GP& pPage, int nPage, XmlUtils::CXmlNode& text) { int nWidth = pPage->get_real_width(); int nHeight = pPage->get_real_height(); int nDpi = pPage->get_dpi(); double dPixToMM = 25.4; double dRendDpiX = 0; double dRendDpiY = 0; pRenderer->get_DpiX(&dRendDpiX); pRenderer->get_DpiY(&dRendDpiY); if (0 >= dRendDpiX) dRendDpiX = 72.0; if (0 >= dRendDpiY) dRendDpiY = 72.0; double dRendWidth = 0; double dRendHeight = 0; pRenderer->get_Width(&dRendWidth); pRenderer->get_Height(&dRendHeight); if (0 >= dRendWidth) dRendWidth = 200; if (0 >= dRendHeight) dRendHeight = 300; LONG lImageWidth = (LONG)(dRendDpiX * dRendWidth / dPixToMM); LONG lImageHeight = (LONG)(dRendDpiY * dRendHeight / dPixToMM); long lRendererType = c_nUnknownRenderer; pRenderer->get_Type(&lRendererType); if (c_nPDFWriter == lRendererType) { lImageWidth = pPage->get_real_width(); lImageHeight = pPage->get_real_height(); } else if (c_nHtmlRendrerer == lRendererType) { // TODO: Нужно реализовать функцию // pRenderer->GetMaxImageSize(); //VARIANT var; //renderer->GetAdditionalParam(L"MaxImageSize", &var); //LONG lMaxWidth = var.lVal; //if ((lImageWidth > lMaxWidth) || (lImageHeight > lMaxWidth)) //{ // double dAspect = (double)(lImageWidth) / lImageHeight; // if (lImageWidth > lImageHeight) // { // lImageWidth = lMaxWidth; // lImageHeight = (LONG)(lImageHeight / dAspect); // } // else // { // lImageHeight = lMaxWidth; // lImageWidth = (LONG)(dAspect * lImageHeight); // } //} } BYTE* pBufferDst = new BYTE[4 * lImageHeight * lImageWidth]; if (!pBufferDst) return; Aggplus::CImage oImage; oImage.Create(pBufferDst, lImageWidth, lImageHeight, 4 * lImageWidth); if (pPage->is_legal_photo() || pPage->is_legal_compound()) { GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pImage = pPage->get_pixmap(oRectAll, oRectAll); BYTE* pBuffer = pBufferDst; for (int j = lImageHeight - 1; j >= 0; --j) { GPixel* pLine = pImage->operator [](j); for (int i = 0; i < lImageWidth; ++i, pBuffer += 4, ++pLine) { pBuffer[0] = pLine->b; pBuffer[1] = pLine->g; pBuffer[2] = pLine->r; pBuffer[3] = 255; } } } else if (pPage->is_legal_bilevel()) { GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pBitmap = pPage->get_bitmap(oRectAll, oRectAll, 4); int nPaletteEntries = pBitmap->get_grays(); DWORD* palette = new DWORD[nPaletteEntries]; // Create palette for the bitmap int color = 0xff0000; int decrement = color / (nPaletteEntries - 1); for (int i = 0; i < nPaletteEntries; ++i) { BYTE level = (BYTE)(color >> 16); palette[i] = (0xFF000000 | level << 16 | level << 8 | level); color -= decrement; } DWORD* pBuffer = (DWORD*)pBufferDst; for (int j = lImageHeight - 1; j >= 0; --j) { BYTE* pLine = pBitmap->operator [](j); for (int i = 0; i < lImageWidth; ++i, ++pBuffer, ++pLine) { if (*pLine < nPaletteEntries) { *pBuffer = palette[*pLine]; } else { *pBuffer = palette[0]; } } } RELEASEARRAYOBJECTS(palette); } else { // белый фрейм?? //memset(pBufferDst, 0xFF, 4 * lImageWidth * lImageHeight); GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pImage = pPage->get_pixmap(oRectAll, oRectAll); if (NULL != pImage) { BYTE* pBuffer = pBufferDst; for (int j = lImageHeight - 1; j >= 0; --j) { GPixel* pLine = pImage->operator [](j); for (int i = 0; i < lImageWidth; ++i, pBuffer += 4, ++pLine) { pBuffer[0] = pLine->b; pBuffer[1] = pLine->g; pBuffer[2] = pLine->r; pBuffer[3] = 255; } } } else { GP pBitmap = pPage->get_bitmap(oRectAll, oRectAll, 4); if (NULL != pBitmap) { int nPaletteEntries = pBitmap->get_grays(); DWORD* palette = new DWORD[nPaletteEntries]; // Create palette for the bitmap int color = 0xff0000; int decrement = color / (nPaletteEntries - 1); for (int i = 0; i < nPaletteEntries; ++i) { BYTE level = (BYTE)(color >> 16); palette[i] = (0xFF000000 | level << 16 | level << 8 | level); color -= decrement; } DWORD* pBuffer = (DWORD*)pBufferDst; for (int j = lImageHeight - 1; j >= 0; --j) { BYTE* pLine = pBitmap->operator [](j); for (int i = 0; i < lImageWidth; ++i, ++pBuffer, ++pLine) { if (*pLine < nPaletteEntries) { *pBuffer = palette[*pLine]; } else { *pBuffer = palette[0]; } } } RELEASEARRAYOBJECTS(palette); } } } pRenderer->BeginCommand(c_nPageType); if (c_nGrRenderer != lRendererType && c_nHtmlRendrerer != lRendererType && c_nHtmlRendrerer2 != lRendererType) { TextToRenderer(pRenderer, text, dPixToMM / nDpi); } pRenderer->DrawImage((IGrObject*)&oImage, 0, 0, dRendWidth, dRendHeight); pRenderer->EndCommand(c_nPageType); } void CDjVuFileImplementation::CreatePdfFrame(IRenderer* pRenderer, GP& pPage, int nPageIndex, XmlUtils::CXmlNode& oText) { double dPageDpiX, dPageDpiY; double dWidth, dHeight; GetPageInfo(nPageIndex, &dWidth, &dHeight, &dPageDpiX, &dPageDpiY); dWidth *= 25.4 / dPageDpiX; dHeight *= 25.4 / dPageDpiY; pRenderer->BeginCommand(c_nPageType); TextToRenderer(pRenderer, oText, 25.4 / pPage->get_dpi()); LONG lImageWidth = pPage->get_real_width(); LONG lImageHeight = pPage->get_real_height(); CPdfRenderer* pPdf = (CPdfRenderer*)pRenderer; if (pPage->is_legal_photo()) { BYTE* pBufferDst = new BYTE[4 * lImageHeight * lImageWidth]; if (!pBufferDst) return; Aggplus::CImage oImage; oImage.Create(pBufferDst, lImageWidth, lImageHeight, 4 * lImageWidth); GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pImage = pPage->get_pixmap(oRectAll, oRectAll); BYTE* pBuffer = pBufferDst; for (int j = lImageHeight - 1; j >= 0; --j) { GPixel* pLine = pImage->operator [](j); for (int i = 0; i < lImageWidth; ++i, pBuffer += 4, ++pLine) { pBuffer[0] = pLine->b; pBuffer[1] = pLine->g; pBuffer[2] = pLine->r; pBuffer[3] = 255; } } pRenderer->DrawImage((IGrObject*)&oImage, 0, 0, dWidth, dHeight); } else if (pPage->is_legal_compound()) { GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pIW44Image = pPage->get_bg44(); if (NULL != pIW44Image) { int nBgWidth = pIW44Image->get_width(); int nBgHeight = pIW44Image->get_height(); GP pBgImage = pIW44Image->get_pixmap(); if (NULL != pBgImage) { BYTE* pBgBuffer = new BYTE[4 * nBgWidth * nBgHeight]; if (!pBgBuffer) return; Aggplus::CImage oBgImage; oBgImage.Create(pBgBuffer, nBgWidth, nBgHeight, 4 * nBgWidth); BYTE* pBuffer = pBgBuffer; for (int j = nBgHeight - 1; j >= 0; --j) { GPixel* pLine = pBgImage->operator [](j); for (int i = 0; i < nBgWidth; ++i, pBuffer += 4, ++pLine) { pBuffer[0] = pLine->b; pBuffer[1] = pLine->g; pBuffer[2] = pLine->r; pBuffer[3] = 255; } } pRenderer->DrawImage((IGrObject*)&oBgImage, 0, 0, dWidth, dHeight); } } GP pImage = pPage->get_fgpm(); if (NULL == pImage) pImage = pPage->get_fg_pixmap(oRectAll); if (NULL != pImage) { unsigned int unPixmapH = pImage->rows(); unsigned int unPixmapW = pImage->columns(); BYTE* pBufferDst = new BYTE[4 * unPixmapH * unPixmapW]; if (!pBufferDst) return; Aggplus::CImage oImage; oImage.Create(pBufferDst, unPixmapW, unPixmapH, 4 * unPixmapW); BYTE* pBuffer = pBufferDst; for (int j = unPixmapH - 1; j >= 0; --j) { GPixel* pLine = pImage->operator [](j); for (int i = 0; i < unPixmapW; ++i, pBuffer += 4, ++pLine) { pBuffer[0] = pLine->b; pBuffer[1] = pLine->g; pBuffer[2] = pLine->r; pBuffer[3] = 255; } } GP pBitmap = pPage->get_bitmap(oRectAll, oRectAll, 4); Pix* pPix = pixCreate(lImageWidth, lImageHeight, 1); if (pPix) { for (int nY = 0; nY < lImageHeight; nY++) { BYTE* pLine = pBitmap->operator [](nY); for (int nX = 0; nX < lImageWidth; nX++, pLine++) { pixSetPixel(pPix, nX, lImageHeight - 1 - nY, *pLine); } } pPdf->DrawImageWith1bppMask((IGrObject*)&oImage, pPix, lImageWidth, lImageHeight, 0, 0, dWidth, dHeight); pixDestroy(&pPix); } } } else if (pPage->is_legal_bilevel()) { GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pBitmap = pPage->get_bitmap(oRectAll, oRectAll, 4); Pix* pPix = pixCreate(lImageWidth, lImageHeight, 1); if (pPix) { for (int nY = 0; nY < lImageHeight; nY++) { BYTE* pLine = pBitmap->operator [](nY); for (int nX = 0; nX < lImageWidth; nX++, pLine++) { pixSetPixel(pPix, nX, lImageHeight - 1 - nY, *pLine); } } pPdf->DrawImage1bpp(pPix, lImageWidth, lImageHeight, 0, 0, dWidth, dHeight); pixDestroy(&pPix); } } else { // белый фрейм?? //memset(pBufferDst, 0xFF, 4 * lImageWidth * lImageHeight); GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pImage = pPage->get_pixmap(oRectAll, oRectAll); if (NULL != pImage) { BYTE* pBufferDst = new BYTE[4 * lImageHeight * lImageWidth]; if (pBufferDst) { Aggplus::CImage oImage; oImage.Create(pBufferDst, lImageWidth, lImageHeight, 4 * lImageWidth); BYTE* pBuffer = pBufferDst; for (int j = lImageHeight - 1; j >= 0; --j) { GPixel* pLine = pImage->operator [](j); for (int i = 0; i < lImageWidth; ++i, pBuffer += 4, ++pLine) { pBuffer[0] = pLine->b; pBuffer[1] = pLine->g; pBuffer[2] = pLine->r; pBuffer[3] = 255; } } pRenderer->DrawImage((IGrObject*)&oImage, 0, 0, dWidth, dHeight); } } else { GP pBitmap = pPage->get_bitmap(oRectAll, oRectAll, 4); if (NULL != pBitmap) { int nPaletteEntries = pBitmap->get_grays(); if (nPaletteEntries <= 2) { Pix* pPix = pixCreate(lImageWidth, lImageHeight, 1); if (pPix) { for (int nY = 0; nY < lImageHeight; nY++) { BYTE* pLine = pBitmap->operator [](nY); for (int nX = 0; nX < lImageWidth; nX++, pLine++) { pixSetPixel(pPix, nX, lImageHeight - 1 - nY, *pLine); } } pPdf->DrawImage1bpp(pPix, lImageWidth, lImageHeight, 0, 0, dWidth, dHeight); pixDestroy(&pPix); } } else { BYTE* pBufferDst = new BYTE[4 * lImageHeight * lImageWidth]; if (!pBufferDst) return; Aggplus::CImage oImage; oImage.Create(pBufferDst, lImageWidth, lImageHeight, 4 * lImageWidth); DWORD* palette = new DWORD[nPaletteEntries]; // Create palette for the bitmap int color = 0xff0000; int decrement = color / (nPaletteEntries - 1); for (int i = 0; i < nPaletteEntries; ++i) { BYTE level = (BYTE)(color >> 16); palette[i] = (0xFF000000 | level << 16 | level << 8 | level); color -= decrement; } DWORD* pBuffer = (DWORD*)pBufferDst; for (int j = lImageHeight - 1; j >= 0; --j) { BYTE* pLine = pBitmap->operator [](j); for (int i = 0; i < lImageWidth; ++i, ++pBuffer, ++pLine) { if (*pLine < nPaletteEntries) { *pBuffer = palette[*pLine]; } else { *pBuffer = palette[0]; } } } RELEASEARRAYOBJECTS(palette); pRenderer->DrawImage((IGrObject*)&oImage, 0, 0, dWidth, dHeight); } } } } pRenderer->EndCommand(c_nPageType); } void CDjVuFileImplementation::CreateGrFrame(IRenderer* pRenderer, GP& pPage, bool* pBreak) { int nWidth = pPage->get_real_width(); int nHeight = pPage->get_real_height(); BYTE* pBufferDst = NULL; LONG lImageWidth = 0; LONG lImageHeight = 0; // TODO: Реализовать для графического рендерера //VARIANT var; //renderer->GetAdditionalParam(L"Pixels", &var); //pBufferDst = (BYTE*)var.lVal; //renderer->GetAdditionalParam(L"PixelsWidth", &var); //lImageWidth = var.lVal; //renderer->GetAdditionalParam(L"PixelsHeight", &var); //lImageHeight = var.lVal; volatile bool* pCancel = pBreak; if ((NULL != pCancel) && (TRUE == *pCancel)) return; if (pPage->is_legal_photo() || pPage->is_legal_compound()) { GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pImage = pPage->get_pixmap(oRectAll, oRectAll); BYTE* pBuffer = pBufferDst; for (int j = 0; j < lImageHeight; ++j) { GPixel* pLine = pImage->operator [](j); if ((NULL != pCancel) && (TRUE == *pCancel)) return; for (int i = 0; i < lImageWidth; ++i, pBuffer += 4, ++pLine) { pBuffer[0] = pLine->b; pBuffer[1] = pLine->g; pBuffer[2] = pLine->r; pBuffer[3] = 255; } } } else if (pPage->is_legal_bilevel()) { GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pBitmap = pPage->get_bitmap(oRectAll, oRectAll, 4); int nPaletteEntries = pBitmap->get_grays(); DWORD* palette = new DWORD[nPaletteEntries]; // Create palette for the bitmap int color = 0xff0000; int decrement = color / (nPaletteEntries - 1); for (int i = 0; i < nPaletteEntries; ++i) { BYTE level = (BYTE)(color >> 16); palette[i] = (0xFF000000 | level << 16 | level << 8 | level); color -= decrement; } DWORD* pBuffer = (DWORD*)pBufferDst; for (int j = 0; j < lImageHeight; ++j) { BYTE* pLine = pBitmap->operator [](j); if ((NULL != pCancel) && (TRUE == *pCancel)) return; for (int i = 0; i < lImageWidth; ++i, ++pBuffer, ++pLine) { if (*pLine < nPaletteEntries) { *pBuffer = palette[*pLine]; } else { *pBuffer = palette[0]; } } } RELEASEARRAYOBJECTS(palette); } else { // белый фрейм?? //memset(pBufferDst, 0xFF, 4 * lImageWidth * lImageHeight); GRect oRectAll(0, 0, lImageWidth, lImageHeight); GP pImage = pPage->get_pixmap(oRectAll, oRectAll); if (NULL != pImage) { BYTE* pBuffer = pBufferDst; for (int j = 0; j < lImageHeight; ++j) { GPixel* pLine = pImage->operator [](j); if ((NULL != pCancel) && (TRUE == *pCancel)) return; for (int i = 0; i < lImageWidth; ++i, pBuffer += 4, ++pLine) { pBuffer[0] = pLine->b; pBuffer[1] = pLine->g; pBuffer[2] = pLine->r; pBuffer[3] = 255; } } return; } GP pBitmap = pPage->get_bitmap(oRectAll, oRectAll, 4); if (NULL != pBitmap) { int nPaletteEntries = pBitmap->get_grays(); DWORD* palette = new DWORD[nPaletteEntries]; // Create palette for the bitmap int color = 0xff0000; int decrement = color / (nPaletteEntries - 1); for (int i = 0; i < nPaletteEntries; ++i) { BYTE level = (BYTE)(color >> 16); palette[i] = (0xFF000000 | level << 16 | level << 8 | level); color -= decrement; } DWORD* pBuffer = (DWORD*)pBufferDst; for (int j = 0; j < lImageHeight; ++j) { BYTE* pLine = pBitmap->operator [](j); if ((NULL != pCancel) && (TRUE == *pCancel)) return; for (int i = 0; i < lImageWidth; ++i, ++pBuffer, ++pLine) { if (*pLine < nPaletteEntries) { *pBuffer = palette[*pLine]; } else { *pBuffer = palette[0]; } } } RELEASEARRAYOBJECTS(palette); } } } XmlUtils::CXmlNode CDjVuFileImplementation::ParseText(GP pPage) { XmlUtils::CXmlNode paragraph; const GP text(DjVuText::create()); const GP text_str(pPage->get_text()); if (text_str) { text->decode(text_str); GUTF8String pageText = text->get_xmlText(pPage->get_height()); XmlUtils::CXmlNode hiddenText; XmlUtils::CXmlNode pageColumn; XmlUtils::CXmlNode region; hiddenText.FromXmlString(NSDjvu::MakeCString(pageText)); hiddenText.GetNode(_T("PAGECOLUMN"), pageColumn); pageColumn.GetNode(_T("REGION"), region); region.GetNode(_T("PARAGRAPH"), paragraph); } return paragraph; } void CDjVuFileImplementation::TextToRenderer(IRenderer* pRenderer, XmlUtils::CXmlNode oTextNode, double dKoef, bool isView) { // Выставим шрифт пустой (чтобы растягивать по всему ректу) pRenderer->put_FontName(L"DjvuEmptyFont"); CString csText = oTextNode.GetXml(); XmlUtils::CXmlNodes oLinesNodes; oTextNode.GetNodes(L"LINE", oLinesNodes); for (int nLineIndex = 0; nLineIndex < oLinesNodes.GetCount(); ++nLineIndex) { XmlUtils::CXmlNode oLineNode; oLinesNodes.GetAt(nLineIndex, oLineNode); XmlUtils::CXmlNodes oWordsNodes; oLineNode.GetNodes(L"WORD", oWordsNodes); for (int nWordIndex = 0; nWordIndex < oWordsNodes.GetCount(); ++nWordIndex) { XmlUtils::CXmlNode oWordNode; oWordsNodes.GetAt(nWordIndex, oWordNode); CString csWord = oWordNode.GetText(); CString csCoords = oWordNode.GetAttribute(L"coords"); double arrCoords[4]; ParseCoords(csCoords.GetBuffer(), arrCoords, dKoef); DrawPageText(pRenderer, arrCoords, csWord.GetBuffer()); } } } void CDjVuFileImplementation::DrawPageText(IRenderer* pRenderer, double* pdCoords, const std::wstring& wsText) { pRenderer->put_FontSize(pdCoords[1] - pdCoords[3]); pRenderer->CommandDrawText(wsText, (float)(pdCoords[0]), (float)(pdCoords[3]), (float)(pdCoords[2] - pdCoords[0]), (float)(pdCoords[1] - pdCoords[3]), (float)(pdCoords[1] - pdCoords[3])); } void CDjVuFileImplementation::ParseCoords(const std::wstring& wsCoordsStr, double* pdCoords, double dKoef) { std::vector vCoords = NSString::Split(wsCoordsStr, L','); if (vCoords.size() >= 4) { for (int nIndex = 0; nIndex < 4; nIndex++) { pdCoords[nIndex] = NSDjvu::GetInteger(vCoords.at(nIndex)) * dKoef; } } }