[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-4.1' - 13 commits - basegfx/source binaryurp/source canvas/source cppcanvas/source filter/source i18npool/source include/basegfx sfx2/source sw/source vcl/aqua vcl/source vcl/unx

Stephan Bergmann sbergman at redhat.com
Wed Nov 27 07:32:47 PST 2013


 basegfx/source/polygon/b2dlinegeometry.cxx          |    7 
 binaryurp/source/reader.cxx                         |   10 
 canvas/source/cairo/cairo_canvashelper.cxx          |    2 
 cppcanvas/source/inc/implrenderer.hxx               |   10 
 cppcanvas/source/mtfrenderer/emfplus.cxx            |  376 ++++++++++++++++++--
 filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx |    7 
 i18npool/source/search/textsearch.cxx               |   26 +
 include/basegfx/polygon/b2dlinegeometry.hxx         |    7 
 sfx2/source/doc/docfile.cxx                         |   21 -
 sw/source/core/text/itrcrsr.cxx                     |    2 
 vcl/aqua/source/window/salframeview.mm              |   37 +
 vcl/source/filter/wmf/winmtf.cxx                    |   33 -
 vcl/source/filter/wmf/winmtf.hxx                    |    1 
 vcl/source/filter/wmf/winwmf.cxx                    |    1 
 vcl/unx/gtk/window/gtksalframe.cxx                  |   67 ++-
 15 files changed, 491 insertions(+), 116 deletions(-)

New commits:
commit 8b811311998a24ff2fdee87ae4ac617d1422a0c8
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Wed Nov 27 14:49:22 2013 +0100

    binaryurp: silently ignore superfluous MUSTREPLY/SYNCHRONOUS flags
    
    ...in a non-oneway call.  This can happen when a pre LO 4 entity is calling a
    LO 4 entity post 90eac3e69749a9227c4b6902b1f3cef1e338c6d1
    "API CHANGE remove [oneway] method attributes."  (See mail thread starting at
    <http://mail-archives.apache.org/mod_mbox/openoffice-api/201311.mbox/%3Ca4e7f34d-b8cb-4d5a-890f-6894d3410265%40ucimail2.uci.cu%3E>
    "hi, code in Java.")
    
    Change-Id: I9f800a979d84a95cc5cd96f75ee7472e8cf6cf4b
    (cherry picked from commit 289e54feabc936b8175327355a159073830a326a)

diff --git a/binaryurp/source/reader.cxx b/binaryurp/source/reader.cxx
index 522b165..184f037 100644
--- a/binaryurp/source/reader.cxx
+++ b/binaryurp/source/reader.cxx
@@ -238,12 +238,10 @@ void Reader::readMessage(Unmarshal & unmarshal) {
     {
         synchronous = forceSynchronous;
     } else {
-        if (forceSynchronous) {
-            throw css::uno::RuntimeException(
-                ("URP: synchronous request message with non-oneway function ID"
-                 " received"),
-                css::uno::Reference< css::uno::XInterface >());
-        }
+        SAL_INFO_IF(
+            forceSynchronous, "binaryurp",
+            ("superfluous MUSTREPLY/SYNCHRONOUS ignored in request message with"
+             " non-oneway function ID"));
         synchronous = true;
     }
     bool setter = false;
commit 910896cb8825a57a22154cc215ca6fe9375d6e9e
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Wed Nov 27 13:11:04 2013 +0100

    cairo canvas: Line dashing size depends on the line width.
    
    Change-Id: I6a3f563b6effd37b448ec3e8463a87879e0566d4
    Reviewed-on: https://gerrit.libreoffice.org/6833
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx
index ca75d35..5953495 100644
--- a/canvas/source/cairo/cairo_canvashelper.cxx
+++ b/canvas/source/cairo/cairo_canvashelper.cxx
@@ -1230,7 +1230,7 @@ namespace cairocanvas
             {
                 double* pDashArray = new double[ strokeAttributes.DashArray.getLength() ];
                 for( sal_Int32 i=0; i<strokeAttributes.DashArray.getLength(); i++ )
-                    pDashArray[i]=strokeAttributes.DashArray[i];
+                    pDashArray[i] = strokeAttributes.DashArray[i] * w;
                 cairo_set_dash( mpCairo.get(), pDashArray, strokeAttributes.DashArray.getLength(), 0 );
                 delete[] pDashArray;
             }
commit 0d39ee6acd420421aa5c396885584b7bca805f25
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Wed Nov 27 11:51:32 2013 +0100

    EMF+: Line thickness has to be considered when drawing the caps.
    
    Change-Id: I6043ee3c214f453afaef06125993c73be624c07e
    Reviewed-on: https://gerrit.libreoffice.org/6832
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/basegfx/source/polygon/b2dlinegeometry.cxx b/basegfx/source/polygon/b2dlinegeometry.cxx
index 5c016bb..417944d 100644
--- a/basegfx/source/polygon/b2dlinegeometry.cxx
+++ b/basegfx/source/polygon/b2dlinegeometry.cxx
@@ -44,7 +44,8 @@ namespace basegfx
             double fWidth,
             double fCandidateLength,
             double fDockingPosition, // 0->top, 1->bottom
-            double* pConsumedLength)
+            double* pConsumedLength,
+            double fShift)
         {
             B2DPolyPolygon aRetval;
             OSL_ENSURE(rCandidate.count() > 1L, "createAreaGeometryForLineStartEnd: Line polygon has too less points (!)");
@@ -89,7 +90,7 @@ namespace basegfx
                 const double fArrowYLength(B2DVector(aUpperCenter).getLength());
 
                 // move arrow to have docking position centered
-                aArrowTransform.translate(0.0, -fArrowYLength * fDockingPosition);
+                aArrowTransform.translate(0.0, -fArrowYLength * fDockingPosition + fShift);
 
                 // prepare polygon length
                 if(fTools::equalZero(fCandidateLength))
@@ -98,7 +99,7 @@ namespace basegfx
                 }
 
                 // get the polygon vector we want to plant this arrow on
-                const double fConsumedLength(fArrowYLength * (1.0 - fDockingPosition));
+                const double fConsumedLength(fArrowYLength * (1.0 - fDockingPosition) - fShift);
                 const B2DVector aHead(rCandidate.getB2DPoint((bStart) ? 0L : rCandidate.count() - 1L));
                 const B2DVector aTail(getPositionAbsolute(rCandidate,
                     (bStart) ? fConsumedLength : fCandidateLength - fConsumedLength, fCandidateLength));
diff --git a/cppcanvas/source/inc/implrenderer.hxx b/cppcanvas/source/inc/implrenderer.hxx
index 270c0de..d602945 100644
--- a/cppcanvas/source/inc/implrenderer.hxx
+++ b/cppcanvas/source/inc/implrenderer.hxx
@@ -282,7 +282,8 @@ static float GetSwapFloat( SvStream& rSt )
             double setFont( sal_uInt8 objectId, const ActionFactoryParameters& rParms, OutDevState& rState );
 
             /// Render LineCap, like the start or end arrow of a polygon.
