filter/source/msfilter/escherex.cxx | 47 ++++--- include/filter/msfilter/escherex.hxx | 12 + oox/source/export/drawingml.cxx | 58 ++++++--- oox/source/export/vmlexport.cxx | 81 +++++++------ sw/qa/extras/ooxmlexport/data/fdo60957-2.docx |binary sw/qa/extras/ooxmlexport/data/kde216114-1.odt |binary sw/qa/extras/ooxmlexport/data/kde302504-1.odt |binary sw/qa/extras/ooxmlexport/data/ooo106020-1.odt |binary sw/qa/extras/ooxmlexport/data/ooo34469-1.odt |binary sw/qa/extras/ooxmlexport/data/ooo39845-7.odt |binary sw/qa/extras/ooxmlexport/data/ooo47778-3.odt |binary sw/qa/extras/ooxmlexport/data/ooo47778-4.odt |binary sw/qa/extras/ooxmlexport/data/ooo67471-2.odt |binary sw/qa/extras/ooxmlexport/data/ooo72950-1.odt |binary sw/qa/extras/ooxmlexport/ooxmlexport5.cxx | 53 ++++++++ sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 13 ++ sw/source/filter/ww8/WW8TableInfo.cxx | 95 ++++++++++----- sw/source/filter/ww8/WW8TableInfo.hxx | 21 ++- sw/source/filter/ww8/docxattributeoutput.cxx | 42 ++++-- sw/source/filter/ww8/rtfsdrexport.cxx | 79 +++++++------ sw/source/filter/ww8/wrtww8.cxx | 96 +++++++++++---- sw/source/filter/ww8/wrtww8.hxx | 4 vcl/headless/svpgdi.cxx | 158 +++++++++++++++++++++++--- vcl/inc/headless/svpgdi.hxx | 9 + vcl/inc/unx/gtk/gtkgdi.hxx | 2 vcl/unx/gtk/window/gtksalframe.cxx | 26 ++-- vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx | 25 ---- 27 files changed, 585 insertions(+), 236 deletions(-)
New commits: commit 1b39e54ecd02fe16ad045bb787c09ded76c4ac33 Author: Julien Nabet <serval2...@yahoo.fr> Date: Wed Jun 24 22:41:31 2015 +0200 GtkSettings:gtk-menu-images deprecated Reviewed-on: https://gerrit.libreoffice.org/16456 Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> (cherry picked from commit c301d8c8fa1de36d8aae03cfa76772b537b10980) Change-Id: I120c33bf726150506d282e972facd4dca0db83aa diff --git a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx index b13674c..ac99078 100644 --- a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx @@ -1740,12 +1740,11 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings ) aMouseSettings.SetMenuDelay( MENU_POPUP_DELAY ); rSettings.SetMouseSettings( aMouseSettings ); - gboolean showmenuicons = true, primarybuttonwarps = false; + gboolean primarybuttonwarps = false; g_object_get( pSettings, - "gtk-menu-images", &showmenuicons, "gtk-primary-button-warps-slider", &primarybuttonwarps, (char *)NULL ); - aStyleSet.SetPreferredUseImagesInMenus(showmenuicons); + aStyleSet.SetPreferredUseImagesInMenus(false); aStyleSet.SetPrimaryButtonWarpsSlider(primarybuttonwarps); // set scrollbar settings commit 155ada9a58fba6ab48029135f6cb9778e2fddffd Author: Julien Nabet <serval2...@yahoo.fr> Date: Tue Jun 23 18:37:11 2015 +0200 GtkSettings:gtk-menu-popup-delay deprecated I took example from https://mail.gnome.org/archives/commits-list/2013-June/msg06434.html Reviewed-on: https://gerrit.libreoffice.org/16432 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> (cherry picked from commit 25befc0a1b1448527c645ed1963b4f29d3126a53) Change-Id: I5fb090c3245848c92238f34259f1a2f77f9080c7 diff --git a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx index 84c138c..b13674c 100644 --- a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx @@ -1725,19 +1725,19 @@ void GtkSalGraphics::updateSettings( AllSettings& rSettings ) aStyleSet.SetCursorBlinkTime( STYLE_CURSOR_NOBLINKTIME ); MouseSettings aMouseSettings = rSettings.GetMouseSettings(); - int iDoubleClickTime, iDoubleClickDistance, iDragThreshold, iMenuPopupDelay; + int iDoubleClickTime, iDoubleClickDistance, iDragThreshold; + static const int MENU_POPUP_DELAY = 225; g_object_get( pSettings, "gtk-double-click-time", &iDoubleClickTime, "gtk-double-click-distance", &iDoubleClickDistance, "gtk-dnd-drag-threshold", &iDragThreshold, - "gtk-menu-popup-delay", &iMenuPopupDelay, (char *)NULL ); aMouseSettings.SetDoubleClickTime( iDoubleClickTime ); aMouseSettings.SetDoubleClickWidth( iDoubleClickDistance ); aMouseSettings.SetDoubleClickHeight( iDoubleClickDistance ); aMouseSettings.SetStartDragWidth( iDragThreshold ); aMouseSettings.SetStartDragHeight( iDragThreshold ); - aMouseSettings.SetMenuDelay( iMenuPopupDelay ); + aMouseSettings.SetMenuDelay( MENU_POPUP_DELAY ); rSettings.SetMouseSettings( aMouseSettings ); gboolean showmenuicons = true, primarybuttonwarps = false; commit 432c33cc1059c220194e2c4a949ffb51b4dddcc4 Author: Caolán McNamara <caol...@redhat.com> Date: Thu Jun 25 20:21:46 2015 +0100 these ancient baselines are breaking my spirit Change-Id: I96dbe2c1213c78da1114f9270953334a38c7b2ae (cherry picked from commit 6a01c78435c4237e8702966d30de2a47b58e7620) diff --git a/vcl/unx/gtk/window/gtksalframe.cxx b/vcl/unx/gtk/window/gtksalframe.cxx index 99adfff..a7b9b88 100644 --- a/vcl/unx/gtk/window/gtksalframe.cxx +++ b/vcl/unx/gtk/window/gtksalframe.cxx @@ -2872,6 +2872,19 @@ void GtkSalFrame::Sync() gdk_display_sync( getGdkDisplay() ); } +#ifndef GDK_Open +#define GDK_Open 0x1008ff6b +#endif +#ifndef GDK_Paste +#define GDK_Paste 0x1008ff6d +#endif +#ifndef GDK_Copy +#define GDK_Copy 0x1008ff57 +#endif +#ifndef GDK_Cut +#define GDK_Cut 0x1008ff58 +#endif + void GtkSalFrame::KeyCodeToGdkKey(const vcl::KeyCode& rKeyCode, guint* pGdkKeyCode, GdkModifierType *pGdkModifiers) { commit c2a667666fb1bb286c22ba87d18d81bb53029079 Author: Caolán McNamara <caol...@redhat.com> Date: Sat Jun 20 18:04:12 2015 +0100 fix assert on exporting ooo106020-1.odt to docx the dread msword column limit Change-Id: Icbf7fc396de62286d523516da815dabf62336567 (cherry picked from commit 20e64b6012442749d01810869229613ea36be3a9) diff --git a/sw/qa/extras/ooxmlexport/data/ooo106020-1.odt b/sw/qa/extras/ooxmlexport/data/ooo106020-1.odt new file mode 100644 index 0000000..9cc774b Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ooo106020-1.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 0c215a9..dd3a11f 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -858,6 +858,14 @@ DECLARE_OOXMLEXPORT_TEST(fdo60957, "fdo60957-2.docx") assertXPath(pXmlDoc, "//w:tbl", 2); } +//This has more cells than msword supports, we must balance the +//number of cell start and ends +DECLARE_OOXMLEXPORT_TEST(testOO106020, "ooo106020-1.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPath(pXmlDoc, "//w:tbl", 1); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 0064d4d..54b511c 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -688,16 +688,18 @@ void DocxAttributeOutput::EndSdtBlock() m_pSerializer->endElementNS( XML_w, XML_sdt ); } +#define MAX_CELL_IN_WORD 62 + void DocxAttributeOutput::SyncNodelessCells(ww8::WW8TableNodeInfoInner::Pointer_t pInner, sal_Int32 nCell, sal_uInt32 nRow) { sal_Int32 nOpenCell = lastOpenCell.back(); - if (nOpenCell != -1 && nOpenCell != nCell) + if (nOpenCell != -1 && nOpenCell != nCell && nOpenCell < MAX_CELL_IN_WORD) EndTableCell(pInner, nOpenCell, nRow); sal_Int32 nClosedCell = lastClosedCell.back(); for (sal_Int32 i = nClosedCell+1; i < nCell; ++i) { - if (i >= 62) //words limit + if (i >= MAX_CELL_IN_WORD) break; if (i == 0) @@ -725,11 +727,11 @@ void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointe // so simply if there are more columns, don't close the last one msoffice will handle // and merge the contents of the remaining ones into it (since we don't close the cell // here, following ones will not be opened) - const bool limitWorkaround = (nCell >= 62 && !pInner->isEndOfLine()); + const bool limitWorkaround = (nCell >= MAX_CELL_IN_WORD && !pInner->isEndOfLine()); const bool bEndCell = pInner->isEndOfCell() && !limitWorkaround; const bool bEndRow = pInner->isEndOfLine(); - if ( bEndCell ) + if (bEndCell) { while (pInner->getDepth() < m_tableReference->m_nTableDepth) { commit fbe0ba4c92e4feef429fcab4aa49fdef6ac63b8c Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 17 13:21:23 2015 +0100 fix crash on re-export of fdo60957-2.docx to docx Change-Id: I1a74a5f1877bfa72818ff0a38788eafe77eea581 (cherry picked from commit 89c85a4b7674ddfd697d539d59d27176c683a46c) diff --git a/sw/qa/extras/ooxmlexport/data/fdo60957-2.docx b/sw/qa/extras/ooxmlexport/data/fdo60957-2.docx new file mode 100644 index 0000000..3819aaf Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/fdo60957-2.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index dddbdee..0c215a9 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -849,6 +849,15 @@ DECLARE_OOXMLEXPORT_TEST(testOO72950, "ooo72950-1.odt") assertXPath(pXmlDoc, "//w:tbl", 1); } +//There are two tables to export in this doc the second of which is inside a +//frame anchored to first cell of the first table. They must not be +//considered the same table +DECLARE_OOXMLEXPORT_TEST(fdo60957, "fdo60957-2.docx") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPath(pXmlDoc, "//w:tbl", 2); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 88cfdc7..0064d4d 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -567,15 +567,15 @@ void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pT // Write framePr if(!aFramePrTextbox.empty()) { - ww8::WW8TableInfo::Pointer_t pOldTableInfo = m_rExport.m_pTableInfo; for (std::vector< boost::shared_ptr<sw::Frame> > ::iterator it = aFramePrTextbox.begin() ; it != aFramePrTextbox.end(); ++it) { - m_rExport.m_pTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo()); + DocxTableExportContext aTableExportContext; + pushToTableExportContext(aTableExportContext); m_pCurrentFrame = it->get(); m_rExport.SdrExporter().writeOnlyTextOfFrame(it->get()); m_pCurrentFrame = NULL; + popFromTableExportContext(aTableExportContext); } - m_rExport.m_pTableInfo = pOldTableInfo; aFramePrTextbox.clear(); } // Check for end of cell, rows, tables here commit b8a6477f4ba00b6253cfb33d4e8edccf60685168 Author: Caolán McNamara <caol...@redhat.com> Date: Thu Jun 11 14:30:18 2015 +0100 best effort export of ooo72950-1.odt to docx without crashing the curious case of ooo72950-1.odt which has no nodes in the first line of the table as seen from the visual layout perspective seeing as the table is split over two columns with the second column portion of the table higher than the left column portion Change-Id: I38526bf80ff8cef1688aa5f5f686e437c4a3d6e5 (cherry picked from commit f81c775b0782259c1b5504af859237fd71ac89e6) diff --git a/sw/qa/extras/ooxmlexport/data/ooo72950-1.odt b/sw/qa/extras/ooxmlexport/data/ooo72950-1.odt new file mode 100644 index 0000000..df0ac91 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ooo72950-1.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 14be93e..dddbdee 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -843,6 +843,12 @@ DECLARE_OOXMLEXPORT_TEST(testKDE216114, "kde216114-1.odt") assertXPath(pXmlDoc, "//w:pict", 1); } +DECLARE_OOXMLEXPORT_TEST(testOO72950, "ooo72950-1.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPath(pXmlDoc, "//w:tbl", 1); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index c6e980c..88cfdc7 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -250,7 +250,7 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText sal_uInt32 nRow = pTextNodeInfo->getRow(); sal_uInt32 nCell = pTextNodeInfo->getCell(); - if ( nRow == 0 && nCell == 0 ) + if (nCell == 0) { // Do we have to start the table? // [If we are at the right depth already, it means that we @@ -260,14 +260,14 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText if ( nCurrentDepth > m_tableReference->m_nTableDepth ) { // Start all the tables that begin here - for ( sal_uInt32 nDepth = m_tableReference->m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth ) + for ( sal_uInt32 nDepth = m_tableReference->m_nTableDepth + 1; nDepth <= nCurrentDepth; ++nDepth ) { ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) ); StartTable( pInner ); StartTableRow( pInner ); - StartTableCell(pInner, 0, 0); + StartTableCell(pInner, 0, nDepth == nCurrentDepth ? nRow : 0); } m_tableReference->m_nTableDepth = nCurrentDepth; commit eca8386ce0f7693bfe3520f6cd86bc7c1cbb4dc0 Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 10 15:34:44 2015 +0100 Prop_pSegmentInfo is totally misunderstood apparently digging into the crash on export of kde216114-1.odt reveals various horrors Change-Id: I0d24fe303d561a00a08098b306d10fd8273af928 (cherry picked from commit b04e1e79e64cb7bb3106fd08a019c27b09bdd5c6) diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx index 3bc125f..eded8e8 100644 --- a/filter/source/msfilter/escherex.cxx +++ b/filter/source/msfilter/escherex.cxx @@ -3258,85 +3258,92 @@ void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeT .WriteUInt16( nElementSize ); for ( j = 0; j < nElements; j++ ) { + // The segment type is stored in the upper 3 bits + // and segment count is stored in the lower 13 + // bits. + // + // If the segment type is msopathEscape, the lower 13 bits + // are divided in a 5 bit escape code and 8 bit + // vertex count (not segment count!) sal_uInt16 nVal = (sal_uInt16)aSegments[ j ].Count; switch( aSegments[ j ].Command ) { - case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN : - case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::LINETO : break; - case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::MOVETO : - { - nVal = 0x4000; - } - break; + case css::drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN : + case css::drawing::EnhancedCustomShapeSegmentCommand::LINETO : + break; + case css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO : + nVal = (msopathMoveTo << 13); + break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CURVETO : { - nVal |= 0x2000; + nVal |= (msopathCurveTo << 13); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH : { - nVal = 0x6001; + nVal = 1; + nVal |= (msopathClose << 13); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH : { - nVal = 0x8000; + nVal = (msopathEnd << 13); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOFILL : { - nVal = 0xaa00; + nVal = (msopathEscape << 13) | (5 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE : { - nVal = 0xab00; + nVal = (msopathEscape << 13) | (11 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO : { nVal *= 3; - nVal |= 0xa100; + nVal |= (msopathEscape << 13) | (1 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE : { nVal *= 3; - nVal |= 0xa200; + nVal |= (msopathEscape << 13) | (2 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARCTO : { nVal <<= 2; - nVal |= 0xa300; + nVal |= (msopathEscape << 13) | (3 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ARC : { nVal <<= 2; - nVal |= 0xa400; + nVal |= (msopathEscape << 13) | (4 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO : { nVal <<= 2; - nVal |= 0xa500; + nVal |= (msopathEscape << 13) | (5 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC : { nVal <<= 2; - nVal |= 0xa600; + nVal |= (msopathEscape << 13) | (6 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX : { - nVal |= 0xa700; + nVal |= (msopathEscape << 13) | (7 << 8); } break; case com::sun::star::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY : { - nVal |= 0xa800; + nVal |= (msopathEscape << 13) | (8 << 8); } break; } diff --git a/include/filter/msfilter/escherex.hxx b/include/filter/msfilter/escherex.hxx index 4e3f8d7..ca3465a 100644 --- a/include/filter/msfilter/escherex.hxx +++ b/include/filter/msfilter/escherex.hxx @@ -424,6 +424,18 @@ enum ESCHER_LineCap ESCHER_LineEndCapFlat // Line ends at end point }; +enum MSOPATHTYPE +{ + msopathLineTo, // Draw a straight line (one point) + msopathCurveTo, // Draw a cubic Bezier curve (three points) + msopathMoveTo, // Move to a new point (one point) + msopathClose, // Close a sub - path (no points) + msopathEnd, // End a path (no points) + msopathEscape, // Escape code + msopathClientEscape, // Escape code interpreted by the client + msopathInvalid // Invalid - should never be found +}; + // Shape Properties // 1pt = 12700 EMU (English Metric Units) // 1pt = 20 Twip = 20/1440" = 1/72" diff --git a/oox/source/export/vmlexport.cxx b/oox/source/export/vmlexport.cxx index 9e8e6d2..7161a2f 100644 --- a/oox/source/export/vmlexport.cxx +++ b/oox/source/export/vmlexport.cxx @@ -474,27 +474,56 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect for ( ; nSegments; --nSegments ) { sal_uInt16 nSeg = impl_GetUInt16( pSegmentIt ); - switch ( nSeg ) + + // The segment type is stored in the upper 3 bits + // and segment count is stored in the lower 13 + // bits. + unsigned char nSegmentType = (nSeg & 0xE000) >> 13; + unsigned short nSegmentCount = nSeg & 0x03FF; + + switch (nSegmentType) { - case 0x4000: // moveto + case msopathMoveTo: + { + sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize ); + sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize ); + if (nX >= 0 && nY >= 0 ) + aPath.append( "m" ).append( nX ).append( "," ).append( nY ); + break; + } + case msopathClientEscape: + break; + case msopathEscape: + { + // If the segment type is msopathEscape, the lower 13 bits are + // divided in a 5 bit escape code and 8 bit + // vertex count (not segment count!) + unsigned char nEscapeCode = (nSegmentCount & 0x1F00) >> 8; + unsigned char nVertexCount = nSegmentCount & 0x00FF; + pVerticesIt += nVertexCount; + + switch (nEscapeCode) { - sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize ); - sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize ); - if (nX >= 0 && nY >= 0 ) - aPath.append( "m" ).append( nX ).append( "," ).append( nY ); + case 0xa: // nofill + aPath.append( "nf" ); + break; + case 0xb: // nostroke + aPath.append( "ns" ); + break; } + break; - case 0xb300: - case 0xac00: - break; - case 0x0001: // lineto + } + case msopathLineTo: + for (unsigned short i = 0; i < nSegmentCount; ++i) { sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize ); sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize ); aPath.append( "l" ).append( nX ).append( "," ).append( nY ); } break; - case 0x2001: // curveto + case msopathCurveTo: + for (unsigned short i = 0; i < nSegmentCount; ++i) { sal_Int32 nX1 = impl_GetPointComponent( pVerticesIt, nPointSize ); sal_Int32 nY1 = impl_GetPointComponent( pVerticesIt, nPointSize ); @@ -507,35 +536,17 @@ void VMLExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect .append( nX3 ).append( "," ).append( nY3 ); } break; - case 0xaa00: // nofill - aPath.append( "nf" ); - break; - case 0xab00: // nostroke - aPath.append( "ns" ); - break; - case 0x6001: // close + case msopathClose: aPath.append( "x" ); break; - case 0x8000: // end + case msopathEnd: aPath.append( "e" ); break; default: - // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points. - // FIXME: we miss out a significant amount of complexity from - // the above method here, and do some rather odd things to match. - int nElems = !nPointSize ? 0 : aVertices.nPropSize / (nPointSize * 2); - if (nSeg > nElems) - { - SAL_WARN("oox", "Busted escher export " << nSeg << "vs . " << nElems << " truncating point stream"); - nSeg = nElems; - } - for (int i = 0; i < nSeg; ++i) - { - sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nPointSize); - sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nPointSize); - if (nX >= 0 && nY >= 0 ) - aPath.append("l").append(nX).append(",").append(nY); - } + SAL_WARN("oox", "Totally b0rked\n"); + break; + case msopathInvalid: + SAL_WARN("oox", "Invalid - should never be found"); break; } } diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index aea445e..14be93e 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -837,11 +837,11 @@ DECLARE_OOXMLEXPORT_TEST(testKDE302504, "kde302504-1.odt") assertXPath(pXmlDoc, "//v:shape", "ID", "KoPathShape"); } -//DECLARE_OOXMLEXPORT_TEST(testKDE216114, "kde216114-1.odt") -//{ -// if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) -// assertXPath(pXmlDoc, "//w:pict", 1); -//} +DECLARE_OOXMLEXPORT_TEST(testKDE216114, "kde216114-1.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPath(pXmlDoc, "//w:pict", 1); +} CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx index da441f5..cb8e8f6 100644 --- a/sw/source/filter/ww8/rtfsdrexport.cxx +++ b/sw/source/filter/ww8/rtfsdrexport.cxx @@ -278,48 +278,61 @@ void RtfSdrExport::Commit(EscherPropertyContainer& rProps, const Rectangle& rRec for (; nSegments; --nSegments) { sal_uInt16 nSeg = impl_GetUInt16(pSegmentIt); + + // The segment type is stored in the upper 3 bits + // and segment count is stored in the lower 13 + // bits. + unsigned char nSegmentType = (nSeg & 0xE000) >> 13; + unsigned short nSegmentCount = nSeg & 0x03FF; + aSegmentInfo.append(';').append((sal_Int32)nSeg); - switch (nSeg) - { - case 0x0001: // lineto - case 0x4000: // moveto - { - sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); - sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); - aVerticies.append(";(").append(nX).append(",").append(nY).append(")"); - nVertices ++; - } - break; - case 0x2001: // curveto + switch (nSegmentType) { - for (int i = 0; i < 3; i++) + case msopathLineTo: + for (unsigned short i = 0; i < nSegmentCount; ++i) + { + sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); + sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); + aVerticies.append(";(").append(nX).append(",").append(nY).append(")"); + nVertices ++; + } + break; + case msopathMoveTo: { sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); aVerticies.append(";(").append(nX).append(",").append(nY).append(")"); - nVertices ++; + nVertices++; + break; } - } - break; - case 0xb300: - case 0xac00: - case 0xaa00: // nofill - case 0xab00: // nostroke - case 0x6001: // close - case 0x8000: // end - break; - default: - // See EscherPropertyContainer::CreateCustomShapeProperties, by default nSeg is simply the number of points. - for (int i = 0; i < nSeg; ++i) + case msopathCurveTo: + for (unsigned short j = 0; j < nSegmentCount; ++j) + { + for (int i = 0; i < 3; i++) + { + sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); + sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); + aVerticies.append(";(").append(nX).append(",").append(nY).append(")"); + nVertices ++; + } + } + break; + case msopathEscape: { - if (nVerticesPos >= aVertices.nPropSize) - break; - sal_Int32 nX = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); - sal_Int32 nY = impl_GetPointComponent(pVerticesIt, nVerticesPos, nPointSize); - aVerticies.append(";(").append(nX).append(",").append(nY).append(")"); - ++nVertices; + // If the segment type is msopathEscape, the lower 13 bits are + // divided in a 5 bit escape code and 8 bit + // vertex count (not segment count!) + unsigned char nVertexCount = nSegmentCount & 0x00FF; + nVerticesPos += nVertexCount; + break; } - break; + case msopathClientEscape: + case msopathClose: + case msopathEnd: + break; + default: + SAL_WARN("oox", "Totally b0rked\n"); + break; } } commit c0d691b9d3266823e2ca64164b1738965699b8c9 Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 10 13:42:37 2015 +0100 VMLExport::Commit is riddled with out of bounds writes on export Change-Id: I9490d888ad148caecba034ef12b7398ae5c66a3f (cherry picked from commit 169cd9f675b6c868b829caf4bed0d829d9404b41) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 14be93e..aea445e 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -837,11 +837,11 @@ DECLARE_OOXMLEXPORT_TEST(testKDE302504, "kde302504-1.odt") assertXPath(pXmlDoc, "//v:shape", "ID", "KoPathShape"); } -DECLARE_OOXMLEXPORT_TEST(testKDE216114, "kde216114-1.odt") -{ - if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) - assertXPath(pXmlDoc, "//w:pict", 1); -} +//DECLARE_OOXMLEXPORT_TEST(testKDE216114, "kde216114-1.odt") +//{ +// if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) +// assertXPath(pXmlDoc, "//w:pict", 1); +//} CPPUNIT_PLUGIN_IMPLEMENT(); commit 5e9483c0e2573d759a96050070f51ff3b068c6af Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 10 13:05:51 2015 +0100 similarly fix fatal export of kde216114-1.odt to docx Change-Id: I78478de91473681fd8d836293dabe7b790dda516 (cherry picked from commit 80fbd731d8b8b101a10466a4d16d4867e9de968b) diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index b795c3e..9d4d84d 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -2282,9 +2282,11 @@ void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape ) } else { - sal_Int32 nXMin = aPairs[0].First.Value.get<sal_Int32>(); + sal_Int32 nXMin(0); + aPairs[0].First.Value >>= nXMin; sal_Int32 nXMax = nXMin; - sal_Int32 nYMin = aPairs[0].Second.Value.get<sal_Int32>(); + sal_Int32 nYMin(0); + aPairs[0].Second.Value >>= nYMin; sal_Int32 nYMax = nYMin; for ( int j = 0; j < aPairs.getLength(); ++j ) @@ -2321,9 +2323,13 @@ void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape ) { mpFS->startElementNS( XML_a, XML_moveTo, FSEND ); + sal_Int32 nX(0), nY(0); + aPairs[nPairIndex].First.Value >>= nX; + aPairs[nPairIndex].Second.Value >>= nY; + mpFS->singleElementNS( XML_a, XML_pt, - XML_x, I64S( aPairs[nPairIndex].First.Value.get<sal_Int32>() ), - XML_y, I64S( aPairs[nPairIndex].Second.Value.get<sal_Int32>() ), + XML_x, I64S(nX), + XML_y, I64S(nY), FSEND ); mpFS->endElementNS( XML_a, XML_moveTo ); @@ -2333,9 +2339,14 @@ void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape ) case drawing::EnhancedCustomShapeSegmentCommand::LINETO : { mpFS->startElementNS( XML_a, XML_lnTo, FSEND ); + + sal_Int32 nX(0), nY(0); + aPairs[nPairIndex].First.Value >>= nX; + aPairs[nPairIndex].Second.Value >>= nY; + mpFS->singleElementNS( XML_a, XML_pt, - XML_x, I64S( aPairs[nPairIndex].First.Value.get<sal_Int32>() ), - XML_y, I64S( aPairs[nPairIndex].Second.Value.get<sal_Int32>() ), + XML_x, I64S(nX), + XML_y, I64S(nY), FSEND ); mpFS->endElementNS( XML_a, XML_lnTo ); nPairIndex++; @@ -2346,9 +2357,13 @@ void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape ) mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND ); for( sal_uInt8 l = 0; l <= 2; ++l ) { + sal_Int32 nX(0), nY(0); + aPairs[nPairIndex+l].First.Value >>= nX; + aPairs[nPairIndex+l].Second.Value >>= nY; + mpFS->singleElementNS( XML_a, XML_pt, - XML_x, I64S( aPairs[nPairIndex+l].First.Value.get<sal_Int32>() ), - XML_y, I64S( aPairs[nPairIndex+l].Second.Value.get<sal_Int32>() ), + XML_x, I64S( nX ), + XML_y, I64S( nY ), FSEND ); } @@ -2381,10 +2396,14 @@ void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape ) mpFS->startElementNS( XML_a, XML_quadBezTo, FSEND ); for( sal_uInt8 l = 0; l < 2; ++l ) { + sal_Int32 nX(0), nY(0); + aPairs[nPairIndex+l].First.Value >>= nX; + aPairs[nPairIndex+l].Second.Value >>= nY; + mpFS->singleElementNS( XML_a, XML_pt, - XML_x, I64S( aPairs[nPairIndex+l].First.Value.get<sal_Int32>() ), - XML_y, I64S( aPairs[nPairIndex+l].Second.Value.get<sal_Int32>() ), - FSEND ); + XML_x, I64S( nX ), + XML_y, I64S( nY ), + FSEND ); } mpFS->endElementNS( XML_a, XML_quadBezTo ); diff --git a/sw/qa/extras/ooxmlexport/data/kde216114-1.odt b/sw/qa/extras/ooxmlexport/data/kde216114-1.odt new file mode 100644 index 0000000..536da72 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/kde216114-1.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 67ad8df..14be93e 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -837,6 +837,12 @@ DECLARE_OOXMLEXPORT_TEST(testKDE302504, "kde302504-1.odt") assertXPath(pXmlDoc, "//v:shape", "ID", "KoPathShape"); } +DECLARE_OOXMLEXPORT_TEST(testKDE216114, "kde216114-1.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPath(pXmlDoc, "//w:pict", 1); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 02d527344d8d18a01664f32416471161e2f78e27 Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 10 12:20:31 2015 +0100 fix fatal attempt to export kde302504-1.odt to docx the enhanced-path contains decimal points so the last element is a double not an integer Change-Id: I90be76a2d4cb90ee7a904aa72fe65770c675fc53 (cherry picked from commit aeb52a855d55475ff2e74f5308ae580dce3e069f) diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 15a8cb7..b795c3e 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -2289,14 +2289,15 @@ void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape ) for ( int j = 0; j < aPairs.getLength(); ++j ) { - if ( aPairs[j].First.Value.get<sal_Int32>() < nXMin ) - nXMin = aPairs[j].First.Value.get<sal_Int32>(); - if ( aPairs[j].Second.Value.get<sal_Int32>() < nYMin ) - nYMin = aPairs[j].Second.Value.get<sal_Int32>(); - if ( aPairs[j].First.Value.get<sal_Int32>() > nXMax ) - nXMax = aPairs[j].First.Value.get<sal_Int32>(); - if ( aPairs[j].Second.Value.get<sal_Int32>() > nYMax ) - nYMax = aPairs[j].Second.Value.get<sal_Int32>(); + sal_Int32 nCandidate(0); + if ((aPairs[j].First.Value >>= nCandidate) && nCandidate < nXMin) + nXMin = nCandidate; + if ((aPairs[j].Second.Value >>= nCandidate) && nCandidate < nYMin) + nYMin = nCandidate; + if ((aPairs[j].First.Value >>= nCandidate) && nCandidate > nXMax) + nXMax = nCandidate; + if ((aPairs[j].Second.Value >>= nCandidate) && nCandidate > nYMax) + nYMax = nCandidate; } mpFS->startElementNS( XML_a, XML_path, XML_w, I64S( nXMax - nXMin ), diff --git a/sw/qa/extras/ooxmlexport/data/kde302504-1.odt b/sw/qa/extras/ooxmlexport/data/kde302504-1.odt new file mode 100644 index 0000000..d0b7c60 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/kde302504-1.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index b63d755..67ad8df 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -831,6 +831,12 @@ DECLARE_OOXMLEXPORT_TEST(testOO67471, "ooo67471-2.odt") assertXPathContent(pXmlDoc, "(//w:t)[2]", "B"); } +DECLARE_OOXMLEXPORT_TEST(testKDE302504, "kde302504-1.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPath(pXmlDoc, "//v:shape", "ID", "KoPathShape"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 7d60c07613c5efec3ce1f217f00458296aeb5e3b Author: Caolán McNamara <caol...@redhat.com> Date: Tue Jun 9 17:26:14 2015 +0100 fix crash on export of ooo67471-2.sxw to docx This old-school table has three rows in it, but the second row is of 0 height so is indistinguisable from the third row by layout positioning, so the WW8TableNodeInfo view of the table is that it has two rows, and the comparison of being on the last row is done with the m_xTableWrt->GetRows view which considers it to have 3, so the table end marks are never output. add a new finalEndOfLine property that the WW8TableNodeInfo sets on the last end of row of the table as it sees it, which should resolve this. old style tables are a cess pit, which is why they were replaced Change-Id: I996aa59a338a594487f49ec0f228af3fb3032d15 (cherry picked from commit 6f9b3532ee81850500d9e87ad329c00ea9c83bba) diff --git a/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt b/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt new file mode 100644 index 0000000..82daa57 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ooo67471-2.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 5fe36fd..b63d755 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -825,6 +825,12 @@ DECLARE_OOXMLEXPORT_TEST(testOO47778_2, "ooo47778-4.odt") assertXPathContent(pXmlDoc, "(//w:t)[4]", "c"); } +DECLARE_OOXMLEXPORT_TEST(testOO67471, "ooo67471-2.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPathContent(pXmlDoc, "(//w:t)[2]", "B"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/WW8TableInfo.cxx b/sw/source/filter/ww8/WW8TableInfo.cxx index 1ff3298..ad729bc 100644 --- a/sw/source/filter/ww8/WW8TableInfo.cxx +++ b/sw/source/filter/ww8/WW8TableInfo.cxx @@ -40,6 +40,7 @@ WW8TableNodeInfoInner::WW8TableNodeInfoInner(WW8TableNodeInfo * pParent) , mnShadowsBefore(0) , mnShadowsAfter(0) , mbEndOfLine(false) +, mbFinalEndOfLine(false) , mbEndOfCell(false) , mbFirstInTable(false) , mbVertMerge(false) @@ -82,6 +83,11 @@ void WW8TableNodeInfoInner::setEndOfLine(bool bEndOfLine) mbEndOfLine = bEndOfLine; } +void WW8TableNodeInfoInner::setFinalEndOfLine(bool bFinalEndOfLine) +{ + mbFinalEndOfLine = bFinalEndOfLine; +} + void WW8TableNodeInfoInner::setEndOfCell(bool bEndOfCell) { mbEndOfCell = bEndOfCell; @@ -531,8 +537,6 @@ const SwTableBox * WW8TableNodeInfo::getTableBox() const return getInnerForDepth(mnDepth)->getTableBox(); } - - sal_uInt32 WW8TableNodeInfo::getCell() const { return getInnerForDepth(mnDepth)->getCell(); @@ -543,6 +547,10 @@ sal_uInt32 WW8TableNodeInfo::getRow() const return getInnerForDepth(mnDepth)->getRow(); } +bool WW8TableNodeInfo::isEndOfLine() const +{ + return getInnerForDepth(mnDepth)->isEndOfLine(); +} const WW8TableNodeInfoInner::Pointer_t WW8TableNodeInfo::getFirstInner() const { @@ -576,10 +584,9 @@ WW8TableInfo::~WW8TableInfo() } WW8TableNodeInfo * -WW8TableInfo::processSwTableByLayout(const SwTable * pTable) +WW8TableInfo::processSwTableByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds) { SwTableCellInfo aTableCellInfo(pTable); - WW8TableNodeInfo * pPrev = NULL; while (aTableCellInfo.getNext()) { @@ -619,9 +626,7 @@ WW8TableInfo::processSwTableByLayout(const SwTable * pTable) SAL_INFO( "sw.ww8", "</CellFrm>" ); } - pPrev = reorderByLayout(pTable); - - return pPrev; + return reorderByLayout(pTable, rLastRowEnds); } void WW8TableInfo::processSwTable(const SwTable * pTable) @@ -629,11 +634,11 @@ void WW8TableInfo::processSwTable(const SwTable * pTable) SAL_INFO( "sw.ww8", "<processSwTable>" ); WW8TableNodeInfo * pPrev = NULL; + RowEndInners_t aLastRowEnds; if (pTable->IsTableComplex() && pTable->HasLayout()) { - pPrev = processSwTableByLayout(pTable); - + pPrev = processSwTableByLayout(pTable, aLastRowEnds); #ifdef DBG_UTIL SAL_INFO( "sw.ww8", getCellGridForTable(pTable)->toString()); #endif @@ -646,17 +651,22 @@ void WW8TableInfo::processSwTable(const SwTable * pTable) { const SwTableLine * pLine = rLines[n]; - pPrev = processTableLine(pTable, pLine, static_cast<sal_uInt32>(n), 1, pPrev); + pPrev = processTableLine(pTable, pLine, static_cast<sal_uInt32>(n), 1, pPrev, aLastRowEnds); } } - if (pPrev != NULL) + if (pPrev) { SwTableNode * pTableNode = pTable->GetTableNode(); SwEndNode * pEndNode = pTableNode->EndOfSectionNode(); - pPrev->setNextNode(pEndNode); + assert(!aLastRowEnds.empty()); + for (auto &a : aLastRowEnds) + { + assert(a.second->isEndOfLine()); + a.second->setFinalEndOfLine(true); + } } SAL_INFO( "sw.ww8", "</processSwTable>" ); } @@ -665,7 +675,9 @@ WW8TableNodeInfo * WW8TableInfo::processTableLine(const SwTable * pTable, const SwTableLine * pTableLine, sal_uInt32 nRow, - sal_uInt32 nDepth, WW8TableNodeInfo * pPrev) + sal_uInt32 nDepth, + WW8TableNodeInfo * pPrev, + RowEndInners_t &rLastRowEnds) { SAL_INFO( "sw.ww8", "<processTableLine row=\"" << nRow << "\" depth=\"" << nDepth << "\">" ); @@ -677,7 +689,7 @@ WW8TableInfo::processTableLine(const SwTable * pTable, { const SwTableBox * pBox = rBoxes[n]; - pPrev = processTableBox(pTable, pBox, nRow, static_cast<sal_uInt32>(n), nDepth, n == rBoxes.size() - 1, pPrev); + pPrev = processTableBox(pTable, pBox, nRow, static_cast<sal_uInt32>(n), nDepth, n == rBoxes.size() - 1, pPrev, rLastRowEnds); } SAL_INFO( "sw.ww8", "</processTableLine>" ); @@ -736,6 +748,16 @@ WW8TableInfo::processTableBoxLines(const SwTableBox * pBox, return pNodeInfo; } +void updateFinalEndOfLine(RowEndInners_t &rLastRowEnds, WW8TableNodeInfo* pEndOfCellInfo) +{ + sal_Int32 nDepth = pEndOfCellInfo->getDepth(); + WW8TableNodeInfoInner::Pointer_t pInner = pEndOfCellInfo->getInnerForDepth(nDepth); + + auto aIt = rLastRowEnds.find(nDepth); + if (aIt == rLastRowEnds.end() || (pInner->getRow() > aIt->second->getRow())) + rLastRowEnds[nDepth] = pInner.get(); +} + WW8TableNodeInfo * WW8TableInfo::processTableBox(const SwTable * pTable, const SwTableBox * pBox, @@ -743,7 +765,8 @@ WW8TableInfo::processTableBox(const SwTable * pTable, sal_uInt32 nCell, sal_uInt32 nDepth, bool bEndOfLine, - WW8TableNodeInfo * pPrev) + WW8TableNodeInfo * pPrev, + RowEndInners_t &rLastRowEnds) { SAL_INFO( "sw.ww8", "<processTableBox row=\"" << nRow << "\" cell=\"" << nCell << "\" depth=\"" << nDepth << "\">" ); @@ -758,13 +781,16 @@ WW8TableInfo::processTableBox(const SwTable * pTable, pNodeInfo = processTableBoxLines(pBox, pTable, pBox, nRow, nCell, nDepth); pNodeInfo->setEndOfCell(true); if (bEndOfLine) + { pNodeInfo->setEndOfLine(true); + updateFinalEndOfLine(rLastRowEnds, pNodeInfo.get()); + } for (sal_uInt32 n = 0; n < rLines.size(); n++) { const SwTableLine * pLine = rLines[n]; - pPrev = processTableLine(pTable, pLine, n, 1, pPrev); + pPrev = processTableLine(pTable, pLine, n, 1, pPrev, rLastRowEnds); } } else @@ -788,7 +814,7 @@ WW8TableInfo::processTableBox(const SwTable * pTable, pNodeInfo = insertTableNodeInfo(&rNode, pTable, pBox, nRow, nCell, nDepth); - if (pPrev != NULL) + if (pPrev) pPrev->setNext(pNodeInfo.get()); pPrev = pNodeInfo.get(); @@ -800,7 +826,7 @@ WW8TableInfo::processTableBox(const SwTable * pTable, { nDepthInsideCell--; - if (nDepthInsideCell == 0 && pEndOfCellInfo.get() == NULL) + if (nDepthInsideCell == 0 && !pEndOfCellInfo) pEndOfCellInfo = pNodeInfo; SwEndNode * pEndNode = rNode.GetEndNode( ); @@ -818,7 +844,10 @@ WW8TableInfo::processTableBox(const SwTable * pTable, pEndOfCellInfo->setEndOfCell(true); if (bEndOfLine) + { pEndOfCellInfo->setEndOfLine(true); + updateFinalEndOfLine(rLastRowEnds, pEndOfCellInfo.get()); + } } } @@ -973,7 +1002,7 @@ bool CellInfo::operator < (const CellInfo & aCellInfo) const aRet = true; else if (height() == aCellInfo.height()) { - if (aCellInfo.getTableNodeInfo() != NULL) + if (aCellInfo.getTableNodeInfo()) { if (m_pNodeInfo == NULL) aRet = true; @@ -1011,9 +1040,8 @@ bool CellInfo::operator < (const CellInfo & aCellInfo) const } #endif -WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable) +WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds) { - WW8TableNodeInfo * pPrev = NULL; WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable); #ifdef DBG_UTIL @@ -1021,9 +1049,7 @@ WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable) #endif pCellGrid->addShadowCells(); - pPrev = pCellGrid->connectCells(); - - return pPrev; + return pCellGrid->connectCells(rLastRowEnds); } WW8TableCellGrid::WW8TableCellGrid() @@ -1138,13 +1164,13 @@ void WW8TableCellGrid::addShadowCells() nRowSpan++; } - if (pNodeInfo != NULL) + if (pNodeInfo) pRowSpans->push_back(nRowSpan); else pRowSpans->push_back(-nRowSpan); } - if (pNodeInfo != NULL) + if (pNodeInfo) { pNodeInfo->setVertMerge(bVertMerge); } @@ -1166,7 +1192,7 @@ void WW8TableCellGrid::addShadowCells() SAL_INFO( "sw.ww8", "</addShadowCells>" ); } -WW8TableNodeInfo * WW8TableCellGrid::connectCells() +WW8TableNodeInfo * WW8TableCellGrid::connectCells(RowEndInners_t &rLastRowEnds) { RowTops_t::const_iterator aTopsIt = getRowTopsBegin(); sal_uInt32 nRow = 0; @@ -1188,7 +1214,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() { long nCellX = aCellIt->left(); WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo(); - if (pNodeInfo != NULL) + if (pNodeInfo) { const SwNode * pNode = pNodeInfo->getNode(); @@ -1204,7 +1230,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() pNodeInfo->setShadowsBefore(nShadows); pNodeInfo->setCell(nCell); pNodeInfo->setRow(nRow); - if (pLastNodeInfo != NULL) + if (pLastNodeInfo) { pLastNodeInfo->setNext(pNodeInfo); pLastNodeInfo->setNextNode(pNode); @@ -1216,7 +1242,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() { nDepthInCell--; - if (nDepthInCell == 0 && pEndOfCellInfo == NULL) + if (nDepthInCell == 0 && !pEndOfCellInfo) pEndOfCellInfo = pNodeInfo; } } @@ -1229,7 +1255,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() { pWidths->push_back(aCellIt->getFormatFrmWidth()); - if (pNodeInfo != NULL) + if (pNodeInfo) pTableBoxes->push_back(pNodeInfo->getTableBox()); else pTableBoxes->push_back(NULL); @@ -1243,7 +1269,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() nCell++; bBeginningOfCell = true; - if (pEndOfCellInfo != NULL) + if (pEndOfCellInfo) { pEndOfCellInfo->setEndOfCell(true); } @@ -1254,13 +1280,14 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() pLastNodeInfo->setShadowsAfter(nShadows); - if (pEndOfCellInfo == NULL) + if (!pEndOfCellInfo) { pEndOfCellInfo = pLastNodeInfo; } pEndOfCellInfo->setEndOfCell(true); pLastNodeInfo->setEndOfLine(true); + updateFinalEndOfLine(rLastRowEnds, pLastNodeInfo); WW8TableCellGridRow::Pointer_t pRow(getRow(*aTopsIt)); pRow->setTableBoxVector(pTableBoxes); @@ -1297,7 +1324,7 @@ WW8TableNodeInfo * WW8TableCellGrid::connectCells() sResult += sBuffer; WW8TableNodeInfo * pInfo = aCellIt->getTableNodeInfo(); - if (pInfo != NULL) + if (pInfo) sResult += pInfo->toString(); else sResult += "<shadow/>\n"; diff --git a/sw/source/filter/ww8/WW8TableInfo.hxx b/sw/source/filter/ww8/WW8TableInfo.hxx index 8a3013a..722302c 100644 --- a/sw/source/filter/ww8/WW8TableInfo.hxx +++ b/sw/source/filter/ww8/WW8TableInfo.hxx @@ -58,6 +58,7 @@ class WW8TableNodeInfoInner sal_uInt32 mnShadowsBefore; sal_uInt32 mnShadowsAfter; bool mbEndOfLine; + bool mbFinalEndOfLine; bool mbEndOfCell; bool mbFirstInTable; bool mbVertMerge; @@ -77,10 +78,11 @@ public: void setShadowsBefore(sal_uInt32 nShadowsBefore); void setShadowsAfter(sal_uInt32 nShadowsAfter); void setEndOfLine(bool bEndOfLine); + void setFinalEndOfLine(bool bEndOfLine); void setEndOfCell(bool bEndOfCell); void setFirstInTable(bool bFirstInTable); - void setVertMerge(bool bVertMErge); - void setTableBox(const SwTableBox * pTableBox); + void setVertMerge(bool bVertMerge); + void setTableBox(const SwTableBox *pTableBox); void setTable(const SwTable * pTable); void setRect(const SwRect & rRect); @@ -91,6 +93,7 @@ public: sal_uInt32 getShadowsAfter() const { return mnShadowsAfter;} bool isEndOfCell() const { return mbEndOfCell;} bool isEndOfLine() const { return mbEndOfLine;} + bool isFinalEndOfLine() const { return mbFinalEndOfLine;} bool isFirstInTable() const { return mbFirstInTable;} bool isVertMerge() const; const SwTableBox * getTableBox() const { return mpTableBox;} @@ -156,6 +159,9 @@ public: typedef ::std::multiset<CellInfo, ::std::less<CellInfo> > CellInfoMultiSet; typedef boost::shared_ptr<CellInfoMultiSet> CellInfoMultiSetPtr; +typedef ::std::map<sal_uInt32, WW8TableNodeInfoInner*, + ::std::greater<sal_uInt32> > RowEndInners_t; + class WW8TableInfo; class WW8TableNodeInfo @@ -278,7 +284,7 @@ public: void insert(const SwRect & rRect, WW8TableNodeInfo * pNodeInfo, unsigned long * pFormatFrmWidth = NULL); void addShadowCells(); - WW8TableNodeInfo * connectCells(); + WW8TableNodeInfo *connectCells(RowEndInners_t &rLastRowEnds); #ifdef DBG_UTIL ::std::string toString(); @@ -305,14 +311,15 @@ class WW8TableInfo processTableLine(const SwTable * pTable, const SwTableLine * pTableLine, sal_uInt32 nRow, - sal_uInt32 nDepth, WW8TableNodeInfo * pPrev); + sal_uInt32 nDepth, WW8TableNodeInfo * pPrev, RowEndInners_t &rLastRowEnds); WW8TableNodeInfo * processTableBox(const SwTable * pTable, const SwTableBox * pTableBox, sal_uInt32 nRow, sal_uInt32 nCell, - sal_uInt32 nDepth, bool bEndOfLine, WW8TableNodeInfo * pPrev); + sal_uInt32 nDepth, bool bEndOfLine, + WW8TableNodeInfo * pPrev, RowEndInners_t &rLastRowEnds); WW8TableNodeInfo::Pointer_t processTableBoxLines(const SwTableBox * pBox, @@ -341,12 +348,12 @@ public: virtual ~WW8TableInfo(); void processSwTable(const SwTable * pTable); - WW8TableNodeInfo * processSwTableByLayout(const SwTable * pTable); + WW8TableNodeInfo * processSwTableByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds); WW8TableNodeInfo::Pointer_t getTableNodeInfo(const SwNode * pNode); const SwNode * getNextNode(const SwNode * pNode); const WW8TableNodeInfo * getFirstTableNodeInfo() const; - WW8TableNodeInfo * reorderByLayout(const SwTable * pTable); + WW8TableNodeInfo * reorderByLayout(const SwTable * pTable, RowEndInners_t &rLastRowEnds); }; } diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 79ced22..c6e980c 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -719,8 +719,6 @@ void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointe InitTableHelper( pInner ); - const size_t nLinesCount = m_xTableWrt->GetRows().size(); - // HACK // msoffice seems to have an internal limitation of 63 columns for tables // and refuses to load .docx with more, even though the spec seems to allow that; @@ -764,7 +762,7 @@ void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointe EndTableRow(); // This is the end of the table - if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount ) + if (pInner->isFinalEndOfLine()) EndTable(); } } commit c34014b97bb8afcaded8fb1a75b1fd5f89758769 Author: Caolán McNamara <caol...@redhat.com> Date: Tue Jun 9 10:11:28 2015 +0100 Resolves: more crash on export of ooo47778-3.sxw to docx This is more of the horror where the table in the frame has its cells out of visual sequence, extend the previous fix of this kind to accept cells within the original unmodified selected range Change-Id: I6e8220f712fe9de5d4b98fb3cb5ed67e3762e929 (cherry picked from commit 60f8dd78fa3f19e8bed867f7f5926fcf9a8d8e67) diff --git a/sw/qa/extras/ooxmlexport/data/ooo47778-4.odt b/sw/qa/extras/ooxmlexport/data/ooo47778-4.odt new file mode 100644 index 0000000..ae6b56b Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ooo47778-4.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 6b2fb6e..5fe36fd 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -813,12 +813,18 @@ DECLARE_OOXMLEXPORT_TEST(testSectionHeader, "sectionprot.odt") } } -DECLARE_OOXMLEXPORT_TEST(testOO47778, "ooo47778-3.odt") +DECLARE_OOXMLEXPORT_TEST(testOO47778_1, "ooo47778-3.odt") { if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) assertXPathContent(pXmlDoc, "(//w:t)[3]", "c"); } +DECLARE_OOXMLEXPORT_TEST(testOO47778_2, "ooo47778-4.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPathContent(pXmlDoc, "(//w:t)[4]", "c"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx index 6d1cd84..01a95cf 100644 --- a/sw/source/filter/ww8/wrtww8.cxx +++ b/sw/source/filter/ww8/wrtww8.cxx @@ -1720,6 +1720,8 @@ void MSWordExportBase::WriteSpecialText( sal_uLong nStart, sal_uLong nEnd, sal_u sal_uInt8 nOldTyp = m_nTextTyp; m_nTextTyp = nTTyp; SwPaM* pOldPam = m_pCurPam; //!! Simply shifting the PaM without restoring should do the job too + sal_uLong nOldStart = m_nCurStart; + sal_uLong nOldEnd = m_nCurEnd; SwPaM* pOldEnd = m_pOrigPam; bool bOldPageDescs = m_bOutPageDescs; m_bOutPageDescs = false; @@ -1731,6 +1733,8 @@ void MSWordExportBase::WriteSpecialText( sal_uLong nStart, sal_uLong nEnd, sal_u m_bOutPageDescs = bOldPageDescs; delete m_pCurPam; // delete Pam m_pCurPam = pOldPam; + m_nCurStart = nOldStart; + m_nCurEnd = nOldEnd; m_pOrigPam = pOldEnd; m_nTextTyp = nOldTyp; } @@ -1791,6 +1795,8 @@ void WW8Export::WriteChar( sal_Unicode c ) void MSWordExportBase::SetCurPam(sal_uLong nStt, sal_uLong nEnd) { + m_nCurStart = nStt; + m_nCurEnd = nEnd; m_pCurPam = Writer::NewSwPaM( *m_pDoc, nStt, nEnd ); // Recognize tables in special cases @@ -1842,6 +1848,8 @@ void MSWordExportBase::RestoreData() delete m_pCurPam; m_pCurPam = rData.pOldPam; + m_nCurStart = rData.nOldStart; + m_nCurEnd = rData.nOldEnd; m_pOrigPam = rData.pOldEnd; m_bOutTable = rData.bOldOutTable; @@ -2530,11 +2538,12 @@ class TrackContentToExport { private: SwPaM *m_pCurPam; - SwPaM m_aOrigPam; + sal_uLong m_nStart, m_nEnd; public: - TrackContentToExport(SwPaM *pCurPam) + TrackContentToExport(SwPaM *pCurPam, sal_uLong nCurStart, sal_uLong nCurEnd) : m_pCurPam(pCurPam) - , m_aOrigPam(*pCurPam, NULL) + , m_nStart(nCurStart) + , m_nEnd(nCurEnd) { } @@ -2559,8 +2568,8 @@ public: if (pNextNode && pCurrentNode != pNextNode) { - return pNextNode->GetIndex() >= m_aOrigPam.GetPoint()->nNode.GetIndex() && - pNextNode->GetIndex() < m_aOrigPam.GetMark()->nNode.GetIndex(); + return pNextNode->GetIndex() >= m_nStart && + pNextNode->GetIndex() < m_nEnd; } return false; @@ -2569,7 +2578,7 @@ public: void MSWordExportBase::WriteText() { - TrackContentToExport aContentTracking(m_pCurPam); + TrackContentToExport aContentTracking(m_pCurPam, m_nCurStart, m_nCurEnd); while (aContentTracking.contentRemainsToExport(m_pTableInfo.get())) { SwNode& rNd = m_pCurPam->GetNode(); @@ -3558,6 +3567,8 @@ MSWordExportBase::MSWordExportBase( SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM , m_bOutOutlineOnly(false) , m_bFontSizeWritten(false) , m_pDoc(pDocument) + , m_nCurStart(pCurrentPam->GetPoint()->nNode.GetIndex()) + , m_nCurEnd(pCurrentPam->GetMark()->nNode.GetIndex()) , m_pCurPam(pCurrentPam) , m_pOrigPam(pOriginalPam) { diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index 898051e..957ab28 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -437,6 +437,7 @@ struct MSWordSaveData RndStdIds eOldAnchorType; ww::bytes* pOOld; ///< WW8Export only SwPaM* pOldPam, *pOldEnd; + sal_uLong nOldStart, nOldEnd; const sw::Frame* pOldFlyFormat; const SwPageDesc* pOldPageDesc; @@ -554,6 +555,7 @@ public: bool m_bFontSizeWritten; SwDoc *m_pDoc; + sal_uLong m_nCurStart, m_nCurEnd; SwPaM *m_pCurPam, *m_pOrigPam; /// Stack to remember the nesting (see MSWordSaveData for more) commit cf079c58295be078631caa5091817f276b505c74 Author: Caolán McNamara <caol...@redhat.com> Date: Tue Jun 9 09:43:43 2015 +0100 combine duplicate code into shared method Change-Id: I76d50a135153a7022b481e4025f9b5f948ce7efa (cherry picked from commit fce7587b4deea4d79c9da695bb8f43a2a5864ce2) diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx index 6e71f61..6d1cd84 100644 --- a/sw/source/filter/ww8/wrtww8.cxx +++ b/sw/source/filter/ww8/wrtww8.cxx @@ -1724,17 +1724,7 @@ void MSWordExportBase::WriteSpecialText( sal_uLong nStart, sal_uLong nEnd, sal_u bool bOldPageDescs = m_bOutPageDescs; m_bOutPageDescs = false; // bOutKF was setted / stored in WriteKF1 - m_pCurPam = Writer::NewSwPaM( *m_pDoc, nStart, nEnd ); - - // Tabelle in Sonderbereichen erkennen - if ( ( nStart != m_pCurPam->GetMark()->nNode.GetIndex() ) && - m_pDoc->GetNodes()[ nStart ]->IsTableNode() ) - { - m_pCurPam->GetMark()->nNode = nStart; - } - - m_pOrigPam = m_pCurPam; - m_pCurPam->Exchange(); + SetCurPam(nStart, nEnd); WriteText(); @@ -1799,6 +1789,21 @@ void WW8Export::WriteChar( sal_Unicode c ) Strm().WriteUChar( c ); } +void MSWordExportBase::SetCurPam(sal_uLong nStt, sal_uLong nEnd) +{ + m_pCurPam = Writer::NewSwPaM( *m_pDoc, nStt, nEnd ); + + // Recognize tables in special cases + if ( nStt != m_pCurPam->GetMark()->nNode.GetIndex() && + m_pDoc->GetNodes()[ nStt ]->IsTableNode() ) + { + m_pCurPam->GetMark()->nNode = nStt; + } + + m_pOrigPam = m_pCurPam; + m_pCurPam->Exchange(); +} + void MSWordExportBase::SaveData( sal_uLong nStt, sal_uLong nEnd ) { MSWordSaveData aData; @@ -1820,17 +1825,7 @@ void MSWordExportBase::SaveData( sal_uLong nStt, sal_uLong nEnd ) aData.bOldStartTOX = m_bStartTOX; aData.bOldInWriteTOX = m_bInWriteTOX; - m_pCurPam = Writer::NewSwPaM( *m_pDoc, nStt, nEnd ); - - // Recognize tables in special cases - if ( nStt != m_pCurPam->GetMark()->nNode.GetIndex() && - m_pDoc->GetNodes()[ nStt ]->IsTableNode() ) - { - m_pCurPam->GetMark()->nNode = nStt; - } - - m_pOrigPam = m_pCurPam; - m_pCurPam->Exchange(); + SetCurPam(nStt, nEnd); m_bOutTable = false; // Caution: bIsInTable should not be set here diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index 2b7cdff..898051e 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -860,6 +860,8 @@ protected: const NfKeywordTable & GetNfKeywordTable(); + void SetCurPam(sal_uLong nStt, sal_uLong nEnd); + /// Populates m_vecBulletPic with all the bullet graphics used by numberings. int CollectGrfsOfBullets(); /// Write the numbering picture bullets. commit 9e0e4f54fc43eabbd235c5e5d022c18660b611ad Author: Caolán McNamara <caol...@redhat.com> Date: Mon Jun 8 10:25:13 2015 +0100 Resolves: crash on export of ooo47778-3.sxw to docx This is a horror where the table in the frame has its cells out of visual sequence, so the last row appears before the last node so on hitting the last node we have to really jump backwards to a previously skipped set of nodes to find the end of the table Change-Id: I93545e0c425267647d5f048c3bd95fe0cfddf8f3 (cherry picked from commit 89a28f54a295e1e05116176346763b16c8d187e0) diff --git a/sw/qa/extras/ooxmlexport/data/ooo47778-3.odt b/sw/qa/extras/ooxmlexport/data/ooo47778-3.odt new file mode 100644 index 0000000..69005b1 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ooo47778-3.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index f97d6a3..6b2fb6e 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -813,6 +813,12 @@ DECLARE_OOXMLEXPORT_TEST(testSectionHeader, "sectionprot.odt") } } +DECLARE_OOXMLEXPORT_TEST(testOO47778, "ooo47778-3.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport("word/document.xml")) + assertXPathContent(pXmlDoc, "(//w:t)[3]", "c"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx index c7883a6..6e71f61 100644 --- a/sw/source/filter/ww8/wrtww8.cxx +++ b/sw/source/filter/ww8/wrtww8.cxx @@ -2531,11 +2531,51 @@ void WW8Export::SectionBreaksAndFrames( const SwTextNode& rNode ) OutWW6FlyFrmsInContent( rNode ); } +class TrackContentToExport +{ +private: + SwPaM *m_pCurPam; + SwPaM m_aOrigPam; +public: + TrackContentToExport(SwPaM *pCurPam) + : m_pCurPam(pCurPam) + , m_aOrigPam(*pCurPam, NULL) + { + } + + bool contentRemainsToExport(ww8::WW8TableInfo *pTableInfo) + { + bool bSimpleContentRemains = m_pCurPam->GetPoint()->nNode < m_pCurPam->GetMark()->nNode || + (m_pCurPam->GetPoint()->nNode == m_pCurPam->GetMark()->nNode && + m_pCurPam->GetPoint()->nContent.GetIndex() <= m_pCurPam->GetMark()->nContent.GetIndex()); + if (bSimpleContentRemains) + return true; + + if (!pTableInfo) + return false; + + //An old-school table where one cell may points back to a previous node as the next cell + //so if this node is the last node in the range, we may need to jump back to a previously + //skipped cell to output it in a sane sequence. See ooo47778-3.sxw for one of these + //horrors. So if we are at the end of the selection, but this end point is a table + //cell whose next cell is in the selection allow jumping back to it + const SwNode* pCurrentNode = &m_pCurPam->GetPoint()->nNode.GetNode(); + const SwNode* pNextNode = pTableInfo->getNextNode(pCurrentNode); + + if (pNextNode && pCurrentNode != pNextNode) + { + return pNextNode->GetIndex() >= m_aOrigPam.GetPoint()->nNode.GetIndex() && + pNextNode->GetIndex() < m_aOrigPam.GetMark()->nNode.GetIndex(); + } + + return false; + } +}; + void MSWordExportBase::WriteText() { - while( m_pCurPam->GetPoint()->nNode < m_pCurPam->GetMark()->nNode || - ( m_pCurPam->GetPoint()->nNode == m_pCurPam->GetMark()->nNode && - m_pCurPam->GetPoint()->nContent.GetIndex() <= m_pCurPam->GetMark()->nContent.GetIndex() ) ) + TrackContentToExport aContentTracking(m_pCurPam); + while (aContentTracking.contentRemainsToExport(m_pTableInfo.get())) { SwNode& rNd = m_pCurPam->GetNode(); commit 47bd63e9bf9c36551c5760a9037acfd36d264827 Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 3 15:20:13 2015 +0100 fix crash on export of ooo39845-7.sxw to .docx only bump m_nFieldsInHyperlink if the field isn't erased from the stack Change-Id: Idb75d087f6fa3ce3cd399623d8ace1e7f3899b5c (cherry picked from commit 77df4faa4783df38383020a6236136a88eb51069) diff --git a/sw/qa/extras/ooxmlexport/data/ooo39845-7.odt b/sw/qa/extras/ooxmlexport/data/ooo39845-7.odt new file mode 100644 index 0000000..ee8d139 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ooo39845-7.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index 5e18937..f702fa9 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -677,6 +677,13 @@ DECLARE_OOXMLEXPORT_TEST(testOO34469, "ooo34469-1.odt") assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:hyperlink[1]", "anchor", "2.9.2.Creating New files|outline"); } +DECLARE_OOXMLEXPORT_TEST(testOO39845, "ooo39845-7.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport()) + assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:hyperlink[1]", "anchor", "Figure4|graphic"); +} + + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 629a9ae..79ced22 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -1059,9 +1059,6 @@ void DocxAttributeOutput::EndRun() { StartField_Impl( *pIt ); - if (m_startedHyperlink) - ++m_nFieldsInHyperlink; - // Remove the field from the stack if only the start has to be written // Unknown fields should be removed too if ( !pIt->bClose || ( pIt->eType == ww::eUNKNOWN ) ) @@ -1070,6 +1067,9 @@ void DocxAttributeOutput::EndRun() continue; } + if (m_startedHyperlink) + ++m_nFieldsInHyperlink; + if ( m_pHyperlinkAttrList ) { m_nFieldsInHyperlink++; commit 56ef1d03ceecf47c21b6012a733da9e9562f180b Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 3 10:20:01 2015 +0100 fix crash on export of ooo34469-1.sxw to docx Change-Id: I94a11bd24ccbc550c9fa555b1a0b5493ccd9f904 (cherry picked from commit 9d0c6308be5fb086e51cb8b4b0652f3d6184fd3c) diff --git a/sw/qa/extras/ooxmlexport/data/ooo34469-1.odt b/sw/qa/extras/ooxmlexport/data/ooo34469-1.odt new file mode 100644 index 0000000..7cf031f Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/ooo34469-1.odt differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index 9121588..5e18937 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -671,6 +671,12 @@ DECLARE_OOXMLEXPORT_TEST(testFixedDateFields, "fixed-date-field.docx") } } +DECLARE_OOXMLEXPORT_TEST(testOO34469, "ooo34469-1.odt") +{ + if (xmlDocPtr pXmlDoc = parseExport()) + assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:hyperlink[1]", "anchor", "2.9.2.Creating New files|outline"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index f6fa97a..629a9ae 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -1052,7 +1052,7 @@ void DocxAttributeOutput::EndRun() } // Write field starts - for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ) + for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin() + nFieldsInPrevHyperlink; pIt != m_Fields.end(); ) { // Add the fields starts for all but hyperlinks and TOCs if ( pIt->bOpen && pIt->pField ) @@ -1266,6 +1266,7 @@ void DocxAttributeOutput::EndRun() EndField_Impl( m_Fields.back( ) ); m_Fields.pop_back(); } + m_nFieldsInHyperlink = 0; m_pSerializer->endElementNS( XML_w, XML_hyperlink ); m_startedHyperlink = false; @@ -1274,12 +1275,15 @@ void DocxAttributeOutput::EndRun() m_closeHyperlinkInThisRun = false; } - if(!m_startedHyperlink) + if (!m_startedHyperlink) + { while ( m_Fields.begin() != m_Fields.end() ) { EndField_Impl( m_Fields.front( ) ); m_Fields.erase( m_Fields.begin( ) ); } + m_nFieldsInHyperlink = 0; + } } void DocxAttributeOutput::DoWriteBookmarks() commit 362897df5ef52b42d40550a6a896a8e1873a35ed Author: Caolán McNamara <caol...@redhat.com> Date: Tue Jun 2 16:00:59 2015 +0100 move ++m_nFieldsInHyperlink from StartField_Impl to callers no logic change at all, justs makes it clear the dubiousness of this unconditional increment Change-Id: I32e3cb2c45b1b45826a59642c33ab850d698c206 (cherry picked from commit 6d50c6ccdf85e7d01f16d3edb957eed2a4ad5e47) diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 073ec34..f6fa97a 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -1059,6 +1059,9 @@ void DocxAttributeOutput::EndRun() { StartField_Impl( *pIt ); + if (m_startedHyperlink) + ++m_nFieldsInHyperlink; + // Remove the field from the stack if only the start has to be written // Unknown fields should be removed too if ( !pIt->bClose || ( pIt->eType == ww::eUNKNOWN ) ) @@ -1124,6 +1127,9 @@ void DocxAttributeOutput::EndRun() { StartField_Impl( *pIt, true ); + if (m_startedHyperlink) + ++m_nFieldsInHyperlink; + // Remove the field if no end needs to be written if ( !pIt->bClose ) { pIt = m_Fields.erase( pIt ); @@ -1413,8 +1419,6 @@ void DocxAttributeOutput::WriteFFData( const FieldInfos& rInfos ) void DocxAttributeOutput::StartField_Impl( FieldInfos& rInfos, bool bWriteRun ) { - if ( m_startedHyperlink ) - ++m_nFieldsInHyperlink; if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN ) { // Expand unsupported fields commit b69febafa040de1e7654d3fb48b9a3357ca061e9 Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 24 10:30:28 2015 +0100 gtk3: fix 'degenerate' clip in cairo clipping fix spelling in basebmp clipping case and downgrade to INFO (cherry picked from commit 8eb8ef879320960fe2147a039bbb933484856693) Change-Id: I16ec943bd4be8ca374ded7827e4ec24e7df03e8e diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index 085933e..be86a63 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -120,10 +120,13 @@ namespace void SvpSalGraphics::clipRegion(cairo_t* cr) { + RectangleVector aRectangles; if (!m_aClipRegion.IsEmpty()) { - RectangleVector aRectangles; m_aClipRegion.GetRegionRectangles(aRectangles); + } + if (!aRectangles.empty()) + { for (RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) { cairo_rectangle(cr, aRectIter->Left(), aRectIter->Top(), aRectIter->GetWidth(), aRectIter->GetHeight()); @@ -153,6 +156,8 @@ bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight, cairo_translate(cr, 0.0, -m_aDevice->getSize().getY()); } + clipRegion(cr); + const double fTransparency = (100 - nTransparency) * (1.0/100); cairo_set_source_rgba(cr, m_aFillColor.getRed()/255.0, m_aFillColor.getGreen()/255.0, @@ -330,7 +335,7 @@ bool SvpSalGraphics::isClippedSetup( const basegfx::B2IBox &aRange, SvpSalGraphi if( nHit == 0 ) // rendering outside any clipping region { -// fprintf (stderr, "denegerate case detected ...\n"); + SAL_INFO("vcl.headless", "SvpSalGraphics::isClippedSetup: degenerate case detected ..."); return true; } else if( nHit == 1 ) // common path: rendering against just one clipping region @@ -339,10 +344,10 @@ bool SvpSalGraphics::isClippedSetup( const basegfx::B2IBox &aRange, SvpSalGraphi { //The region to be painted (aRect) is equal to or inside the //current clipping region -// fprintf (stderr, " is inside ! avoid deeper clip ...\n"); + SAL_INFO("vcl.headless", "SvpSalGraphics::isClippedSetup: is inside ! avoid deeper clip ..."); return false; } -// fprintf (stderr, " operation only overlaps with a single clip zone\n" ); + SAL_INFO("vcl.headless", "SvpSalGraphics::isClippedSetup: operation only overlaps with a single clip zone"); rUndo.m_aDevice = m_aDevice; m_aDevice = basebmp::subsetBitmapDevice( m_aOrigDevice, basegfx::B2IBox (aHitRect.Left(), commit 83484b7b0b3ab73dedced59a52426ab9178c7605 Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 24 10:09:26 2015 +0100 gtk3: move cairo region clipping to svp Change-Id: I4b4f09ee3fb7edbda3b6bb5af024c0966e3a2082 (cherry picked from commit edf56cb4300f68a3e513420feccbf8d5287a0428) diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index 43ace36..085933e 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -118,6 +118,20 @@ namespace } } +void SvpSalGraphics::clipRegion(cairo_t* cr) +{ + if (!m_aClipRegion.IsEmpty()) + { + RectangleVector aRectangles; + m_aClipRegion.GetRegionRectangles(aRectangles); + for (RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) + { + cairo_rectangle(cr, aRectIter->Left(), aRectIter->Top(), aRectIter->GetWidth(), aRectIter->GetHeight()); + } + cairo_clip(cr); + } +} + #endif bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency) diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx index 9698e3d..9b8a25a 100644 --- a/vcl/inc/headless/svpgdi.hxx +++ b/vcl/inc/headless/svpgdi.hxx @@ -212,6 +212,7 @@ public: #if ENABLE_CAIRO_CANVAS static cairo_t* createCairoContext(const basebmp::BitmapDeviceSharedPtr& rBuffer); + void clipRegion(cairo_t* cr); #endif // ENABLE_CAIRO_CANVAS diff --git a/vcl/inc/unx/gtk/gtkgdi.hxx b/vcl/inc/unx/gtk/gtkgdi.hxx index 0d02188..80de62b 100644 --- a/vcl/inc/unx/gtk/gtkgdi.hxx +++ b/vcl/inc/unx/gtk/gtkgdi.hxx @@ -61,8 +61,6 @@ public: cairo_t* getCairoContext() const; - void clipRegion(cairo_t* cr); - private: GtkWidget *mpWindow; static GtkStyleContext *mpButtonStyle; diff --git a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx index 080f6cc..84c138c 100644 --- a/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx +++ b/vcl/unx/gtk3/gdi/gtk3salnativewidgets-gtk.cxx @@ -2104,18 +2104,4 @@ cairo_t* GtkSalGraphics::getCairoContext() const return mpFrame->getCairoContext(); } -void GtkSalGraphics::clipRegion(cairo_t* cr) -{ - if (!m_aClipRegion.IsEmpty()) - { - RectangleVector aRectangles; - m_aClipRegion.GetRegionRectangles(aRectangles); - for (RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) - { - cairo_rectangle(cr, aRectIter->Left(), aRectIter->Top(), aRectIter->GetWidth(), aRectIter->GetHeight()); - } - cairo_clip(cr); - } -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 7357f6f8bff02d403e88c7e9f4a2a36d5f269fa9 Author: Caolán McNamara <caol...@redhat.com> Date: Wed Jun 24 10:07:14 2015 +0100 gtk3: alpha rects using cairo (cherry picked from commit 65d31de78dd3f5055102122e60b7261f8b170df5) Change-Id: I7fdcd6336fdc7ea8149c385a177db91ffaa61c94 stinking ancient cairo impls Change-Id: I35e826bc78556a912358dfad2fac7c45ca35bfd1 (cherry picked from commit a7a95af74badcb745bb1c86c7f9a21444ca12c77) WaE: -Werror=unused-parameter on Android Change-Id: Ie5a4015794350a513c39a60ae650f4626d92e1b8 (cherry picked from commit b28a63728ac081b3cc94c76d0bac4a573087ca5e) error: missing binary operator before token '(' Change-Id: Ieafb13245a11347cbda8a33e49ad618bf85d8a89 (cherry picked from commit 3928a1514c9202a52d698570022c197ecc8703eb) WaE: error: 'CAIRO_VERSION' is not defined Change-Id: I9e4f0d0af541226089a6295962a91ca09debb418 (cherry picked from commit b51fe01f7c8853c353401001bdd417b9ed27fb87) try harder to hide this from android tinderbox Change-Id: I586fea9f1570b68ed789da8b10a3b46216c42969 (cherry picked from commit f1761903cdafd12d4b33d4e8733971a3d9ad8a10) diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index 6811e93..43ace36 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -96,10 +96,89 @@ bool SvpSalGraphics::drawTransformedBitmap( return false; } -bool SvpSalGraphics::drawAlphaRect( long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/, sal_uInt8 /*nTransparency*/ ) +#if ENABLE_CAIRO_CANVAS + +namespace { - // TODO(P3) implement alpha blending - return false; + bool isCairoCompatible(const basebmp::BitmapDeviceSharedPtr &rBuffer) + { + if (!rBuffer) + return false; + + if (rBuffer->getScanlineFormat() != basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX) + return false; + +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 6, 0) + basegfx::B2IVector size = rBuffer->getSize(); + sal_Int32 nStride = rBuffer->getScanlineStride(); + return (cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, size.getX()) == nStride); +#else + return false; +#endif + } +} + +#endif + +bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency) +{ + bool bRet = false; + (void)nX; (void)nY; (void)nWidth; (void)nHeight; (void)nTransparency; +#if ENABLE_CAIRO_CANVAS +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 6, 0) + if (m_bUseLineColor || !m_bUseFillColor) + return bRet; + + cairo_t* cr = createCairoContext(m_aDevice); + if (!cr) + return bRet; + + if (!m_aDevice->isTopDown()) + { + cairo_scale(cr, 1, -1.0); + cairo_translate(cr, 0.0, -m_aDevice->getSize().getY()); + } + + const double fTransparency = (100 - nTransparency) * (1.0/100); + cairo_set_source_rgba(cr, m_aFillColor.getRed()/255.0, + m_aFillColor.getGreen()/255.0, + m_aFillColor.getBlue()/255.0, + fTransparency); + cairo_rectangle(cr, nX, nY, nWidth, nHeight); + + + cairo_rectangle_int_t extents; + basebmp::IBitmapDeviceDamageTrackerSharedPtr xDamageTracker(m_aDevice->getDamageTracker()); + if (xDamageTracker) + { + double x1, y1, x2, y2; + + cairo_clip_extents(cr, &x1, &y1, &x2, &y2); + extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1; + cairo_region_t *region = cairo_region_create_rectangle(&extents); + + cairo_fill_extents(cr, &x1, &y1, &x2, &y2); + extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1; + cairo_region_intersect_rectangle(region, &extents); + + cairo_region_get_extents(region, &extents); + cairo_region_destroy(region); + } + + cairo_fill(cr); + + cairo_surface_flush(cairo_get_target(cr)); + cairo_destroy(cr); // unref + + if (xDamageTracker) + { + xDamageTracker->damaged(basegfx::B2IBox(extents.x, extents.y, extents.x + extents.width, + extents.y + extents.height)); + } + bRet = true; +#endif +#endif + return bRet; } SvpSalGraphics::SvpSalGraphics() : @@ -727,32 +806,15 @@ bool SvpSalGraphics::drawEPS( long, long, long, long, void*, sal_uLong ) return false; } -#ifndef IOS - -SystemGraphicsData SvpSalGraphics::GetGraphicsData() const -{ - return SystemGraphicsData(); -} - -bool SvpSalGraphics::supportsOperation( OutDevSupportType ) const -{ - return false; -} - -#endif - #if ENABLE_CAIRO_CANVAS cairo_t* SvpSalGraphics::createCairoContext(const basebmp::BitmapDeviceSharedPtr &rBuffer) { -#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 6, 0) - if (rBuffer->getScanlineFormat() != basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX) + if (!isCairoCompatible(rBuffer)) return NULL; basegfx::B2IVector size = rBuffer->getSize(); sal_Int32 nStride = rBuffer->getScanlineStride(); - if (cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, size.getX()) != nStride) - return NULL; basebmp::RawMemorySharedArray data = rBuffer->getBuffer(); cairo_surface_t *target = @@ -763,9 +825,6 @@ cairo_t* SvpSalGraphics::createCairoContext(const basebmp::BitmapDeviceSharedPtr cairo_t* cr = cairo_create(target); cairo_surface_destroy(target); return cr; -#else - return NULL; -#endif } #endif @@ -795,4 +854,25 @@ css::uno::Any SvpSalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& /* return css::uno::Any(); } +#ifndef IOS + +SystemGraphicsData SvpSalGraphics::GetGraphicsData() const +{ + return SystemGraphicsData(); +} + +bool SvpSalGraphics::supportsOperation(OutDevSupportType eType) const +{ +#if ENABLE_CAIRO_CANVAS + return m_aDrawMode != basebmp::DrawMode_XOR && + OutDevSupport_TransparentRect == eType && + isCairoCompatible(m_aDevice); +#else + (void)eType; + return false; +#endif +} + +#endif + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit bb7687b295367ad7572af130298a03d7915625d4 Author: Caolán McNamara <caol...@redhat.com> Date: Tue Jun 23 20:33:18 2015 +0100 gtk3: move createCairoContext down to svpgdi (cherry picked from commit 253c0f073715b1d0f6ba063b1182016e45951bf4) Change-Id: Ib3c6d6689c4b79a636a3f2f0f985f3573aa46f3d cairo_format_stride_for_width is 1.6 onwards (cherry picked from commit 5ce9954c5ec244b9a858ab7e996d5201a21dc3fe) Change-Id: Ic233b4b6c7067f2473eb76b0c7e520cfe1dfcd14 diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index a41626f..6811e93 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -32,6 +32,10 @@ #include <basegfx/polygon/b2dpolygontools.hxx> #include <basebmp/scanlineformats.hxx> +#if ENABLE_CAIRO_CANVAS +#include <cairo.h> +#endif + #if OSL_DEBUG_LEVEL > 2 #include <basebmp/debug.hxx> #include <fstream> @@ -737,6 +741,35 @@ bool SvpSalGraphics::supportsOperation( OutDevSupportType ) const #endif +#if ENABLE_CAIRO_CANVAS + +cairo_t* SvpSalGraphics::createCairoContext(const basebmp::BitmapDeviceSharedPtr &rBuffer) +{ +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 6, 0) + if (rBuffer->getScanlineFormat() != basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX) + return NULL; + + basegfx::B2IVector size = rBuffer->getSize(); + sal_Int32 nStride = rBuffer->getScanlineStride(); + if (cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, size.getX()) != nStride) + return NULL; + + basebmp::RawMemorySharedArray data = rBuffer->getBuffer(); + cairo_surface_t *target = + cairo_image_surface_create_for_data(data.get(), + CAIRO_FORMAT_RGB24, + size.getX(), size.getY(), + nStride); + cairo_t* cr = cairo_create(target); + cairo_surface_destroy(target); + return cr; +#else + return NULL; +#endif +} + +#endif + bool SvpSalGraphics::SupportsCairo() const { return false; diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx index 297d28a..9698e3d 100644 --- a/vcl/inc/headless/svpgdi.hxx +++ b/vcl/inc/headless/svpgdi.hxx @@ -24,6 +24,7 @@ #include <basebmp/color.hxx> #include <vcl/sysdata.hxx> #include <vcl/metric.hxx> +#include <config_cairo_canvas.h> #include "salgdi.hxx" #include "sallayout.hxx" @@ -35,6 +36,7 @@ class GlyphCache; class ServerFont; +typedef struct _cairo cairo_t; class VCL_DLLPUBLIC SvpSalGraphics : public SalGraphics { @@ -207,6 +209,12 @@ public: virtual SystemFontData GetSysFontData( int nFallbacklevel ) const SAL_OVERRIDE; +#if ENABLE_CAIRO_CANVAS + + static cairo_t* createCairoContext(const basebmp::BitmapDeviceSharedPtr& rBuffer); + +#endif // ENABLE_CAIRO_CANVAS + virtual void BeginPaint() SAL_OVERRIDE { }; virtual void EndPaint() SAL_OVERRIDE { }; }; diff --git a/vcl/unx/gtk/window/gtksalframe.cxx b/vcl/unx/gtk/window/gtksalframe.cxx index 98c02f2..99adfff 100644 --- a/vcl/unx/gtk/window/gtksalframe.cxx +++ b/vcl/unx/gtk/window/gtksalframe.cxx @@ -3550,17 +3550,8 @@ gboolean GtkSalFrame::signalCrossing( GtkWidget*, GdkEventCrossing* pEvent, gpoi cairo_t* GtkSalFrame::getCairoContext() const { - basebmp::RawMemorySharedArray data = m_aFrame->getBuffer(); - basegfx::B2IVector size = m_aFrame->getSize(); - sal_Int32 nStride = m_aFrame->getScanlineStride(); - assert(cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, size.getX()) == nStride); - cairo_surface_t *target = - cairo_image_surface_create_for_data(data.get(), - CAIRO_FORMAT_RGB24, - size.getX(), size.getY(), - nStride); - cairo_t* cr = cairo_create(target); - cairo_surface_destroy(target); + cairo_t* cr = SvpSalGraphics::createCairoContext(m_aFrame); + assert(cr); return cr; }
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits