[Libreoffice-commits] core.git: include/vcl sd/source vcl/source

Miklos Vajna vmiklos at collabora.co.uk
Mon Jan 2 17:42:23 UTC 2017


 include/vcl/pdfextoutdevdata.hxx    |    8 +++
 include/vcl/pdfwriter.hxx           |    7 ++
 sd/source/ui/unoidl/unomodel.cxx    |   12 ++++
 vcl/source/gdi/pdfextoutdevdata.cxx |   40 +++++++++++++++
 vcl/source/gdi/pdfwriter.cxx        |   11 ++++
 vcl/source/gdi/pdfwriter_impl.cxx   |   91 ++++++++++++++++++++++++++++++++++++
 vcl/source/gdi/pdfwriter_impl.hxx   |   14 +++++
 7 files changed, 183 insertions(+)

New commits:
commit 9d6a749bc664f1876c938afb9eba4adc9f6ee09a
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Jan 2 17:28:57 2017 +0100

    tdf#104841 sd PDF export: handle linked videos
    
    Use the screen annotation markup for this purpose.
    
    Change-Id: I129111cbe08c19c2f3b3ae046408ff9b2a28520c
    Reviewed-on: https://gerrit.libreoffice.org/32654
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/include/vcl/pdfextoutdevdata.hxx b/include/vcl/pdfextoutdevdata.hxx
index 7095b90..1a0c941 100644
--- a/include/vcl/pdfextoutdevdata.hxx
+++ b/include/vcl/pdfextoutdevdata.hxx
@@ -262,6 +262,10 @@ public:
     -1 if page id does not exist
     */
     sal_Int32 CreateLink( const Rectangle& rRect, sal_Int32 nPageNr = -1 );
+
+    /// Create a Screen annotation.
+    sal_Int32 CreateScreen(const Rectangle& rRect);
+
     /** Set the destination for a link
         <p>will change a URL type link to a dest link if necessary</p>
 
@@ -293,6 +297,10 @@ public:
         -1 in case the link id does not exist
     */
     sal_Int32 SetLinkURL( sal_Int32 nLinkId, const OUString& rURL );
+
+    /// Set URL for a Screen annotation.
+    void SetScreenURL(sal_Int32 nScreenId, const OUString& rURL);
+
     /** Create a new outline item
 
         @param nParent
diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx
index 67eee15..888cddb 100644
--- a/include/vcl/pdfwriter.hxx
+++ b/include/vcl/pdfwriter.hxx
@@ -927,6 +927,9 @@ The following structure describes the permissions used in PDF security
     */
     sal_Int32           CreateLink( const Rectangle& rRect, sal_Int32 nPageNr );
 
+    /// Creates a screen annotation.
+    sal_Int32 CreateScreen(const Rectangle& rRect, sal_Int32 nPageNr);
+
     /** creates a destination which is not intended to be referred to by a link, but by a public destination Id.
 
         Form widgets, for instance, might refer to a destination, without ever actually creating a source link to
@@ -973,6 +976,10 @@ The following structure describes the permissions used in PDF security
         service; the result will then appear literally in the PDF file produced
     */
     void           SetLinkURL( sal_Int32 nLinkId, const OUString& rURL );