-            void EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
+            /// @return how much we should shorten the original polygon.
+            double EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
                     const ::basegfx::B2DPolyPolygon& rLineCap, bool bStart,
                     const com::sun::star::rendering::StrokeAttributes& rAttributes,
                     const ActionFactoryParameters& rParms, OutDevState& rState);
diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index 469e83c..a289610 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -1320,13 +1320,12 @@ namespace cppcanvas
             }
         }
 
-
-        void ImplRenderer::EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
+        double ImplRenderer::EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
                 const ::basegfx::B2DPolyPolygon& rLineCap, bool bStart, const rendering::StrokeAttributes& rAttributes,
                 const ActionFactoryParameters& rParms, OutDevState& rState)
         {
             if (!rLineCap.count())
-                return;
+                return 0.0;
 
             // it seems the line caps in EMF+ are 4*larger than what
             // LibreOffice expects, and the mapping in
@@ -1338,7 +1337,7 @@ namespace cppcanvas
 
             basegfx::B2DPolyPolygon aArrow(basegfx::tools::createAreaGeometryForLineStartEnd(
                         rPolygon, rLineCap, bStart,
-                        fWidth, fPolyLength, 0.0, NULL));
+                        fWidth, fPolyLength, 0, NULL, rAttributes.StrokeWidth));
 
             // createAreaGeometryForLineStartEnd from some reason always sets
             // the path as closed, correct it
@@ -1350,6 +1349,8 @@ namespace cppcanvas
                 maActions.push_back(MtfAction(pAction, rParms.mrCurrActionIndex));
                 rParms.mrCurrActionIndex += pAction->getActionCount()-1;
             }
+
+            return rAttributes.StrokeWidth;
         }
 
         void ImplRenderer::EMFPPlusDrawPolygon (const ::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
@@ -1379,49 +1380,59 @@ namespace cppcanvas
                 rendering::StrokeAttributes aPolygonAttributes(aCommonAttributes);
                 pen->SetStrokeDashing(aPolygonAttributes);
 
-                // render the polygon
-                ActionSharedPtr pPolyAction(internal::PolyPolyActionFactory::createPolyPolyAction(aPolyPolygon, rParms.mrCanvas, rState, aPolygonAttributes));
-                if( pPolyAction )
-                {
-                    maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex));
-                    rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
-                }
+                basegfx::B2DPolyPolygon aFinalPolyPolygon;
 
-                // render line starts & ends
-                if (pen->customStartCap || pen->customEndCap)
+                // render line starts & ends if present
+                if (!pen->customStartCap && !pen->customEndCap)
+                    aFinalPolyPolygon = aPolyPolygon;
+                else
                 {
                     for (sal_uInt32 i = 0; i < aPolyPolygon.count(); ++i)
                     {
-                        // break the polypolygon into polygons
                         basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(i));
 
-                        if (aPolygon.isClosed())
-                            continue;
+                        if (!aPolygon.isClosed())
+                        {
+                            double fStart = 0.0;
+                            double fEnd = 0.0;
+                            double fPolyLength = basegfx::tools::getLength(aPolygon);
 
-                        double fPolyLength = basegfx::tools::getLength(aPolygon);
+                            // line start
+                            if (pen->customStartCap)
+                            {
+                                rendering::StrokeAttributes aAttributes(aCommonAttributes);
+                                pen->customStartCap->SetAttributes(aAttributes);
 
-                        // line start
-                        if (pen->customStartCap)
-                        {
-                            rendering::StrokeAttributes aAttributes(aCommonAttributes);
-                            pen->customStartCap->SetAttributes(aAttributes);
+                                fStart = EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customStartCap->polygon,
+                                        true, aAttributes, rParms, rState);
+                            }
 
-                            EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customStartCap->polygon,
-                                    true, aAttributes, rParms, rState);
-                        }
+                            // line end
+                            if (pen->customEndCap)
+                            {
+                                rendering::StrokeAttributes aAttributes(aCommonAttributes);
+                                pen->customEndCap->SetAttributes(aAttributes);
 
-                        // line end
-                        if (pen->customEndCap)
-                        {
-                            rendering::StrokeAttributes aAttributes(aCommonAttributes);
-                            pen->customEndCap->SetAttributes(aAttributes);
+                                fEnd = EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customEndCap->polygon,
+                                        false, aAttributes, rParms, rState);
+                            }
 
-                            EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customEndCap->polygon,
-                                    false, aAttributes, rParms, rState);
+                            // build new poly, consume something from the old poly
+                            if (fStart != 0.0 || fEnd != 0.0)
+                                aPolygon = basegfx::tools::getSnippetAbsolute(aPolygon, fStart, fPolyLength - fEnd, fPolyLength);
                         }
+
+                        aFinalPolyPolygon.append(aPolygon);
                     }
                 }
 
+                // finally render the polygon
+                ActionSharedPtr pPolyAction(internal::PolyPolyActionFactory::createPolyPolyAction(aFinalPolyPolygon, rParms.mrCanvas, rState, aPolygonAttributes));
+                if( pPolyAction )
+                {
+                    maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex));
+                    rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
+                }
             }
         }
 
diff --git a/include/basegfx/polygon/b2dlinegeometry.hxx b/include/basegfx/polygon/b2dlinegeometry.hxx
index 934158f..62e230f 100644
--- a/include/basegfx/polygon/b2dlinegeometry.hxx
+++ b/include/basegfx/polygon/b2dlinegeometry.hxx
@@ -63,6 +63,10 @@ namespace basegfx
             again calculating the length (which may be expensive with beziers). If 0.0 is
             given, the length is calculated on demand.
 
+            @param fShift
+            When it is necessary to count with the thickness of the line, it
+            makes sense to move the start position slightly - so define the shift.
+
             @return
             The Line start and end polygon, correctly rotated and scaled
         */
@@ -73,7 +77,8 @@ namespace basegfx
             double fWidth,
             double fCandidateLength = 0.0, // 0.0 -> calculate self
             double fDockingPosition = 0.5, // 0->top, 1->bottom
-            double* pConsumedLength = 0L);
+            double* pConsumedLength = 0L,
+            double fShift = 0.0);
 
         /** create filled polygon geometry for lines with a line width
 
commit 75db5c966215b678acc56f9f1be1a1b823ff763c
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Fri Nov 22 17:06:10 2013 +0100

    EMF+: Parse and render custom line cap data.
    
    Contains the following commits:
    
    * EMF+: Small cleanup & more logging in preparation for line starts & ends.
    * EMF+: Parse custom line cap data for start and end line caps.
    * EMF+: Render custom line cap data.
    * EMF+: Set the stroke attributes on the custom line caps.
    
    Change-Id: Ibdf69c7944e4d027d9dc6974bd740f9b70fb5079
    Reviewed-on: https://gerrit.libreoffice.org/6831
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/cppcanvas/source/inc/implrenderer.hxx b/cppcanvas/source/inc/implrenderer.hxx
index 79a2967..270c0de 100644
--- a/cppcanvas/source/inc/implrenderer.hxx
+++ b/cppcanvas/source/inc/implrenderer.hxx
@@ -280,7 +280,14 @@ static float GetSwapFloat( SvStream& rSt )
             /* EMF+ */
             void processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms, OutDevState& rState, const CanvasSharedPtr& rCanvas );
             double setFont( sal_uInt8 objectId, const ActionFactoryParameters& rParms, OutDevState& rState );
