/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: IBM Corporation
*
* Copyright: 2008 by IBM Corporation
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
/**
* @file
* For LWP filter architecture prototype
*/
#include <memory>
#include <string_view>
#include <lwpfilehdr.hxx>
#include "lwpgrfobj.hxx"
#include "lwpsdwfileloader.hxx"
#include "bento.hxx"
#include <lwpglobalmgr.hxx>
#include <o3tl/numeric.hxx>
#include <o3tl/sprintf.hxx>
#include <rtl/string.hxx>
#include "lwpframelayout.hxx"
#include <xfilter/xfframe.hxx>
#include <xfilter/xfimage.hxx>
#include <xfilter/xfimagestyle.hxx>
#include <xfilter/xfstylemanager.hxx>
#include <xfilter/xfparagraph.hxx>
#include <xfilter/xfannotation.hxx>
//For chart
#include <string.h>
#include <osl/thread.h>
#include <sal/log.hxx>
#define EF_NONE 0x0000
#define EF_ODMA 0x0002
LwpGraphicObject::LwpGraphicObject(LwpObjectHeader const &objHdr, LwpSvStream* pStrm)
: LwpGraphicOleObject(objHdr, pStrm)
, m_nCachedBaseLine(0)
, m_bIsLinked(0)
, m_bCompressed(0)
{
}
LwpGraphicObject::~LwpGraphicObject()
{
}
void LwpGraphicObject::Read()
{
LwpGraphicOleObject::Read();
m_pObjStrm->QuickReaduInt16(); //disksize
sal_uInt16 strsize = m_pObjStrm->QuickReaduInt16();
if (strsize<AFID_MAX_FILE_FORMAT_SIZE)
{
m_pObjStrm->QuickRead(m_sDataFormat,strsize);
m_sDataFormat[strsize] = '\0';
}
sal_uInt32 nServerContextSize = m_pObjStrm->QuickReaduInt32();
if (nServerContextSize > 0)
{
sal_uInt16 nMaxPossibleSize = m_pObjStrm->remainingSize();
if (nServerContextSize > nMaxPossibleSize)
{
SAL_WARN("lwp", "stream too short for claimed no of records");
nServerContextSize = nMaxPossibleSize;
}
std::vector<unsigned char> aServerContext(nServerContextSize);
m_pObjStrm->QuickRead(aServerContext.data(), static_cast<sal_uInt16>(nServerContextSize));
if (nServerContextSize > 44)
{
m_aIPData.nBrightness = aServerContext[14];
m_aIPData.nContrast = aServerContext[19];
m_aIPData.nEdgeEnhancement = aServerContext[24];
m_aIPData.nSmoothing = aServerContext[29];
m_aIPData.bInvertImage = (aServerContext[34] == 0x01);
m_aIPData.bAutoContrast = (aServerContext[44] == 0x00);
}
}
m_pObjStrm->QuickReaduInt16(); //disksize
strsize = m_pObjStrm->QuickReaduInt16();
if (strsize<AFID_MAX_FILE_FORMAT_SIZE)
{
m_pObjStrm->QuickRead(m_sServerContextFormat,strsize);
m_sServerContextFormat[strsize] = '\0';
}
if (nServerContextSize == 0)
{
if (strcmp(reinterpret_cast<char *>(m_sServerContextFormat), ".cht") == 0 &&
strcmp(reinterpret_cast<char *>(m_sDataFormat), ".sdw") == 0)
{
strcpy(reinterpret_cast<char *>(m_sServerContextFormat), ".lch");
strcpy(reinterpret_cast<char *>(m_sDataFormat), ".lch");
}
}
m_nCachedBaseLine = m_pObjStrm->QuickReadInt32();
m_bIsLinked = m_pObjStrm->QuickReadInt16();
if (m_bIsLinked)
{
m_LinkedFilePath = m_pObjStrm->QuickReadStringPtr();
sal_uInt32 nFilterContextSize = m_pObjStrm->QuickReaduInt32();
if (nFilterContextSize > 0)
{
sal_uInt16 nMaxPossibleSize = m_pObjStrm->remainingSize();
if (nFilterContextSize > nMaxPossibleSize)
{
SAL_WARN("lwp", "stream too short for claimed no of records");
nFilterContextSize = nMaxPossibleSize;
}
std::vector<unsigned char> aFilterContext(nFilterContextSize);
m_pObjStrm->QuickRead(aFilterContext.data(), static_cast<sal_uInt16>(nFilterContextSize));
}
if (LwpFileHeader::m_nFileRevision >= 0x000b)
{
// read external file object stuff
sal_uInt16 type = m_pObjStrm->QuickReaduInt16();
if ((EF_ODMA != type) && (EF_NONE != type)) // don't know about this
{
sal_uInt32 size = m_pObjStrm->QuickReaduInt32();
m_pObjStrm->SeekRel(static_cast<sal_uInt16>(size));
}
// else no external file object
}
}
if (LwpFileHeader::m_nFileRevision >= 0x000b)
{
m_bCompressed = m_pObjStrm->QuickReadInt16();
m_Cache.LinkedFileSize = m_pObjStrm->QuickReaduInt32();
m_Cache.LinkedFileTime = m_pObjStrm->QuickReaduInt32();
m_Cache.Width = m_pObjStrm->QuickReadInt32();
m_Cache.Height = m_pObjStrm->QuickReadInt32();
}
if(LwpFileHeader::m_nFileRevision >= 0x000c)
{
m_WatermarkName = m_pObjStrm->QuickReadStringPtr();
}
}
void LwpGraphicObject::XFConvert (XFContentContainer* pCont)
{
if (m_sServerContextFormat[1]=='s'&&m_sServerContextFormat[2]=='d'&&m_sServerContextFormat[3]=='w')
{
for (auto const& vXFDrawObject : m_vXFDrawObjects)
{
pCont->Add(vXFDrawObject.get());
}
}
else if (IsGrafFormatValid() && !m_vXFDrawObjects.empty())
{
XFImage* pImage = static_cast<XFImage*>(m_vXFDrawObjects.front().get());
if (m_bIsLinked)
{
OUString fileURL = LwpTools::convertToFileUrl(OUStringToOString(m_LinkedFilePath, osl_getThreadTextEncoding()));
pImage->SetFileURL(fileURL);
}
else
{
std::vector<sal_uInt8> aGrafData = GetRawGrafData();
pImage->SetImageData(aGrafData.data(), aGrafData.size());
}
pCont->Add(pImage);
}
else if(m_sServerContextFormat[1]=='t'&&m_sServerContextFormat[2]=='e'&&m_sServerContextFormat[3]=='x')
{
XFConvertEquation(pCont);
}
}
/**
* @descr judge if the graphic format is what we can support: bmp, jpg, wmf, gif, tgf(tif). other format will be filtered to
* these formats by Word Pro.
* @return sal_True if yes sal_False if not.
*/
bool LwpGraphicObject::IsGrafFormatValid() const
{
return (m_sServerContextFormat[1]=='b'&& m_sServerContextFormat[2]=='m' && m_sServerContextFormat[3]=='p')
|| (m_sServerContextFormat[1]=='j' && m_sServerContextFormat[2]=='p' && m_sServerContextFormat[3]=='g')
|| (m_sServerContextFormat[1]=='w' && m_sServerContextFormat[2]=='m' && m_sServerContextFormat[3]=='f')
|| (m_sServerContextFormat[1]=='g' && m_sServerContextFormat[2]=='i' && m_sServerContextFormat[3]=='f')
|| (m_sServerContextFormat[1]=='t' && m_sServerContextFormat[2]=='g' && m_sServerContextFormat[3]=='f')
|| (m_sServerContextFormat[1]=='p' && m_sServerContextFormat[2]=='n' && m_sServerContextFormat[3]=='g')
|| (m_sServerContextFormat[1]=='e' && m_sServerContextFormat[2]=='p' && m_sServerContextFormat[3]=='s');
}
/**
* @descr create drawing object and image object.
*/
void LwpGraphicObject::RegisterStyle()
{
if (m_sServerContextFormat[1]=='s'&&m_sServerContextFormat[2]=='d'&&m_sServerContextFormat[3]=='w')
{
CreateDrawObjects();
}
// test codes for importing pictures
else if(IsGrafFormatValid())
{
CreateGrafObject();
}
if (m_sServerContextFormat[1]=='l'&&m_sServerContextFormat[2]=='c'&&m_sServerContextFormat[3]=='h')
{
rtl::Reference<LwpVirtualLayout> xMyLayout(GetLayout(nullptr));
if (xMyLayout.is() && xMyLayout->IsFrame())
{
std::unique_ptr<XFFrameStyle> pXFFrameStyle(new XFFrameStyle());
pXFFrameStyle->SetXPosType(enumXFFrameXPosFromLeft, enumXFFrameXRelFrame);
pXFFrameStyle->SetYPosType(enumXFFrameYPosFromTop, enumXFFrameYRelPara);
XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
m_strStyleName = pXFStyleManager->AddStyle(std::move(pXFFrameStyle)).m_pStyle->GetStyleName();
}
}
}
/**
* @descr create drawing object.
*/
void LwpGraphicObject::CreateDrawObjects()
{
// if small file, use the compressed stream for BENTO
LwpSvStream* pStream = m_pStrm->GetCompressedStream() ? m_pStrm->GetCompressedStream(): m_pStrm;
std::unique_ptr<OpenStormBento::LtcBenContainer> pBentoContainer;
OpenStormBento::BenError ulRet = OpenStormBento::BenOpenContainer(pStream, &pBentoContainer);
if (ulRet != OpenStormBento::BenErr_OK)
return;
// get graphic object's bento object name
LwpObjectID& rMyID = GetObjectID();
std::string aGrfObjName;
GetBentoNamebyID(rMyID, aGrfObjName);
// get bento stream by the name
std::vector<sal_uInt8> aData = pBentoContainer->GetGraphicData(aGrfObjName.c_str());
if (!aData.empty())
{
SvMemoryStream aDrawObjStream(aData.data(), aData.size(), StreamMode::READ);
LwpSdwFileLoader fileLoader(&aDrawObjStream, this);
fileLoader.CreateDrawObjects(&m_vXFDrawObjects);
}
}
/**
* @descr create drawing object.
*/
void LwpGraphicObject::GetBentoNamebyID(LwpObjectID const & rMyID, std::string& rName)
{
sal_uInt16 nHigh = rMyID.GetHigh();
sal_uInt32 nLow = rMyID.GetLow();
char pTempStr[32];
rName = std::string("Gr");
o3tl::sprintf(pTempStr, "%X,%" SAL_PRIXUINT32, nHigh, nLow);
rName.append(pTempStr);
}
/**
* @descr get the image data read from bento stream according to the VO_GRAPHIC ID.
* @return the image data.
*/
std::vector<sal_uInt8> LwpGraphicObject::GetRawGrafData()
{
std::vector<sal_uInt8> aGrafData;
// create graphic object
// if small file, use the compressed stream for BENTO
LwpSvStream* pStream = m_pStrm->GetCompressedStream() ? m_pStrm->GetCompressedStream(): m_pStrm;
std::unique_ptr<OpenStormBento::LtcBenContainer> pBentoContainer;
{
OpenStormBento::BenError ulRet = OpenStormBento::BenOpenContainer(pStream, &pBentoContainer);
if (ulRet != OpenStormBento::BenErr_OK)
return aGrafData;
}
// get graphic object's bento object name
LwpObjectID& rMyID = GetObjectID();
std::string aGrfObjName;
GetBentoNamebyID(rMyID, aGrfObjName);
// get bento stream by the name and read image data
return pBentoContainer->GetGraphicData(aGrfObjName.c_str());
}
/**
* @descr get the image data (only -D data) read from bento stream according to the VO_GRAPHIC ID.
* @param pGrafData the array to store the image data. the pointer need to be deleted outside.
* @return the length of the image data.
*/
sal_uInt32 LwpGraphicObject::GetGrafData(std::unique_ptr<sal_uInt8[]>& pGrafData)
{
// create graphic object
// if small file, use the compressed stream for BENTO
LwpSvStream* pStream = m_pStrm->GetCompressedStream() ? m_pStrm->GetCompressedStream(): m_pStrm;
std::unique_ptr<OpenStormBento::LtcBenContainer> pBentoContainer;
OpenStormBento::BenError ulRet = OpenStormBento::BenOpenContainer(pStream, &pBentoContainer);
if (ulRet != OpenStormBento::BenErr_OK)
return 0;
SvStream* pGrafStream = nullptr;
// get graphic object's bento object name
LwpObjectID& rMyID = GetObjectID();
std::string aGrfObjName;
GetBentoNamebyID(rMyID, aGrfObjName);
OString sDName=OString::Concat(std::string_view(aGrfObjName)) + "-D";
// get bento stream by the name
pGrafStream = pBentoContainer->FindValueStreamWithPropertyName(sDName.getStr());
std::unique_ptr<SvMemoryStream> pMemGrafStream(static_cast<SvMemoryStream*>(pGrafStream));
if (pMemGrafStream)
{
// read image data
sal_uInt32 nDataLen = pGrafStream->TellEnd();
pGrafData.reset(new sal_uInt8 [nDataLen]);
pMemGrafStream->ReadBytes(pGrafData.get(), nDataLen);
return nDataLen;
}
return 0;
}
/**
* @descr create xf-image object and save it in the container: m_vXFDrawObjects.
*/
void LwpGraphicObject::CreateGrafObject()
{
rtl::Reference<XFImage> pImage = new XFImage();
// set image processing styles
std::unique_ptr<XFImageStyle> xImageStyle(new XFImageStyle);
if (m_sServerContextFormat[1]!='w' || m_sServerContextFormat[2]!='m' || m_sServerContextFormat[3]!='f')
{
if (m_aIPData.nBrightness != 50)
{
sal_Int32 nSODCBrightness = static_cast<sal_Int32>(m_aIPData.nBrightness)*2 - 100;
xImageStyle->SetBrightness(nSODCBrightness);
}
if (m_aIPData.nContrast != 50)
{
sal_Int32 nSODCContrast = static_cast<sal_Int32>(80 - static_cast<double>(m_aIPData.nContrast)*1.6);
xImageStyle->SetContrast(nSODCContrast);
}
}
// set scale and crop styles
LwpAssociatedLayouts& rLayoutWithMe = GetLayoutsWithMe();
LwpFrameLayout* pMyFrameLayout =
static_cast<LwpFrameLayout*>(rLayoutWithMe.GetOnlyLayout().obj(VO_FRAMELAYOUT).get());
if (pMyFrameLayout)
{
LwpLayoutScale* pMyScale = pMyFrameLayout->GetLayoutScale();
LwpLayoutGeometry* pFrameGeo = pMyFrameLayout->GetGeometry();
// original image size
double fOrgGrafWidth = LwpTools::ConvertFromTwips(m_Cache.Width);
double fOrgGrafHeight = LwpTools::ConvertFromTwips(m_Cache.Height);
// get margin values
double fLeftMargin = pMyFrameLayout->GetMarginsValue(MARGIN_LEFT);
double fRightMargin = pMyFrameLayout->GetMarginsValue(MARGIN_RIGHT);
double fTopMargin = pMyFrameLayout->GetMarginsValue(MARGIN_TOP);
double fBottomMargin = pMyFrameLayout->GetMarginsValue(MARGIN_BOTTOM);
if (pMyScale && pFrameGeo)
{
if (fOrgGrafHeight == 0.0 || fOrgGrafWidth == 0.0)
throw o3tl::divide_by_zero();
// frame size
double fFrameWidth = LwpTools::ConvertFromUnits(pFrameGeo->GetWidth());
double fFrameHeight = LwpTools::ConvertFromUnits(pFrameGeo->GetHeight());
// calculate the displayed size of the frame
double fDisFrameWidth = fFrameWidth - (fLeftMargin+fRightMargin);
double fDisFrameHeight = fFrameHeight - (fTopMargin+fBottomMargin);
// scaled image size
double fSclGrafWidth = fOrgGrafWidth;
double fSclGrafHeight = fOrgGrafHeight;
// get scale mode
sal_uInt16 nScalemode = pMyScale->GetScaleMode();
if (nScalemode & LwpLayoutScale::CUSTOM)
{
fSclGrafWidth = LwpTools::ConvertFromUnits(pMyScale->GetScaleWidth());
fSclGrafHeight = LwpTools::ConvertFromUnits(pMyScale->GetScaleHeight());
}
else if (nScalemode & LwpLayoutScale::PERCENTAGE)
{
double fScalePercentage = static_cast<double>(pMyScale->GetScalePercentage()) / 1000;
fSclGrafWidth = fScalePercentage * fOrgGrafWidth;
fSclGrafHeight = fScalePercentage * fOrgGrafHeight;
}
else if (nScalemode & LwpLayoutScale::FIT_IN_FRAME)
{
if (pMyFrameLayout->IsFitGraphic())
{
fSclGrafWidth = fOrgGrafWidth;
fSclGrafHeight = fOrgGrafHeight;
}
else if (nScalemode & LwpLayoutScale::MAINTAIN_ASPECT_RATIO)
{
if (fDisFrameHeight == 0.0)
throw o3tl::divide_by_zero();
if (fOrgGrafWidth/fOrgGrafHeight >= fDisFrameWidth/fDisFrameHeight)
{
fSclGrafWidth = fDisFrameWidth;
fSclGrafHeight = (fDisFrameWidth/fOrgGrafWidth) * fOrgGrafHeight;
}
else
{
fSclGrafHeight = fDisFrameHeight;
fSclGrafWidth = (fDisFrameHeight/fOrgGrafHeight) * fOrgGrafWidth;
}
}
else
{
fSclGrafWidth = fDisFrameWidth;
fSclGrafHeight = fDisFrameHeight;
}
}
// scaled ratio
double fXRatio = fSclGrafWidth / fOrgGrafWidth;
double fYRatio = fSclGrafHeight / fOrgGrafHeight;
// set image to scaled size.
pImage->SetWidth(fSclGrafWidth);
pImage->SetHeight(fSclGrafHeight);
// placement:centered or tiled. tiled style is not supported so it's processed together with centered.
if (pMyFrameLayout->GetScaleCenter() || pMyFrameLayout->GetScaleTile())
{
// set center alignment
xImageStyle->SetXPosType(enumXFFrameXPosCenter, enumXFFrameXRelFrame);
xImageStyle->SetYPosType(enumXFFrameYPosMiddle, enumXFFrameYRelFrame);
// need horizontal crop?
double fClipWidth = 0;
double fClipHeight = 0;
bool sal_bCropped = false;
if (fSclGrafWidth > fDisFrameWidth)
{
if (fXRatio == 0.0)
throw o3tl::divide_by_zero();
fClipWidth = (fSclGrafWidth-fDisFrameWidth ) / 2 / fXRatio;
sal_bCropped = true;
}
// need vertical crop?
if (fSclGrafHeight > fDisFrameHeight)
{
if (fYRatio == 0.0)
throw o3tl::divide_by_zero();
fClipHeight = (fSclGrafHeight-fDisFrameHeight ) / 2 / fYRatio;
sal_bCropped = true;
}
if (sal_bCropped)
{
xImageStyle->SetClip(fClipWidth, fClipWidth, fClipHeight, fClipHeight);
pImage->SetWidth(fDisFrameWidth);
pImage->SetHeight(fDisFrameHeight);
}
}
// placement:automatic
else
{
// set left-top alignment
xImageStyle->SetYPosType(enumXFFrameYPosFromTop, enumXFFrameYRelFrame);
xImageStyle->SetXPosType(enumXFFrameXPosFromLeft, enumXFFrameXRelFrame);
// get image position offset
LwpPoint& rOffset = pMyScale->GetOffset();
double fOffsetX = LwpTools::ConvertFromUnits(rOffset.GetX());
double fOffsetY = LwpTools::ConvertFromUnits(rOffset.GetY());
struct LwpRect
{
double fLeft;
double fRight;
double fTop;
double fBottom;
LwpRect()
{
fLeft = 0.00;
fRight = 0.00;
fTop = 0.00;
fBottom = 0.00;
}
LwpRect(double fL, double fR, double fT, double fB)
{
fLeft = fL;
fRight = fR;
fTop = fT;
fBottom = fB;
}
};
LwpRect aFrameRect(-fOffsetX, (fDisFrameWidth-fOffsetX), (-fOffsetY), (fDisFrameHeight-fOffsetY));
LwpRect aImageRect(0, fSclGrafWidth, 0, fSclGrafHeight);
if (aFrameRect.fRight <= aImageRect.fLeft || aFrameRect.fLeft >= aImageRect.fRight
||aFrameRect.fBottom <= aImageRect.fTop|| aFrameRect.fTop >= aImageRect.fBottom)
{
// display blank
}
else// need cropped
{
// horizontal crop
LwpRect aCropRect;
if (aFrameRect.fLeft > aImageRect.fLeft)
{
aCropRect.fLeft = (aFrameRect.fLeft - aImageRect.fLeft) / fXRatio;
}
if (aFrameRect.fRight < aImageRect.fRight)
{
aCropRect.fRight = (aImageRect.fRight - aFrameRect.fRight) / fXRatio;
}
// vertical crop
if (aFrameRect.fTop > aImageRect.fTop)
{
aCropRect.fTop = (aFrameRect.fTop - aImageRect.fTop) / fYRatio;
}
if (aFrameRect.fBottom < aImageRect.fBottom)
{
aCropRect.fBottom = (aImageRect.fBottom - aFrameRect.fBottom) / fYRatio;
}
xImageStyle->SetClip(aCropRect.fLeft, aCropRect.fRight, aCropRect.fTop, aCropRect.fBottom);
double fPicWidth = fSclGrafWidth - (aCropRect.fLeft+aCropRect.fRight)*fXRatio;
double fPicHeight = fSclGrafHeight- (aCropRect.fTop+aCropRect.fBottom)*fYRatio;
double fX = fOffsetX > 0 ? fOffsetX : 0.00;
double fY = fOffsetY > 0 ? fOffsetY : 0.00;
pImage->SetPosition((fX+fLeftMargin), (fY+fTopMargin), fPicWidth, fPicHeight);
}
}
}
}
// set style for the image
XFStyleManager* pXFStyleManager = LwpGlobalMgr::GetInstance()->GetXFStyleManager();
pImage->SetStyleName(pXFStyleManager->AddStyle(std::move(xImageStyle)).m_pStyle->GetStyleName());
// set anchor to frame
pImage->SetAnchorType(enumXFAnchorFrame);
// set object name
LwpAtomHolder& rHolder = GetName();
if ( !rHolder.str().isEmpty() )
{
pImage->SetName(rHolder.str());
}
// insert image object into array
m_vXFDrawObjects.emplace_back(pImage.get());
}
/**
* @descr Reserve the equation text in a note in the context.
*/
void LwpGraphicObject::XFConvertEquation(XFContentContainer * pCont)
{
std::unique_ptr<sal_uInt8[]> pGrafData;
sal_uInt32 nDataLen = GetGrafData(pGrafData);
if(!pGrafData)
return;
//convert equation
XFParagraph* pXFPara = new XFParagraph;
pXFPara->Add(u"Formula:"_ustr);
//add notes
XFAnnotation* pXFNote = new XFAnnotation;
//add equation to comment notes
XFParagraph* pXFNotePara = new XFParagraph;
//equation header text: Times New Roman,
// 18,12,0,0,0,0,0.
// .TCIformat{2}
//total head length = 45
bool bOk = true;
sal_uInt32 nBegin = 45;
sal_uInt32 nEnd = 0;
if (nDataLen >= 1)
nEnd = nDataLen - 1;
else
bOk = false;
if (bOk && pGrafData[nEnd] == '$' && nEnd > 0 && pGrafData[nEnd-1] != '\\')
{
//equation body is contained by '$';
nBegin++;
nEnd--;
}
bOk &= nEnd >= nBegin;
if (bOk)
{
std::unique_ptr<sal_uInt8[]> pEquData( new sal_uInt8[nEnd - nBegin + 1] );
for(sal_uInt32 nIndex = 0; nIndex < nEnd - nBegin +1 ; nIndex++)
{
pEquData[nIndex] = pGrafData[nBegin + nIndex];
}
pXFNotePara->Add(OUString(reinterpret_cast<char*>(pEquData.get()), (nEnd - nBegin + 1), osl_getThreadTextEncoding()));
}
pXFNote->Add(pXFNotePara);
pXFPara->Add(pXFNote);
pCont->Add(pXFPara);
}
void LwpGraphicObject::GetGrafOrgSize(double & rWidth, double & rHeight)
{
// original image size
rWidth = LwpTools::ConvertFromTwips(m_Cache.Width);
rHeight = LwpTools::ConvertFromTwips(m_Cache.Height);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V781 The value of the 'nEnd' index is checked after it was used. Perhaps there is a mistake in program logic.