+
+    /// Sets the URL of a linked screen annotation.
+    void SetScreenURL(sal_Int32 nScreenId, const OUString& rURL);
+
     /** Resolve link in logical structure
 
         If a link is created after the corresponding visual appearance was drawn
diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx
index 0da6543..cb269d6 100644
--- a/sd/source/ui/unoidl/unomodel.cxx
+++ b/sd/source/ui/unoidl/unomodel.cxx
@@ -1652,6 +1652,18 @@ void ImplPDFExportShapeInteraction( const uno::Reference< drawing::XShape >& xSh
             awt::Size   aShapeSize( xShape->getSize() );
             Rectangle   aLinkRect( Point( aShapePos.X, aShapePos.Y ), Size( aShapeSize.Width, aShapeSize.Height ) );
 
+            // Handle linked videos.
+            if (xShape->getShapeType() == "com.sun.star.drawing.MediaShape")
+            {
+                OUString aMediaURL;
+                xShapePropSet->getPropertyValue("MediaURL") >>= aMediaURL;
+                if (!aMediaURL.isEmpty())
+                {
+                    sal_Int32 nScreenId = rPDFExtOutDevData.CreateScreen(aLinkRect);
+                    rPDFExtOutDevData.SetScreenURL(nScreenId, aMediaURL);
+                }
+            }
+
             presentation::ClickAction eCa;
             uno::Any aAny( xShapePropSet->getPropertyValue( "OnClick" ) );
             if ( aAny >>= eCa )
diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx b/vcl/source/gdi/pdfextoutdevdata.cxx
index 73d9232..f85c981 100644
--- a/vcl/source/gdi/pdfextoutdevdata.cxx
+++ b/vcl/source/gdi/pdfextoutdevdata.cxx
@@ -36,8 +36,10 @@ struct PDFExtOutDevDataSync
     enum Action{    CreateNamedDest,
                     CreateDest,
                     CreateLink,
+                    CreateScreen,
                     SetLinkDest,
                     SetLinkURL,
+                    SetScreenURL,
                     RegisterDest,
                     CreateOutlineItem,
                     SetOutlineItemParent,
@@ -183,6 +185,17 @@ void GlobalSyncData::PlayGlobalActions( PDFWriter& rWriter )
                 rWriter.Pop();
             }
             break;
+            case PDFExtOutDevDataSync::CreateScreen:
+            {
+                rWriter.Push(PushFlags::MAPMODE);
+                rWriter.SetMapMode(mParaMapModes.front());
+                mParaMapModes.pop_front();
+                mParaIds.push_back(rWriter.CreateScreen(mParaRects.front(), mParaInts.front()));
+                mParaRects.pop_front();
+                mParaInts.pop_front();
+                rWriter.Pop();
+            }
+            break;
             case PDFExtOutDevDataSync::SetLinkDest :
             {
                 sal_Int32 nLinkId = GetMappedId();
@@ -197,6 +210,13 @@ void GlobalSyncData::PlayGlobalActions( PDFWriter& rWriter )
                 mParaOUStrings.pop_front();
             }
             break;
+            case PDFExtOutDevDataSync::SetScreenURL:
+            {
+                sal_Int32 nScreenId = GetMappedId();
+                rWriter.SetScreenURL(nScreenId, mParaOUStrings.front());
+                mParaOUStrings.pop_front();
+            }
+            break;
             case PDFExtOutDevDataSync::RegisterDest :
             {
                 const sal_Int32 nDestId = mParaInts.front();
@@ -494,8 +514,10 @@ bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAc
             case PDFExtOutDevDataSync::CreateNamedDest:
             case PDFExtOutDevDataSync::CreateDest:
             case PDFExtOutDevDataSync::CreateLink:
+            case PDFExtOutDevDataSync::CreateScreen:
             case PDFExtOutDevDataSync::SetLinkDest:
             case PDFExtOutDevDataSync::SetLinkURL:
+            case PDFExtOutDevDataSync::SetScreenURL:
             case PDFExtOutDevDataSync::RegisterDest:
             case PDFExtOutDevDataSync::CreateOutlineItem:
             case PDFExtOutDevDataSync::SetOutlineItemParent:
@@ -672,6 +694,16 @@ sal_Int32 PDFExtOutDevData::CreateLink( const Rectangle& rRect, sal_Int32 nPageN
     mpGlobalSyncData->mParaInts.push_back( nPageNr == -1 ? mnPage : nPageNr );
     return mpGlobalSyncData->mCurId++;
 }
+
+sal_Int32 PDFExtOutDevData::CreateScreen(const Rectangle& rRect)
+{
+    mpGlobalSyncData->mActions.push_back(PDFExtOutDevDataSync::CreateScreen);
+    mpGlobalSyncData->mParaRects.push_back(rRect);
+    mpGlobalSyncData->mParaMapModes.push_back(mrOutDev.GetMapMode());
+    mpGlobalSyncData->mParaInts.push_back(mnPage);
+    return mpGlobalSyncData->mCurId++;
+}
+
 sal_Int32 PDFExtOutDevData::SetLinkDest( sal_Int32 nLinkId, sal_Int32 nDestId )
 {
     mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::SetLinkDest );
@@ -686,6 +718,14 @@ sal_Int32 PDFExtOutDevData::SetLinkURL( sal_Int32 nLinkId, const OUString& rURL
     mpGlobalSyncData->mParaOUStrings.push_back( rURL );
     return 0;
 }
+
+void PDFExtOutDevData::SetScreenURL(sal_Int32 nScreenId, const OUString& rURL)
+{
+    mpGlobalSyncData->mActions.push_back(PDFExtOutDevDataSync::SetScreenURL);
+    mpGlobalSyncData->mParaInts.push_back(nScreenId);
+    mpGlobalSyncData->mParaOUStrings.push_back(rURL);
+}
+
 sal_Int32 PDFExtOutDevData::CreateOutlineItem( sal_Int32 nParent, const OUString& rText, sal_Int32 nDestID )
 {
     mpGlobalSyncData->mActions.push_back( PDFExtOutDevDataSync::CreateOutlineItem );
diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx
index 741df80..7463e77 100644
--- a/vcl/source/gdi/pdfwriter.cxx
+++ b/vcl/source/gdi/pdfwriter.cxx
@@ -343,6 +343,12 @@ sal_Int32 PDFWriter::CreateLink( const Rectangle& rRect, sal_Int32 nPageNr )
 {
     return xImplementation->createLink( rRect, nPageNr );
 }
+
+sal_Int32 PDFWriter::CreateScreen(const Rectangle& rRect, sal_Int32 nPageNr)
+{
+    return xImplementation->createScreen(rRect, nPageNr);
+}
+
 sal_Int32 PDFWriter::RegisterDestReference( sal_Int32 nDestId, const Rectangle& rRect, sal_Int32 nPageNr, DestAreaType eType )
 {
     return xImplementation->registerDestReference( nDestId, rRect, nPageNr, eType );
@@ -367,6 +373,11 @@ void PDFWriter::SetLinkURL( sal_Int32 nLinkId, const OUString& rURL )
     xImplementation->setLinkURL( nLinkId, rURL );
 }
 
+void PDFWriter::SetScreenURL(sal_Int32 nScreenId, const OUString& rURL)
+{
+    xImplementation->setScreenURL(nScreenId, rURL);
+}
+
 void PDFWriter::SetLinkPropertyID( sal_Int32 nLinkId, sal_Int32 nPropertyId )
 {
     xImplementation->setLinkPropertyId( nLinkId, nPropertyId );
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index d75bdeb..83672f1 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -106,6 +106,7 @@
 #endif
 
 using namespace vcl;
+using namespace::com::sun::star;
 
 static bool g_bDebugDisableCompression = getenv("VCL_DEBUG_DISABLE_PDFCOMPRESSION");
 
@@ -3765,6 +3766,64 @@ bool PDFWriterImpl::appendDest( sal_Int32 nDestID, OStringBuffer& rBuffer )
     return true;
 }
 
+bool PDFWriterImpl::emitScreenAnnotations()
+{
+    int nAnnots = m_aScreens.size();
+    for (int i = 0; i < nAnnots; i++)
+    {
+        const PDFScreen& rScreen = m_aScreens[i];
+        if (!updateObject(rScreen.m_nObject))
+            continue;
+
+        // Annot dictionary.
+        OStringBuffer aLine;
+        aLine.append(rScreen.m_nObject);
+        aLine.append(" 0 obj\n");
+        aLine.append("<</Type/Annot");
+        aLine.append("/Subtype/Screen/Rect[");
+        appendFixedInt(rScreen.m_aRect.Left(), aLine);
+        aLine.append(' ');
+        appendFixedInt(rScreen.m_aRect.Top(), aLine);
+        aLine.append(' ');
+        appendFixedInt(rScreen.m_aRect.Right(), aLine);
+        aLine.append(' ');
+        appendFixedInt(rScreen.m_aRect.Bottom(), aLine);
+        aLine.append("]");
+
+        // Action dictionary.
+        aLine.append("/A<</Type/Action /S/Rendition /AN ");
+        aLine.append(rScreen.m_nObject);
+        aLine.append(" 0 R ");
+
+        // Rendition dictionary.
+        aLine.append("/R<</Type/Rendition /S/MR ");
+
+        // MediaClip dictionary.
+        aLine.append("/C<</Type/MediaClip /S/MCD ");
+        aLine.append("/D << /FS /URL /Type /Filespec /F ");
+        appendLiteralStringEncrypt(rScreen.m_aURL, rScreen.m_nObject, aLine, osl_getThreadTextEncoding());
+        aLine.append(" >>");
+        // Is there anything Acrobat supports natively other than this?
+        aLine.append("/CT (video/mpeg)");
+        aLine.append(">>");
+
+        // End Rendition dictionary by requesting play/pause/stop controls.
+        aLine.append("/P<</BE<</C true >>>>");
+        aLine.append(">>");
+
+        // End Action dictionary.
+        aLine.append("/OP 0 >>");
+
+        // End Annot dictionary.
+        aLine.append("/P ");
+        aLine.append(m_aPages[rScreen.m_nPage].m_nPageObject);
+        aLine.append(" 0 R\n>>\nendobj\n\n");
+        CHECK_RETURN(writeBuffer(aLine.getStr(), aLine.getLength()));
+    }
+
+    return true;
+}
+
 bool PDFWriterImpl::emitLinkAnnotations()
 {
     int nAnnots = m_aLinks.size();
@@ -4895,6 +4954,7 @@ bool PDFWriterImpl::emitAnnotations()
         return false;
 
     CHECK_RETURN( emitLinkAnnotations() );
+    CHECK_RETURN(emitScreenAnnotations());
     CHECK_RETURN( emitNoteAnnotations() );
     CHECK_RETURN( emitWidgetAnnotations() );
 
@@ -11814,6 +11874,29 @@ sal_Int32 PDFWriterImpl::createLink( const Rectangle& rRect, sal_Int32 nPageNr )
     return nRet;
 }
 
+sal_Int32 PDFWriterImpl::createScreen(const Rectangle& rRect, sal_Int32 nPageNr)
+{
+    if (nPageNr < 0)
+        nPageNr = m_nCurrentPage;
+
+    if (nPageNr < 0 || nPageNr >= static_cast<sal_Int32>(m_aPages.size()))
+        return -1;
+
+    sal_Int32 nRet = m_aScreens.size();
+
+    m_aScreens.push_back(PDFScreen());
+    m_aScreens.back().m_nObject = createObject();
+    m_aScreens.back().m_nPage = nPageNr;
+    m_aScreens.back().m_aRect = rRect;
+    // Convert to default user space now, since the mapmode may change.
+    m_aPages[nPageNr].convertRect(m_aScreens.back().m_aRect);
+
+    // Insert link to page's annotation list.
+    m_aPages[nPageNr].m_aAnnotations.push_back(m_aScreens.back().m_nObject);
+
+    return nRet;
+}
+
 //--->i56629
 sal_Int32 PDFWriterImpl::createNamedDest( const OUString& sDestName, const Rectangle& rRect, sal_Int32 nPageNr, PDFWriter::DestAreaType eType )
 {
@@ -11895,6 +11978,14 @@ void PDFWriterImpl::setLinkURL( sal_Int32 nLinkId, const OUString& rURL )
     m_aLinks[ nLinkId ].m_aURL  = aURL.Complete;
 }
 
+void PDFWriterImpl::setScreenURL(sal_Int32 nScreenId, const OUString& rURL)
+{
+    if (nScreenId < 0 || nScreenId >= static_cast<sal_Int32>(m_aScreens.size()))
+        return;
+
+    m_aScreens[nScreenId].m_aURL = rURL;
+}
+
 void PDFWriterImpl::setLinkPropertyId( sal_Int32 nLinkId, sal_Int32 nPropertyId )
 {
     m_aLinkPropertyMap[ nPropertyId ] = nLinkId;
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index d974442..8f9a9d6 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -414,6 +414,12 @@ public:
         {}
     };
 
+    /// A PDF Screen annotation.
+    struct PDFScreen : public PDFAnnotation
+    {
+        OUString m_aURL;
+    };
+
     struct PDFNoteEntry : public PDFAnnotation
     {
         PDFNote                     m_aContents;
@@ -604,6 +610,8 @@ private:
        link id is always the link's position in this vector
     */
     std::vector<PDFLink>                m_aLinks;