-            void EMFPPlusDrawPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex);
+
+            /// Render LineCap, like the start or end arrow of a polygon.
+            void EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
+                    const ::basegfx::B2DPolyPolygon& rLineCap, bool bStart,
+                    const com::sun::star::rendering::StrokeAttributes& rAttributes,
+                    const ActionFactoryParameters& rParms, OutDevState& rState);
+
+            void EMFPPlusDrawPolygon (const ::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex);
             void EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor);
 
             ActionVector maActions;
diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index 07a65be..469e83c 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -28,6 +28,7 @@
 #include <basegfx/vector/b2dsize.hxx>
 #include <basegfx/range/b2drange.hxx>
 #include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
 #include <basegfx/polygon/b2dpolygontools.hxx>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
@@ -36,8 +37,10 @@
 #include <rtl/ustring.hxx>
 #include <sal/alloca.h>
 
-#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
 #include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
 
 #include <bitmapaction.hxx>
 #include <implrenderer.hxx>
@@ -96,6 +99,22 @@ const sal_Int32 EmfPlusLineStyleDashDot = 0x00000003;
 const sal_Int32 EmfPlusLineStyleDashDotDot = 0x00000004;
 const sal_Int32 EmfPlusLineStyleCustom = 0x00000005;
 
+const sal_uInt32 EmfPlusCustomLineCapDataTypeDefault = 0x00000000;
+const sal_uInt32 EmfPlusCustomLineCapDataTypeAdjustableArrow = 0x00000001;
+
+const sal_uInt32 EmfPlusCustomLineCapDataFillPath = 0x00000001;
+const sal_uInt32 EmfPlusCustomLineCapDataLinePath = 0x00000002;
+
+const sal_uInt32 EmfPlusLineCapTypeFlat = 0x00000000;
+const sal_uInt32 EmfPlusLineCapTypeSquare = 0x00000001;
+const sal_uInt32 EmfPlusLineCapTypeRound = 0x00000002;
+const sal_uInt32 EmfPlusLineCapTypeTriangle = 0x00000003;
+
+const sal_uInt32 EmfPlusLineJoinTypeMiter = 0x00000000;
+const sal_uInt32 EmfPlusLineJoinTypeBevel = 0x00000001;
+const sal_uInt32 EmfPlusLineJoinTypeRound = 0x00000002;
+const sal_uInt32 EmfPlusLineJoinTypeMiterClipped = 0x00000003;
+
 using namespace ::com::sun::star;
 using namespace ::basegfx;
 
@@ -587,6 +606,137 @@ namespace cppcanvas
             }
         };
 
