[Libreoffice-commits] core.git: include/vcl vcl/source
Miklos Vajna
vmiklos at collabora.co.uk
Thu Feb 23 15:37:01 UTC 2017
include/vcl/pdfwriter.hxx | 2
vcl/source/gdi/pdfextoutdevdata.cxx | 4
vcl/source/gdi/pdfwriter.cxx | 4
vcl/source/gdi/pdfwriter_impl.cxx | 203 +++++++++++++++++-------------------
vcl/source/gdi/pdfwriter_impl.hxx | 42 +++++--
vcl/source/gdi/pdfwriter_impl2.cxx | 2
6 files changed, 137 insertions(+), 120 deletions(-)
New commits:
commit 78e25558e86188314b9b72048b8ddca18697cb86
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date: Thu Feb 23 16:35:15 2017 +0100
tdf#106059 PDF export: create a reference XObject for JPG images with PDF data
In case the bitmap is large enough, the bitmap for the PDF image is a
JPG one, not a PNG one. Handle this case as well.
Also stop compressing the PDF data: Adobe Acrobat gets confused when the
second bugdoc is compressed and it doesn't provide much as most of a PDF
is already compressed anyway.
The rest is just refactoring to decouple the reference XObject code from
PNG, to be able to use it for JPG as well.
Change-Id: I5314a39b0f6d8c6493ecb36a0c588c895f5a70ee
diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx
index 6beeea1..aaacbce 100644
--- a/include/vcl/pdfwriter.hxx
+++ b/include/vcl/pdfwriter.hxx
@@ -868,7 +868,7 @@ The following structure describes the permissions used in PDF security
the same pixel size as the image and
be either 1 bit black&white or 8 bit grey
*/
- void DrawJPGBitmap( SvStream& rJPGData, bool bIsTrueColor, const Size& rSrcSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask );
+ void DrawJPGBitmap( SvStream& rJPGData, bool bIsTrueColor, const Size& rSrcSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask, const Graphic& rGraphic );
/** Create a new named destination to be used in a link from another PDF document
diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx b/vcl/source/gdi/pdfextoutdevdata.cxx
index 10b5a31..6defb59 100644
--- a/vcl/source/gdi/pdfextoutdevdata.cxx
+++ b/vcl/source/gdi/pdfextoutdevdata.cxx
@@ -412,7 +412,7 @@ bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAc
}
else if ((eType == GfxLinkType::NativePng || eType == GfxLinkType::NativePdf) && mParaRects.size() >= 2)
{
- if ( rOutDevData.HasAdequateCompression(rGraphic, mParaRects[0], mParaRects[1]) )
+ if ( rOutDevData.HasAdequateCompression(rGraphic, mParaRects[0], mParaRects[1]) || eType == GfxLinkType::NativePdf )
mCurrentGraphic = rGraphic;
}
}
@@ -465,7 +465,7 @@ bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAc
if( pData && nBytes )
{
aTmp.WriteBytes( pData, nBytes );
- rWriter.DrawJPGBitmap( aTmp, aGraphic.GetBitmap().GetBitCount() > 8, aGraphic.GetSizePixel(), aOutputRect, aMask );
+ rWriter.DrawJPGBitmap( aTmp, aGraphic.GetBitmap().GetBitCount() > 8, aGraphic.GetSizePixel(), aOutputRect, aMask, aGraphic );
}
if ( bClippingNeeded )
diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx
index c17c3f6..bd204cf 100644
--- a/vcl/source/gdi/pdfwriter.cxx
+++ b/vcl/source/gdi/pdfwriter.cxx
@@ -334,9 +334,9 @@ void PDFWriter::SetTextAlign( ::TextAlign eAlign )
xImplementation->setTextAlign( eAlign );
}
-void PDFWriter::DrawJPGBitmap( SvStream& rStreamData, bool bIsTrueColor, const Size& rSrcSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask )
+void PDFWriter::DrawJPGBitmap( SvStream& rStreamData, bool bIsTrueColor, const Size& rSrcSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask, const Graphic& rGraphic )
{
- xImplementation->drawJPGBitmap( rStreamData, bIsTrueColor, rSrcSizePixel, rTargetArea, rMask );
+ xImplementation->drawJPGBitmap( rStreamData, bIsTrueColor, rSrcSizePixel, rTargetArea, rMask, rGraphic );
}
sal_Int32 PDFWriter::CreateLink( const Rectangle& rRect, sal_Int32 nPageNr )
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 3fe1bf4..054b7a3 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -4982,25 +4982,16 @@ bool PDFWriterImpl::emitEmbeddedFiles()
if (!updateObject(rEmbeddedFile.m_nObject))
continue;
- SvMemoryStream aUncompressed;
- aUncompressed.WriteBytes(rEmbeddedFile.m_aData.getArray(), rEmbeddedFile.m_aData.getLength());
- aUncompressed.Seek(0);
- SvMemoryStream aCompressed;
- ZCodec aZCodec;
- aZCodec.BeginCompression();
- aZCodec.Compress(aUncompressed, aCompressed);
- aZCodec.EndCompression();
-
OStringBuffer aLine;
aLine.append(rEmbeddedFile.m_nObject);
aLine.append(" 0 obj\n");
- aLine.append("<< /Type /EmbeddedFile /Filter /FlateDecode /Length ");
- aLine.append(static_cast<sal_Int64>(aCompressed.GetSize()));
+ aLine.append("<< /Type /EmbeddedFile /Length ");
+ aLine.append(static_cast<sal_Int64>(rEmbeddedFile.m_aData.getLength()));
aLine.append(" >>\nstream\n");
CHECK_RETURN(writeBuffer(aLine.getStr(), aLine.getLength()));
aLine.setLength(0);
- CHECK_RETURN(writeBuffer(aCompressed.GetData(), aCompressed.GetSize()));
+ CHECK_RETURN(writeBuffer(rEmbeddedFile.m_aData.getArray(), rEmbeddedFile.m_aData.getLength()));
aLine.append("\nendstream\nendobj\n\n");
CHECK_RETURN(writeBuffer(aLine.getStr(), aLine.getLength()));
@@ -10870,6 +10861,75 @@ void PDFWriterImpl::writeJPG( JPGEmit& rObject )
aEmit.m_aBitmap = BitmapEx( rObject.m_aMask, AlphaMask( rObject.m_aMask ) );
writeBitmapObject( aEmit, true );
}
+
+ writeReferenceXObject(rObject.m_aReferenceXObject);
+}
+
+void PDFWriterImpl::writeReferenceXObject(ReferenceXObjectEmit& rEmit)
+{
+ if (rEmit.m_nFormObject <= 0 || rEmit.m_nEmbeddedObject <= 0)
+ return;
+
+ OStringBuffer aLine;
+ if (!updateObject(rEmit.m_nFormObject))
+ return;
+
+ // Count /Matrix and /BBox.
+ // vcl::ImportPDF() works with 96 DPI so use the same values here, too.
+ sal_Int32 nOldDPIX = getReferenceDevice()->GetDPIX();
+ getReferenceDevice()->SetDPIX(96);
+ sal_Int32 nOldDPIY = getReferenceDevice()->GetDPIY();
+ getReferenceDevice()->SetDPIY(96);
+ Size aSize = getReferenceDevice()->PixelToLogic(rEmit.m_aPixelSize, MapMode(m_aMapMode.GetMapUnit()));
+ getReferenceDevice()->SetDPIX(nOldDPIX);
+ getReferenceDevice()->SetDPIY(nOldDPIY);
+ double fScaleX = 1.0 / aSize.Width();
+ double fScaleY = 1.0 / aSize.Height();
+
+ // Now have all the info to write the form XObject.
+ aLine.append(rEmit.m_nFormObject);
+ aLine.append(" 0 obj\n");
+ aLine.append("<< /Type /XObject");
+ aLine.append(" /Subtype /Form");
+ aLine.append(" /Resources << /XObject<</Im");
+ aLine.append(rEmit.m_nBitmapObject);
+ aLine.append(" ");
+ aLine.append(rEmit.m_nBitmapObject);
+ aLine.append(" 0 R>> >>");
+ aLine.append(" /Matrix [ ");
+ appendDouble(fScaleX, aLine);
+ aLine.append(" 0 0 ");
+ appendDouble(fScaleY, aLine);
+ aLine.append(" 0 0 ]");
+ aLine.append(" /BBox [ 0 0 ");
+ aLine.append(aSize.Width());
+ aLine.append(" ");
+ aLine.append(aSize.Height());
+ aLine.append(" ]\n");
+
+ // Write the reference dictionary.
+ aLine.append("/Ref<< /F << /Type /Filespec /F (<embedded file>) /EF << /F ");
+ aLine.append(rEmit.m_nEmbeddedObject);
+ aLine.append(" 0 R >> >> /Page 0 >>\n");
+
+ aLine.append("/Length ");
+
+ OStringBuffer aStream;
+ aStream.append("q ");
+ aStream.append(aSize.Width());
+ aStream.append(" 0 0 ");
+ aStream.append(aSize.Height());
+ aStream.append(" 0 0 cm\n");
+ aStream.append("/Im");
+ aStream.append(rEmit.m_nBitmapObject);
+ aStream.append(" Do\n");
+ aStream.append("Q");
+ aLine.append(aStream.getLength());
+
+ aLine.append(">>\nstream\n");
+ aLine.append(aStream.getStr());
+ aLine.append("\nendstream\nendobj\n\n");
+ CHECK_RETURN2(writeBuffer(aLine.getStr(), aLine.getLength()));
}
namespace
@@ -11185,75 +11245,28 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
return writeBitmapObject( aEmit, true );
}
- // Write the form XObject proxy for the image.
- if (rObject.m_nFormObject > 0 && rObject.m_nEmbeddedObject > 0)
- {
- aLine.setLength(0);
- if (!updateObject(rObject.m_nFormObject))
- return false;
-
- // Count /Matrix and /BBox.
- // vcl::ImportPDF() works with 96 DPI so use the same values here, too.
- sal_Int32 nOldDPIX = getReferenceDevice()->GetDPIX();
- getReferenceDevice()->SetDPIX(96);
- sal_Int32 nOldDPIY = getReferenceDevice()->GetDPIY();
- getReferenceDevice()->SetDPIY(96);
- Size aSize = getReferenceDevice()->PixelToLogic(rObject.m_aBitmap.GetPrefSize(), MapMode(m_aMapMode.GetMapUnit()));
- getReferenceDevice()->SetDPIX(nOldDPIX);
- getReferenceDevice()->SetDPIY(nOldDPIY);
- double fScaleX = 1.0 / aSize.Width();
- double fScaleY = 1.0 / aSize.Height();
-
- // Now have all the info to write the form XObject.
- aLine.append(rObject.m_nFormObject);
- aLine.append(" 0 obj\n");
- aLine.append("<< /Type /XObject");
- aLine.append(" /Subtype /Form");
- aLine.append(" /Resources << /XObject<</Im");
- aLine.append(rObject.m_nObject);
- aLine.append(" ");
- aLine.append(rObject.m_nObject);
- aLine.append(" 0 R>> >>");
- aLine.append(" /Matrix [ ");
- appendDouble(fScaleX, aLine);
- aLine.append(" 0 0 ");
- appendDouble(fScaleY, aLine);
- aLine.append(" 0 0 ]");
- aLine.append(" /BBox [ 0 0 ");
- aLine.append(aSize.Width());
- aLine.append(" ");
- aLine.append(aSize.Height());
- aLine.append(" ]\n");
-
- // Write the reference dictionary.
- aLine.append("/Ref<< /F << /Type /Filespec /F (<embedded file>) /EF << /F ");
- aLine.append(rObject.m_nEmbeddedObject);
- aLine.append(" 0 R >> >> /Page 0 >>\n");
-
- aLine.append("/Length ");
-
- OStringBuffer aStream;
- aStream.append("q ");
- aStream.append(aSize.Width());
- aStream.append(" 0 0 ");
- aStream.append(aSize.Height());
- aStream.append(" 0 0 cm\n");
- aStream.append("/Im");
- aStream.append(rObject.m_nObject);
- aStream.append(" Do\n");
- aStream.append("Q");
- aLine.append(aStream.getLength());
-
- aLine.append(">>\nstream\n");
- aLine.append(aStream.getStr());
- aLine.append("\nendstream\nendobj\n\n");
- CHECK_RETURN(writeBuffer(aLine.getStr(), aLine.getLength()));
- }
+ writeReferenceXObject(rObject.m_aReferenceXObject);
return true;
}
-void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const Size& rSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask )
+void PDFWriterImpl::createEmbeddedFile(const Graphic& rGraphic, ReferenceXObjectEmit& rEmit, sal_Int32 nBitmapObject)
+{
+ if (!rGraphic.getPdfData().hasElements())
+ return;
+
+ // Store the original PDF data as an embedded file.
+ m_aEmbeddedFiles.push_back(PDFEmbeddedFile());
+ m_aEmbeddedFiles.back().m_nObject = createObject();
+ m_aEmbeddedFiles.back().m_aData = rGraphic.getPdfData();
+
+ rEmit.m_nFormObject = createObject();
+ rEmit.m_nEmbeddedObject = m_aEmbeddedFiles.back().m_nObject;
+ rEmit.m_nBitmapObject = nBitmapObject;
+ rEmit.m_aPixelSize = rGraphic.GetBitmap().GetPrefSize();
+}
+
+void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const Size& rSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask, const Graphic& rGraphic )
{
MARK( "drawJPGBitmap" );
@@ -11309,6 +11322,7 @@ void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const
rEmit.m_bTrueColor = bIsTrueColor;
if( !! rMask && rMask.GetSizePixel() == rSizePixel )
rEmit.m_aMask = rMask;
+ createEmbeddedFile(rGraphic, rEmit.m_aReferenceXObject, rEmit.m_nObject);
it = m_aJPGs.begin();
}
@@ -11324,7 +11338,8 @@ void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const
aLine.append( ' ' );
m_aPages.back().appendPoint( rTargetArea.BottomLeft(), aLine );
aLine.append( " cm\n/Im" );
- aLine.append( it->m_nObject );
+ sal_Int32 nObject = it->m_aReferenceXObject.getObject();
+ aLine.append(nObject);
aLine.append( " Do Q\n" );
if( nCheckWidth == 0 || nCheckHeight == 0 )
{
@@ -11338,8 +11353,8 @@ void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const
OStringBuffer aObjName( 16 );
aObjName.append( "Im" );
- aObjName.append( it->m_nObject );
- pushResource( ResXObject, aObjName.makeStringAndClear(), it->m_nObject );
+ aObjName.append(nObject);
+ pushResource( ResXObject, aObjName.makeStringAndClear(), nObject );
}
@@ -11362,7 +11377,7 @@ void PDFWriterImpl::drawBitmap( const Point& rDestPoint, const Size& rDestSize,
aLine.append( ' ' );
m_aPages.back().appendPoint( rDestPoint + Point( 0, rDestSize.Height()-1 ), aLine );
aLine.append( " cm\n/Im" );
- sal_Int32 nObject = rBitmap.getObject();
+ sal_Int32 nObject = rBitmap.m_aReferenceXObject.getObject();
aLine.append(nObject);
aLine.append( " Do Q\n" );
if( nCheckWidth == 0 || nCheckHeight == 0 )
@@ -11413,22 +11428,13 @@ const PDFWriterImpl::BitmapEmit& PDFWriterImpl::createBitmapEmit( const BitmapEx
m_aBitmaps.front().m_aID = aID;
m_aBitmaps.front().m_aBitmap = aBitmap;
m_aBitmaps.front().m_nObject = createObject();
- if (rGraphic.getPdfData().hasElements())
- {
- // Store the original PDF data as an embedded file.
- m_aEmbeddedFiles.push_back(PDFEmbeddedFile());
- m_aEmbeddedFiles.back().m_nObject = createObject();
- m_aEmbeddedFiles.back().m_aData = rGraphic.getPdfData();
-
- m_aBitmaps.front().m_nFormObject = createObject();
- m_aBitmaps.front().m_nEmbeddedObject = m_aEmbeddedFiles.back().m_nObject;
- }
+ createEmbeddedFile(rGraphic, m_aBitmaps.front().m_aReferenceXObject, m_aBitmaps.front().m_nObject);
it = m_aBitmaps.begin();
}
OStringBuffer aObjName( 16 );
aObjName.append( "Im" );
- sal_Int32 nObject = it->getObject();
+ sal_Int32 nObject = it->m_aReferenceXObject.getObject();
aObjName.append(nObject);
pushResource( ResXObject, aObjName.makeStringAndClear(), nObject );
@@ -13278,21 +13284,12 @@ void PDFWriterImpl::MARK( const char* pString )
emitComment( pString );
}
-PDFWriterImpl::JPGEmit::JPGEmit(PDFWriterImpl::JPGEmit&& rOther)
-{
- m_aID = rOther.m_aID;
- m_pStream = std::move(rOther.m_pStream);
- m_aMask = std::move(rOther.m_aMask);
- m_nObject = rOther.m_nObject;
- m_bTrueColor = rOther.m_bTrueColor;
-}
-
-sal_Int32 PDFWriterImpl::BitmapEmit::getObject() const
+sal_Int32 PDFWriterImpl::ReferenceXObjectEmit::getObject() const
{
if (m_nFormObject > 0)
return m_nFormObject;
else
- return m_nObject;
+ return m_nBitmapObject;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index 022679f..3e50c0b 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -208,20 +208,22 @@ public:
}
};
- struct BitmapEmit
+ /// Contains information to emit a reference XObject.
+ struct ReferenceXObjectEmit
{
- BitmapID m_aID;
- BitmapEx m_aBitmap;
- sal_Int32 m_nObject;
/// ID of the Form XObject, if any.
sal_Int32 m_nFormObject;
- /// ID of the embedded object, if m_nFormObject is used.
+ /// ID of the vector/embedded object, if m_nFormObject is used.
sal_Int32 m_nEmbeddedObject;
-
- BitmapEmit()
- : m_nObject(0),
- m_nFormObject(0),
- m_nEmbeddedObject(0)
+ /// ID of the bitmap object, if m_nFormObject is used.
+ sal_Int32 m_nBitmapObject;
+ /// Size of the bitmap replacement, in pixels.
+ Size m_aPixelSize;
+
+ ReferenceXObjectEmit()
+ : m_nFormObject(0),
+ m_nEmbeddedObject(0),
+ m_nBitmapObject(0)
{
}
@@ -229,6 +231,19 @@ public:
sal_Int32 getObject() const;
};
+ struct BitmapEmit
+ {
+ BitmapID m_aID;
+ BitmapEx m_aBitmap;
+ sal_Int32 m_nObject;
+ ReferenceXObjectEmit m_aReferenceXObject;
+
+ BitmapEmit()
+ : m_nObject(0)
+ {
+ }
+ };
+
struct JPGEmit
{
BitmapID m_aID;
@@ -237,6 +252,7 @@ public:
Bitmap m_aMask;
sal_Int32 m_nObject;
bool m_bTrueColor;
+ ReferenceXObjectEmit m_aReferenceXObject;
JPGEmit()
: m_pStream(nullptr)
@@ -827,6 +843,8 @@ i12626
bool writeBitmapObject( BitmapEmit& rObject, bool bMask = false );
void writeJPG( JPGEmit& rEmit );
+ /// Writes the form XObject proxy for the image.
+ void writeReferenceXObject(ReferenceXObjectEmit& rEmit);
/* tries to find the bitmap by its id and returns its emit data if exists,
else creates a new emit data block */
@@ -1194,7 +1212,9 @@ public:
void drawBitmap( const Point& rDestPoint, const Size& rDestSize, const Bitmap& rBitmap, const Graphic& rGraphic );
void drawBitmap( const Point& rDestPoint, const Size& rDestSize, const BitmapEx& rBitmap );
- void drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const Size& rSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask );
+ void drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const Size& rSizePixel, const Rectangle& rTargetArea, const Bitmap& rMask, const Graphic& rGraphic );
+ /// Stores the original PDF data from rGraphic as an embedded file.
+ void createEmbeddedFile(const Graphic& rGraphic, ReferenceXObjectEmit& rEmit, sal_Int32 nBitmapObject);
void drawGradient( const Rectangle& rRect, const Gradient& rGradient );
void drawHatch( const tools::PolyPolygon& rPolyPoly, const Hatch& rHatch );
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx
index 6de2a88..00120c5 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -243,7 +243,7 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz
}
}
if ( bUseJPGCompression )
- m_rOuterFace.DrawJPGBitmap( aStrm, bTrueColorJPG, aSizePixel, Rectangle( aPoint, aSize ), aMask );
+ m_rOuterFace.DrawJPGBitmap( aStrm, bTrueColorJPG, aSizePixel, Rectangle( aPoint, aSize ), aMask, i_Graphic );
else if ( aBitmapEx.IsTransparent() )
m_rOuterFace.DrawBitmapEx( aPoint, aSize, aBitmapEx );
else
More information about the Libreoffice-commits
mailing list