+    /// Contains all screen annotations.
+    std::vector<PDFScreen> m_aScreens;
     /* makes correctly encoded for export to PDF URLS
     */
     css::uno::Reference< css::util::XURLTransformer > m_xTrans;
@@ -852,6 +860,8 @@ i12626
     bool appendDest( sal_Int32 nDestID, OStringBuffer& rBuffer );
     // write all links
     bool emitLinkAnnotations();
+    /// Write all screen annotations.
+    bool emitScreenAnnotations();
     // write all notes
     bool emitNoteAnnotations();
     // write the appearance streams of a widget
@@ -1189,6 +1199,10 @@ public:
     void      setLinkURL( sal_Int32 nLinkId, const OUString& rURL );
     void      setLinkPropertyId( sal_Int32 nLinkId, sal_Int32 nPropertyId );
 
+    // screens
+    sal_Int32 createScreen(const Rectangle& rRect, sal_Int32 nPageNr);
+    void setScreenURL(sal_Int32 nScreenId, const OUString& rURL);
+
     // outline
     sal_Int32 createOutlineItem( sal_Int32 nParent, const OUString& rText, sal_Int32 nDestID );
     void      setOutlineItemParent( sal_Int32 nItem, sal_Int32 nNewParent );


More information about the Libreoffice-commits mailing list