+        /// Convert stroke caps between EMF+ and rendering API
+        sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
+        {
+            switch (nEmfStroke)
+            {
+                case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE;
+                case EmfPlusLineCapTypeRound:  return rendering::PathCapType::ROUND;
+            }
+
+            // we have no mapping for EmfPlusLineCapTypeTriangle, so return
+            // BUTT always
+            return rendering::PathCapType::BUTT;
+        }
+
+        struct EMFPCustomLineCap : public EMFPObject
+        {
+            sal_uInt32 type;
+            sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
+            float miterLimit;
+            basegfx::B2DPolyPolygon polygon;
+
+        public:
+            EMFPCustomLineCap() : EMFPObject()
+            {
+            }
+
+            ~EMFPCustomLineCap()
+            {
+            }
+
+            void SetAttributes(rendering::StrokeAttributes& aAttributes)
+            {
+                aAttributes.StartCapType = lcl_convertStrokeCap(strokeStartCap);
+                aAttributes.EndCapType = lcl_convertStrokeCap(strokeEndCap);
+
+                switch (strokeJoin)
+                {
+                    case EmfPlusLineJoinTypeMiter:        // fall-through
+                    case EmfPlusLineJoinTypeMiterClipped: aAttributes.JoinType = rendering::PathJoinType::MITER; break;
+                    case EmfPlusLineJoinTypeBevel:        aAttributes.JoinType = rendering::PathJoinType::BEVEL; break;
+                    case EmfPlusLineJoinTypeRound:        aAttributes.JoinType = rendering::PathJoinType::ROUND; break;
+                }
+
+                aAttributes.MiterLimit = miterLimit;
+            }
+
+            void ReadPath(SvStream& s, ImplRenderer& rR, bool bClosed)
+            {
+                sal_Int32 pathLength;
+                s >> pathLength;
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
+
+                sal_uInt32 pathHeader;
+                sal_Int32 pathPoints, pathFlags;
+                s >> pathHeader >> pathPoints >> pathFlags;
+
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)");
+                SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
+
+                EMFPPath path(pathPoints);
+                path.Read(s, pathFlags, rR);
+
+                polygon = path.GetPolygon(rR, false);
+                polygon.setClosed(bClosed);
+
+                // transformation to convert the path to what LibreOffice
+                // expects
+                B2DHomMatrix aMatrix;
+                aMatrix.scale(1.0, -1.0);
+
+                polygon.transform(aMatrix);
+            };
+
+            void Read (SvStream& s, ImplRenderer& rR)
+            {
+                sal_uInt32 header;
+
+                s >> header >> type;
+
+                SAL_INFO("cppcanvas.emf", "EMF+\t\tcustom cap");
+                SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec);
+
+                if (type == EmfPlusCustomLineCapDataTypeDefault)
+                {
+                    sal_uInt32 customLineCapDataFlags, baseCap;
+                    float baseInset;
+                    float widthScale;
+                    float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
+
+                    s >> customLineCapDataFlags >> baseCap >> baseInset
+                      >> strokeStartCap >> strokeEndCap >> strokeJoin
+                      >> miterLimit >> widthScale
+                      >> fillHotSpotX >> fillHotSpotY >> strokeHotSpotX >> strokeHotSpotY;
+
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseInset: " << baseInset);
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tmiterLimit: " << miterLimit);
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\twidthScale: " << widthScale);
+
+                    if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
+                    {
+                        ReadPath(s, rR, true);
+                    }
+
+                    if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
+                    {
+                        ReadPath(s, rR, false);
+                    }
+                }
+                else if (type == EmfPlusCustomLineCapDataTypeAdjustableArrow)
+                {
+                    // TODO only reads the data, does not use them [I've had
+                    // no test document to be able to implement it]
+
+                    sal_Int32 width, height, middleInset, fillState, lineStartCap;
+                    sal_Int32 lineEndCap, lineJoin, widthScale;
+                    float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY;
+
+                    s >> width >> height >> middleInset >> fillState >> lineStartCap
+                      >> lineEndCap >> lineJoin >> miterLimit >> widthScale
+                      >> fillHotSpotX >> fillHotSpotY >> lineHotSpotX >> lineHotSpotY;
+
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
+                }
+            }
+        };
+
         struct EMFPPen : public EMFPBrush
         {
             XForm transformation;
@@ -604,16 +754,28 @@ namespace cppcanvas
             sal_Int32 compoundArrayLen;
             float *compoundArray;
             sal_Int32 customStartCapLen;
-            sal_uInt8 *customStartCap;
+            EMFPCustomLineCap *customStartCap;
             sal_Int32 customEndCapLen;
-            sal_uInt8 *customEndCap;
+            EMFPCustomLineCap *customEndCap;
 
         public:
             EMFPPen () : EMFPBrush ()
             {
+                dashPattern = NULL;
+                compoundArray = NULL;
+                customStartCap = NULL;
+                customEndCap = NULL;
             }
 
-            void SetStrokeAttributes (rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
+            ~EMFPPen ()
+            {
+                delete[] dashPattern;
+                delete[] compoundArray;
+                delete customStartCap;
+                delete customEndCap;
+            }
+
+            void SetStrokeWidth(rendering::StrokeAttributes& rStrokeAttributes, ImplRenderer& rR, const OutDevState& rState)
             {
 #if OSL_DEBUG_LEVEL > 1
                 if (width == 0.0) {
@@ -621,8 +783,10 @@ namespace cppcanvas
                 }
 #endif
                 rStrokeAttributes.StrokeWidth = fabs((rState.mapModeTransform * rR.MapSize (width == 0.0 ? 0.05 : width, 0)).getX());
+            }
 
-                // set dashing
+            void SetStrokeDashing(rendering::StrokeAttributes& rStrokeAttributes)
+            {
                 if (dashStyle != EmfPlusLineStyleSolid)
                 {
                     const float dash[] = {3, 3};
@@ -666,12 +830,18 @@ namespace cppcanvas
                     s >> transformation;
 
                 if (penFlags & 2)
+                {
                     s >> startCap;
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tstartCap: 0x" << std::hex << startCap);
+                }
                 else
                     startCap = 0;
 
                 if (penFlags & 4)
+                {
                     s >> endCap;
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tendCap: 0x" << std::hex << endCap);
+                }
                 else
                     endCap = 0;
 
@@ -737,24 +907,34 @@ namespace cppcanvas
                 } else
                     compoundArrayLen = 0;
 
-                if (penFlags & 2048) {
+                if (penFlags & 2048)
+                {
                     s >> customStartCapLen;
-                    if( customStartCapLen<0 )
-                        customStartCapLen=0;
-                    customStartCap = new sal_uInt8 [customStartCapLen];
-                    for (i = 0; i < customStartCapLen; i++)
-                        s >> customStartCap [i];
-                } else
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomStartCapLen: " << customStartCapLen);
+                    sal_uInt32 pos = s.Tell();
+
+                    customStartCap = new EMFPCustomLineCap();
+                    customStartCap->Read(s, rR);
+
+                    // maybe we don't read everything yet, play it safe ;-)
+                    s.Seek(pos + customStartCapLen);
+                }
+                else
                     customStartCapLen = 0;
 
-                if (penFlags & 4096) {
+                if (penFlags & 4096)
+                {
                     s >> customEndCapLen;
-                    if( customEndCapLen<0 )
-                        customEndCapLen=0;
-                    customEndCap = new sal_uInt8 [customEndCapLen];
-                    for (i = 0; i < customEndCapLen; i++)
-                        s >> customEndCap [i];
-                } else
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomEndCapLen: " << customEndCapLen);
+                    sal_uInt32 pos = s.Tell();
+
+                    customEndCap = new EMFPCustomLineCap();
+                    customEndCap->Read(s, rR);
+
+                    // maybe we don't read everything yet, play it safe ;-)
+                    s.Seek(pos + customEndCapLen);
+                }
+                else
                     customEndCapLen = 0;
 
                 EMFPBrush::Read (s, rR);
@@ -1140,7 +1320,39 @@ namespace cppcanvas
             }
         }
 
-        void ImplRenderer::EMFPPlusDrawPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
+
+        void ImplRenderer::EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
+                const ::basegfx::B2DPolyPolygon& rLineCap, bool bStart, const rendering::StrokeAttributes& rAttributes,
+                const ActionFactoryParameters& rParms, OutDevState& rState)
+        {
+            if (!rLineCap.count())
+                return;
+
+            // it seems the line caps in EMF+ are 4*larger than what
+            // LibreOffice expects, and the mapping in
+            // createAreaGeometryForLineStartEnd scales that down, so
+            // correct it
+            // [unfortunately found no proof for this in the spec :-( - please
+            // feel free to correct this if it causes trouble]
+            double fWidth = rAttributes.StrokeWidth*4;
+
+            basegfx::B2DPolyPolygon aArrow(basegfx::tools::createAreaGeometryForLineStartEnd(
+                        rPolygon, rLineCap, bStart,
+                        fWidth, fPolyLength, 0.0, NULL));
+
+            // createAreaGeometryForLineStartEnd from some reason always sets
+            // the path as closed, correct it
+            aArrow.setClosed(rLineCap.isClosed());
+
+            ActionSharedPtr pAction(internal::PolyPolyActionFactory::createPolyPolyAction(aArrow, rParms.mrCanvas, rState, rAttributes));
+            if (pAction)
+            {
+                maActions.push_back(MtfAction(pAction, rParms.mrCurrActionIndex));
+                rParms.mrCurrActionIndex += pAction->getActionCount()-1;
+            }
+        }
+
+        void ImplRenderer::EMFPPlusDrawPolygon (const ::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
                                                 OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex)
         {
             EMFPPen* pen = (EMFPPen*) aObjects [penIndex & 0xff];
@@ -1154,24 +1366,62 @@ namespace cppcanvas
                 rState.lineColor = ::vcl::unotools::colorToDoubleSequence (pen->GetColor (),
                                                                            rCanvas->getUNOCanvas ()->getDevice()->getDeviceColorSpace());
 
-                polygon.transform( rState.mapModeTransform );
-                rendering::StrokeAttributes aStrokeAttributes;
+                basegfx::B2DPolyPolygon aPolyPolygon(polygon);
+                aPolyPolygon.transform(rState.mapModeTransform);
+                rendering::StrokeAttributes aCommonAttributes;
 
-                pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
+                // some attributes are common for the polygon, and the line
+                // starts & ends - like the stroke width
+                pen->SetStrokeWidth(aCommonAttributes, *this, rState);
 
-                ActionSharedPtr pPolyAction(
-                                            internal::PolyPolyActionFactory::createPolyPolyAction(
-                                                                                                  polygon, rParms.mrCanvas, rState, aStrokeAttributes ) );
+                // but eg. dashing has to be additionally set only on the
+                // polygon
+                rendering::StrokeAttributes aPolygonAttributes(aCommonAttributes);
+                pen->SetStrokeDashing(aPolygonAttributes);
 
+                // render the polygon
+                ActionSharedPtr pPolyAction(internal::PolyPolyActionFactory::createPolyPolyAction(aPolyPolygon, rParms.mrCanvas, rState, aPolygonAttributes));
                 if( pPolyAction )
                 {
-                    maActions.push_back(
-                                        MtfAction(
-                                                  pPolyAction,
-                                                  rParms.mrCurrActionIndex ) );
-
+                    maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex));
                     rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
                 }
+
+                // render line starts & ends
+                if (pen->customStartCap || pen->customEndCap)
+                {
+                    for (sal_uInt32 i = 0; i < aPolyPolygon.count(); ++i)
+                    {
+                        // break the polypolygon into polygons
+                        basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(i));
+
+                        if (aPolygon.isClosed())
+                            continue;
+
+                        double fPolyLength = basegfx::tools::getLength(aPolygon);
+
+                        // line start
+                        if (pen->customStartCap)
+                        {
+                            rendering::StrokeAttributes aAttributes(aCommonAttributes);
+                            pen->customStartCap->SetAttributes(aAttributes);
+
+                            EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customStartCap->polygon,
+                                    true, aAttributes, rParms, rState);
+                        }
+
+                        // line end
+                        if (pen->customEndCap)
+                        {
+                            rendering::StrokeAttributes aAttributes(aCommonAttributes);
+                            pen->customEndCap->SetAttributes(aAttributes);
+
+                            EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customEndCap->polygon,
+                                    false, aAttributes, rParms, rState);
+                        }
+                    }
+                }
+
             }
         }
 
@@ -1545,7 +1795,7 @@ namespace cppcanvas
 
                             rendering::StrokeAttributes aStrokeAttributes;
 
-                            pen->SetStrokeAttributes (aStrokeAttributes, *this, rState);
+                            pen->SetStrokeWidth (aStrokeAttributes, *this, rState);
 
                             ActionSharedPtr pPolyAction(
                                 internal::PolyPolyActionFactory::createPolyPolyAction(
commit 9855f15083faa73c3fa88b2ad084ac9c1aac1aa5
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Fri Nov 22 12:01:15 2013 +0100

    EMF+: Implement line dashing.
    
    Change-Id: I9eb21c0a8b5baa5b0080845f61b12fc65034d959
    Reviewed-on: https://gerrit.libreoffice.org/6830
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index afba7f1..07a65be 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -89,6 +89,13 @@
 
 #define EmfPlusRegionInitialStateInfinite 0x10000003
 
+const sal_Int32 EmfPlusLineStyleSolid = 0x00000000;
+const sal_Int32 EmfPlusLineStyleDash = 0x00000001;
+const sal_Int32 EmfPlusLineStyleDot = 0x00000002;
+const sal_Int32 EmfPlusLineStyleDashDot = 0x00000003;
+const sal_Int32 EmfPlusLineStyleDashDotDot = 0x00000004;
+const sal_Int32 EmfPlusLineStyleCustom = 0x00000005;
+
 using namespace ::com::sun::star;
 using namespace ::basegfx;
 
@@ -614,6 +621,34 @@ namespace cppcanvas
                 }
 #endif
                 rStrokeAttributes.StrokeWidth = fabs((rState.mapModeTransform * rR.MapSize (width == 0.0 ? 0.05 : width, 0)).getX());
+
+                // set dashing
+                if (dashStyle != EmfPlusLineStyleSolid)
+                {
+                    const float dash[] = {3, 3};
+                    const float dot[] = {1, 3};
+                    const float dashdot[] = {3, 3, 1, 3};
+                    const float dashdotdot[] = {3, 3, 1, 3, 1, 3};
+
+                    sal_Int32 nLen = 0;
+                    const float *pPattern;
+                    switch (dashStyle)
+                    {
+                        case EmfPlusLineStyleDash:       nLen = SAL_N_ELEMENTS(dash); pPattern = dash; break;
+                        case EmfPlusLineStyleDot:        nLen = SAL_N_ELEMENTS(dot); pPattern = dot; break;
+                        case EmfPlusLineStyleDashDot:    nLen = SAL_N_ELEMENTS(dashdot); pPattern = dashdot; break;
+                        case EmfPlusLineStyleDashDotDot: nLen = SAL_N_ELEMENTS(dashdotdot); pPattern = dashdotdot; break;
+                        case EmfPlusLineStyleCustom:     nLen = dashPatternLen; pPattern = dashPattern; break;
+                    }
+                    if (nLen > 0)
+                    {
+                        uno::Sequence<double> aDashArray(nLen);
+                        for (int i = 0; i < nLen; ++i)
+                            aDashArray[i] = pPattern[i];
+
+                        rStrokeAttributes.DashArray = aDashArray;
+                    }
+                }
             }
 
             void Read (SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32 )
@@ -651,7 +686,10 @@ namespace cppcanvas
                     mitterLimit = 0;
 
                 if (penFlags & 32)
+                {
                     s >> dashStyle;
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tdashStyle: 0x" << std::hex << dashStyle);
+                }
                 else
                     dashStyle = 0;
 
@@ -665,14 +703,23 @@ namespace cppcanvas
                 else
                     dashOffset = 0;
 
-                if (penFlags & 256) {
+                if (penFlags & 256)
+                {
+                    dashStyle = EmfPlusLineStyleCustom;
+
                     s >> dashPatternLen;
+                    SAL_INFO("cppcanvas.emf", "EMF+\t\tdashPatternLen: " << dashPatternLen);
+
                     if( dashPatternLen<0 || sal_uInt32(dashPatternLen)>SAL_MAX_INT32/sizeof(float) )
                         dashPatternLen = SAL_MAX_INT32/sizeof(float);
                     dashPattern = new float [dashPatternLen];
                     for (i = 0; i < dashPatternLen; i++)
+                    {
                         s >> dashPattern [i];
-                } else
+                        SAL_INFO("cppcanvas.emf", "EMF+\t\t\tdashPattern[" << i << "]: " << dashPattern[i]);
+                    }
+                }
+                else
                     dashPatternLen = 0;
 
                 if (penFlags & 512)
commit 17727bd8c06a365ae59be8c00b3149152f1a0d0d
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Wed Nov 27 12:12:42 2013 +0100

    fdo#61272: Do the mapping correctly both for WMF and EMF.
    
    Turns out that for the WMF, we already had everything set up correctly, we
    were just overwriting the right settings with default data again :-) - fix
    that.
    
    Includes the following commits:
    
    * Revert "wmf-mm-text-1.diff: Fix WMF rendering, n#417818"
    * Revert "wmf-mm-text.diff: Fix WMF rendering, n#417818"
    * fdo#56886 EMF: Fixes some scaling problems of clipped regions, Twips
    
    Change-Id: I7ff859246dbaea3868438d3632f9adc60fc4ee37
    Reviewed-on: https://gerrit.libreoffice.org/6829
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/vcl/source/filter/wmf/winmtf.cxx b/vcl/source/filter/wmf/winmtf.cxx
index c8c6652..6d44084 100644
--- a/vcl/source/filter/wmf/winmtf.cxx
+++ b/vcl/source/filter/wmf/winmtf.cxx
@@ -374,19 +374,6 @@ Point WinMtfOutput::ImplMap( const Point& rPt )
         {
             switch( mnMapMode )
             {
-                case MM_TEXT:
-                    fX2 -= mnWinOrgX;
-                    fY2 -= mnWinOrgY;
-                    if( mnDevWidth != 1 || mnDevHeight != 1 ) {
-                        fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*1000/mnUnitsPerInch;
-                        fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*1000/mnUnitsPerInch;
-                    }
-                    fX2 += mnDevOrgX;
-                    fY2 += mnDevOrgY;
-                    fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
-                    fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
-
-                    break;
                 case MM_LOENGLISH :
                 {
                     fX2 -= mnWinOrgX;
@@ -471,15 +458,6 @@ Size WinMtfOutput::ImplMap( const Size& rSz )
         {
             switch( mnMapMode )
             {
-                case MM_TEXT:
-                if( mnDevWidth != 1 && mnDevHeight != 1 ) {
-                    fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*1000/mnUnitsPerInch;
-                    fHeight*= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*1000/mnUnitsPerInch;
-                } else {
-                    fWidth *= (double)mnMillX * 100 / (double)mnPixX;
-                    fHeight *= (double)mnMillY * 100 / (double)mnPixY;
-                }
-                break;
                 case MM_LOENGLISH :
                 {
                     fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
@@ -916,7 +894,6 @@ WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
     mbComplexClip       ( false ),
     mnGfxMode           ( GM_COMPATIBLE ),
     mnMapMode           ( MM_TEXT ),
-    mnUnitsPerInch ( 96 ),
     mnDevOrgX           ( 0 ),
     mnDevOrgY           ( 0 ),
     mnDevWidth          ( 1 ),
@@ -2025,7 +2002,7 @@ void WinMtfOutput::SetRefMill( const Size& rSize )
 void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode )
 {
     mnMapMode = nMapMode;
-    if ( nMapMode == MM_TEXT )
+    if ( nMapMode == MM_TEXT && !mbIsMapWinSet )
     {
         mnWinExtX = mnDevWidth;
         mnWinExtY = mnDevHeight;
@@ -2039,14 +2016,6 @@ void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode )
 
 
 
-void WinMtfOutput::SetUnitsPerInch( sal_uInt16 nUnitsPerInch )
-{
-    if( nUnitsPerInch != 0 )
-    mnUnitsPerInch = nUnitsPerInch;
-}
-
-
-
 void WinMtfOutput::SetWorldTransform( const XForm& rXForm )
 {
     maXForm.eM11 = rXForm.eM11;
diff --git a/vcl/source/filter/wmf/winmtf.hxx b/vcl/source/filter/wmf/winmtf.hxx
index bec5d8a..8e18f7e 100644
--- a/vcl/source/filter/wmf/winmtf.hxx
+++ b/vcl/source/filter/wmf/winmtf.hxx
@@ -679,7 +679,6 @@ public:
 
     sal_uInt32          GetMapMode() const { return mnMapMode; };
     void                SetMapMode( sal_uInt32 mnMapMode );
-    void                SetUnitsPerInch( sal_uInt16 nUnitsPerInch );
     void                SetWorldTransform( const XForm& rXForm );
     void                ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode );
 
diff --git a/vcl/source/filter/wmf/winwmf.cxx b/vcl/source/filter/wmf/winwmf.cxx
index 84b1a78..3777c3b 100644
--- a/vcl/source/filter/wmf/winwmf.cxx
+++ b/vcl/source/filter/wmf/winwmf.cxx
@@ -1108,7 +1108,6 @@ sal_Bool WMFReader::ReadHeader()
         }
     }
 
-    pOut->SetUnitsPerInch( nUnitsPerInch );
     pOut->SetWinOrg( aPlaceableBound.TopLeft() );
     Size aWMFSize( labs( aPlaceableBound.GetWidth() ), labs( aPlaceableBound.GetHeight() ) );
     pOut->SetWinExt( aWMFSize );
commit 76424bbada9758561e890023124bc3dd7dd0bcbc
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Tue Nov 19 10:02:12 2013 +0100

    EMF+: Stroke size is always supposed to be absolute.
    
    Change-Id: I7221311e5dee6384dc2d1c071bf6f1c61811895a
    Reviewed-on: https://gerrit.libreoffice.org/6827
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index 8f33574..afba7f1 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -613,7 +613,7 @@ namespace cppcanvas
                     SAL_INFO ("cppcanvas.emf", "TODO: pen with zero width - using minimal which might not be correct\n");
                 }
 #endif
-                rStrokeAttributes.StrokeWidth = (rState.mapModeTransform * rR.MapSize (width == 0.0 ? 0.05 : width, 0)).getX ();
+                rStrokeAttributes.StrokeWidth = fabs((rState.mapModeTransform * rR.MapSize (width == 0.0 ? 0.05 : width, 0)).getX());
             }
 
             void Read (SvStream& s, ImplRenderer& rR, sal_Int32, sal_Int32 )
commit c3775f8dc03e85f78471c69e4eb94afdbaf79651
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Mon Nov 25 11:04:41 2013 +0000

    Resolves: fdo#41169 fix MacOSX non-Latin keyboard layout with Latin shortcuts
    
    Change-Id: I168de52d6185d5df9c41fd2d7a68c0ff3f733852
    (cherry picked from commit 82b5172954261e030a42bd6b3f4acc99807d0ee5)
    Reviewed-on: https://gerrit.libreoffice.org/6798
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/vcl/aqua/source/window/salframeview.mm b/vcl/aqua/source/window/salframeview.mm
index a0715d5..610eb93 100644
--- a/vcl/aqua/source/window/salframeview.mm
+++ b/vcl/aqua/source/window/salframeview.mm
@@ -105,6 +105,38 @@ static sal_uInt16 ImplMapCharCode( sal_Unicode aCode )
     return nKeyCode;
 }
 
+static sal_uInt16 ImplMapKeyCode(sal_uInt16 nKeyCode)
+{
+    /*
+      http://stackoverflow.com/questions/2080312/where-can-i-find-a-list-of-key-codes-for-use-with-cocoas-nsevent-class/2080324#2080324
+      /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h
+     */
+
+    static sal_uInt16 aKeyCodeMap[ 0x80 ] =
+    {
+        KEY_A,               KEY_S,     KEY_D,        KEY_F,      KEY_H,      KEY_G,            KEY_Z,         KEY_X,
+        KEY_C,               KEY_V,     0,            KEY_B,      KEY_Q,      KEY_W,            KEY_E,         KEY_R,
+        KEY_Y,               KEY_T,     KEY_1,        KEY_2,      KEY_3,      KEY_4,            KEY_6,         KEY_5,
+        KEY_EQUAL,           KEY_9,     KEY_7, KEY_SUBTRACT,      KEY_8,      KEY_0, KEY_BRACKETRIGHT,         KEY_0,
+        KEY_U,     KEY_BRACKETLEFT,     KEY_I,        KEY_P, KEY_RETURN,      KEY_L,            KEY_J, KEY_QUOTELEFT,
+        KEY_K,       KEY_SEMICOLON,         0,    KEY_COMMA, KEY_DIVIDE,      KEY_N,            KEY_M,     KEY_POINT,
+        KEY_TAB,         KEY_SPACE, KEY_TILDE,   KEY_DELETE,          0, KEY_ESCAPE,                0,             0,
+              0,      KEY_CAPSLOCK,         0,            0,          0,          0,                0,             0,
+        KEY_F17,       KEY_DECIMAL,         0, KEY_MULTIPLY,          0,    KEY_ADD,		    0,             0,
+              0,                 0,         0,   KEY_DIVIDE, KEY_RETURN,          0,     KEY_SUBTRACT,       KEY_F18,
+        KEY_F19,         KEY_EQUAL,         0,            0,          0,          0,                0,             0,
+              0,                 0,   KEY_F20,            0,          0,          0,                0,             0,
+         KEY_F5,            KEY_F6,    KEY_F7,       KEY_F3,     KEY_F8,     KEY_F9,                0,       KEY_F11,
+              0,           KEY_F13,   KEY_F16,      KEY_F14,          0,    KEY_F10,                0,       KEY_F12,
+              0,           KEY_F15,  KEY_HELP,     KEY_HOME, KEY_PAGEUP, KEY_DELETE,           KEY_F4,       KEY_END,
+         KEY_F2,      KEY_PAGEDOWN,    KEY_F1,     KEY_LEFT,  KEY_RIGHT,   KEY_DOWN,           KEY_UP,		   0
+    };
+
+    if (nKeyCode < SAL_N_ELEMENTS(aKeyCodeMap))
+        return aKeyCodeMap[nKeyCode];
+    return 0;
+}
+
 // store the frame the mouse last entered
 static AquaSalFrame* s_pMouseFrame = NULL;
 // store the last pressed button for enter/exit events
@@ -1444,6 +1476,11 @@ private:
     {
         unichar keyChar = [pUnmodifiedString characterAtIndex: 0];
         sal_uInt16 nKeyCode = ImplMapCharCode( keyChar );
+        if (nKeyCode == 0)
+        {
+            sal_uInt16 nOtherKeyCode = [pEvent keyCode];
+            nKeyCode = ImplMapKeyCode(nOtherKeyCode);
+        }
         if( nKeyCode != 0 )
         {
             // don't send unicodes in the private use area
commit de6785b27e127c7e389f4737b31a90db94cac1cf
Author: Eike Rathke <erack at redhat.com>
Date:   Tue Nov 26 00:18:46 2013 +0100

    set a 23 enigma timeout at RegexMatcher, fdo#70627
    
    Change-Id: I390bfec0d36dcc9529785e97994dad2b0704dc80
    (cherry picked from commit d838ea200e7d6060d4a759616f9e1fcbf3c36c8e)
    Reviewed-on: https://gerrit.libreoffice.org/6808
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/i18npool/source/search/textsearch.cxx b/i18npool/source/search/textsearch.cxx
index 7762832..91a770b 100644
--- a/i18npool/source/search/textsearch.cxx
+++ b/i18npool/source/search/textsearch.cxx
@@ -764,8 +764,30 @@ void TextSearch::RESrchPrepare( const ::com::sun::star::util::SearchOptions& rOp
     aChevronMatcherE.reset();
 #endif
     pRegexMatcher = new RegexMatcher( aIcuSearchPatStr, nIcuSearchFlags, nIcuErr);
-    if( nIcuErr)
-        { delete pRegexMatcher; pRegexMatcher = NULL;}
+    if (nIcuErr)
+    {
+        delete pRegexMatcher;
+        pRegexMatcher = NULL;
+    }
+    else
+    {
+        // Pathological patterns may result in exponential run time making the
+        // application appear to be frozen. Limit that. Documentation for this
+        // call says
+        // https://ssl.icu-project.org/apiref/icu4c/classicu_1_1RegexMatcher.html#a6ebcfcab4fe6a38678c0291643a03a00
+        // "The units of the limit are steps of the match engine.
+        // Correspondence with actual processor time will depend on the speed
+        // of the processor and the details of the specific pattern, but will
+        // typically be on the order of milliseconds."
+        // Just what is a good value? 42 is always an answer ... the 23 enigma
+        // as well.. which on the dev's machine is roughly 50 seconds with the
+        // pattern of fdo#70627.
+        /* TODO: make this a configuration settable value and possibly take
+         * complexity of expression into account and maybe even length of text
+         * to be matched; currently (2013-11-25) that is at most one 64k
+         * paragraph per RESrchFrwrd()/RESrchBkwrd() call. */
+        pRegexMatcher->setTimeLimit( 23*1000, nIcuErr);
+    }
 }
 
 //---------------------------------------------------------------------------
commit 3ec7bccfeec842190e0431405188da156acccf35
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Nov 22 13:20:12 2013 +0000

    Related: fdo#41169 fix GTK non-Latin keyboard layout with Latin shortcuts
    
    See also rhbz#958300
    
    Change-Id: I5c3cf9652adb7b1c9ec53a32ed39f231a09ae1d7
    (cherry picked from commit 8cef6c7ec67aec88b339ca647e784afbabf190f8)
    Reviewed-on: https://gerrit.libreoffice.org/6759
    Reviewed-by: Khaled Hosny <khaledhosny at eglug.org>
    Tested-by: Khaled Hosny <khaledhosny at eglug.org>

diff --git a/vcl/unx/gtk/window/gtksalframe.cxx b/vcl/unx/gtk/window/gtksalframe.cxx
index fef8407..7db5649 100644
--- a/vcl/unx/gtk/window/gtksalframe.cxx
+++ b/vcl/unx/gtk/window/gtksalframe.cxx
@@ -323,6 +323,14 @@ static sal_uInt16 GetKeyCode( guint keyval )
     return nCode;
 }
 
+static guint GetKeyValFor(GdkKeymap* pKeyMap, guint16 hardware_keycode, guint8 group)
+{
+    guint updated_keyval = 0;
+    gdk_keymap_translate_keyboard_state(pKeyMap, hardware_keycode,
+        (GdkModifierType)0, group, &updated_keyval, NULL, NULL, NULL);
+    return updated_keyval;
+}
+
 // F10 means either KEY_F10 or KEY_MENU, which has to be decided
 // in the independent part.
 struct KeyAlternate
@@ -373,7 +381,7 @@ struct DamageTracker : public basebmp::IBitmapDeviceDamageTracker
 void GtkSalFrame::doKeyCallback( guint state,
                                  guint keyval,
                                  guint16 hardware_keycode,
-                                 guint8 /*group*/,
+                                 guint8 group,
                                  guint32 time,
                                  sal_Unicode aOrigCode,
                                  bool bDown,
@@ -405,33 +413,48 @@ void GtkSalFrame::doKeyCallback( guint state,
     }
 #endif
 
-    /* #i42122# translate all keys with Ctrl and/or Alt to group 0
-    *  else shortcuts (e.g. Ctrl-o) will not work but be inserted by
-    *  the application
-    */
-    /* #i52338# do this for all keys that the independent part has no key code for
-    */
+    /*
+     *  #i42122# translate all keys with Ctrl and/or Alt to group 0 else
+     *  shortcuts (e.g. Ctrl-o) will not work but be inserted by the
+     *  application
+     *
+     *  #i52338# do this for all keys that the independent part has no key code
+     *  for
+     *
+     *  fdo#41169 rather than use group 0, detect if there is a group which can
+     *  be used to input Latin text and use that if possible
+     */
     aEvent.mnCode = GetKeyCode( keyval );
     if( aEvent.mnCode == 0 )
     {
-        // check other mapping
-        gint eff_group, level;
-        GdkModifierType consumed;
-        guint updated_keyval = 0;
-        // use gdk_keymap_get_default instead of NULL;
-        // workaround a crahs fixed in gtk 2.4
-        if( gdk_keymap_translate_keyboard_state( gdk_keymap_get_default(),
-                                                 hardware_keycode,
-                                                 (GdkModifierType)0,
-                                                 0,
-                                                 &updated_keyval,
-                                                 &eff_group,
-                                                 &level,
-                                                 &consumed ) )
+        gint best_group = SAL_MAX_INT32;
+
+        // Try and find Latin layout
+        GdkKeymap* keymap = gdk_keymap_get_default();
+        GdkKeymapKey *keys;
+        gint n_keys;
+        if (gdk_keymap_get_entries_for_keyval(keymap, GDK_A, &keys, &n_keys))
         {
-            aEvent.mnCode   = GetKeyCode( updated_keyval );
+            // Find the lowest group that supports Latin layout
+            for (gint i = 0; i < n_keys; ++i)
+            {
+                if (keys[i].level != 0 && keys[i].level != 1)
+                    continue;
+                best_group = std::min(best_group, keys[i].group);
+                if (best_group == 0)
+                    break;
+            }
+            g_free(keys);
         }
+
+        //Unavailable, go with original group then I suppose
+        if (best_group == SAL_MAX_INT32)
+            best_group = group;
+
+        guint updated_keyval = GetKeyValFor(keymap, hardware_keycode, best_group);
+        aEvent.mnCode = GetKeyCode(updated_keyval);
     }
+
     aEvent.mnCode   |= GetKeyModCode( state );
 
     if( bDown )
commit 4fd382d32fd304767fba9b1cd07fe5116070a843
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Mon Nov 25 18:01:22 2013 +0100

    rhbz#1030009 Remove global XModel ref
    
    ...that is apparently effectively unused since
    2627bdaddc6f694dc7fc6ba347a305af0f88ee2c "INTEGRATION: CWS fwk02ea: #i28639#
    always used supplied status indicator" anyway but causes crashes during exit
    when it holds an SwXTextDocument ref.
    
    Change-Id: I542545c793855b41731de72650bf07d5748fcb9f
    (cherry picked from commit a7464edb0a4368db02b1298b5710cf98b17e282b)
    Reviewed-on: https://gerrit.libreoffice.org/6804
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    Tested-by: Michael Stahl <mstahl at redhat.com>

diff --git a/filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx b/filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx
index c0b017c..a486cdf 100644
--- a/filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx
+++ b/filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx
@@ -36,7 +36,6 @@
 #include <com/sun/star/frame/XConfigManager.hpp>
 #include <com/sun/star/xml/XImportFilter.hpp>
 #include <com/sun/star/xml/XExportFilter.hpp>
-#include <com/sun/star/frame/XModel.hpp>
 #include <com/sun/star/frame/XController.hpp>
 #include <com/sun/star/task/XStatusIndicator.hpp>
 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
@@ -66,8 +65,6 @@ using namespace ::com::sun::star::task;
 
 #define MAP_LEN(x) x, sizeof(x) - 1
 
-Reference< com::sun::star::frame::XModel > xModel;
-
 sal_Bool SAL_CALL XmlFilterAdaptor::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
     throw (RuntimeException)
 {
@@ -341,9 +338,6 @@ void SAL_CALL XmlFilterAdaptor::setSourceDocument( const Reference< ::com::sun::
 {
     meType = FILTER_EXPORT;
     mxDoc = xDoc;
-        com::sun::star::uno::Reference< com::sun::star::frame::XModel >rModel ( com::sun::star::uno::Reference< com::sun::star::frame::XModel >::query( xDoc ) );
-    xModel=rModel;
-
 }
 
 // XImporter
@@ -352,7 +346,6 @@ void SAL_CALL XmlFilterAdaptor::setTargetDocument( const Reference< ::com::sun::
 {
     meType = FILTER_IMPORT;
     mxDoc = xDoc;
-    //xModel = uno::Reference< frame::XModel >::query( xDoc );
 }
 // XInitialization
 void SAL_CALL XmlFilterAdaptor::initialize( const Sequence< Any >& aArguments )
commit ed195f5d7a5cb1d9e116ca1f8a1ced16072f6d2b
Author: Julien Nabet <serval2412 at yahoo.fr>
Date:   Sun Nov 17 17:48:31 2013 +0100

    Resolves: fdo#67263 CRASH when deleting applied bulleted paragraph style
    
    Change-Id: I70dc18363480e6c07577a93279ddd083631f6cc3
    Reviewed-on: https://gerrit.libreoffice.org/6702
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>
    (cherry picked from commit 899c5ea9dc3c34892edfde642510514779132910)
    Reviewed-on: https://gerrit.libreoffice.org/6755
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    Tested-by: Michael Stahl <mstahl at redhat.com>

diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 3befea2..3891390 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -139,7 +139,7 @@ namespace {
     {
         bool bRet( false );
 
-        if ( rTxtNode.AreListLevelIndentsApplicable() )
+        if ( rTxtNode.GetNumRule() && rTxtNode.AreListLevelIndentsApplicable() )
         {
             const SwNumFmt& rNumFmt =
                     rTxtNode.GetNumRule()->Get( static_cast<sal_uInt16>(rTxtNode.GetActualListLevel()) );
commit 88652b1b0921c623eb43b249b16a240d57f8cb28
Author: matt_51 <matthieu.gay.cap at gmail.com>
Date:   Tue Nov 5 11:40:56 2013 +0100

    fdo#70345 Reuse XStream for Windows platform create a new one for others.
    
    Reviewed-on: https://gerrit.libreoffice.org/6580
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    Tested-by: Michael Stahl <mstahl at redhat.com>
    (cherry picked from commit 3d12549335229aca1a6a57575292111274709992)
    
    Change-Id: I911c24b82b55445c6f95e14be29759e2fe3d9dfd
    Reviewed-on: https://gerrit.libreoffice.org/6761
    Reviewed-by: Michael Stahl <mstahl at redhat.com>
    Tested-by: Michael Stahl <mstahl at redhat.com>

diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index c1ad603..06d7a4b 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -641,13 +641,26 @@ SvStream* SfxMedium::GetOutStream()
 
         if ( pImp->pTempFile )
         {
-            // don't try to re-use XOutStream from xStream if that exists;
+            // On windows we try to re-use XOutStream from xStream if that exists;
+            // because opening new SvFileStream in this situation may fail with ERROR_SHARING_VIOLATION
+            #ifdef WNT
+            if (pImp->xStream.is())
+            {
+                assert(pImp->xStream->getOutputStream().is()); // need that...
+                pImp->m_pOutStream = utl::UcbStreamHelper::CreateStream(
+                        pImp->xStream, false);
+            }
+            else
+            {
+                pImp->m_pOutStream = new SvFileStream(
+                        pImp->m_aName, STREAM_STD_READWRITE);
+            }
+            // On Unix don't try to re-use XOutStream from xStream if that exists;
             // it causes fdo#59022 (fails opening files via SMB on Linux)
-            // OTOH opening new SvFileStream in this situation may fail on
-            // Windows with ERROR_SHARING_VIOLATION... but that is apparently
-            // not a problem in practice currently
+            #else
             pImp->m_pOutStream = new SvFileStream(
                         pImp->m_aName, STREAM_STD_READWRITE);
+            #endif
             CloseStorage();
         }
     }


More information about the Libreoffice-commits mailing list