accessibility/inc/extended/AccessibleBrowseBox.hxx | 2 download.lst | 8 drawinglayer/source/processor2d/cairopixelprocessor2d.cxx | 539 drawinglayer/source/processor2d/processor2dtools.cxx | 14 drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 14 extras/source/autocorr/lang/fa/DocumentList.xml | 8363 +++---------- include/drawinglayer/processor2d/cairopixelprocessor2d.hxx | 27 readlicense_oo/license/CREDITS.fodt | 4069 +++--- sd/qa/unit/export-tests.cxx | 3 sd/source/ui/func/fusldlg.cxx | 26 svx/source/svdraw/svdotextdecomposition.cxx | 19 sw/qa/extras/layout/data/tdf164499.docx |binary sw/qa/extras/layout/layout3.cxx | 28 sw/qa/extras/rtfimport/rtfimport.cxx | 7 sw/qa/extras/uiwriter/data/tdf164620.docx |binary sw/qa/extras/uiwriter/uiwriter3.cxx | 18 sw/source/core/fields/reffld.cxx | 3 sw/source/core/text/portxt.cxx | 2 sw/source/writerfilter/rtftok/rtfdispatchvalue.cxx | 6 xmloff/source/draw/ximpshap.cxx | 16 20 files changed, 4641 insertions(+), 8523 deletions(-)
New commits: commit a2a5e707d935d2bf71a39f773785312c3b5b32c7 Author: Armin Le Grand (Collabora) <[email protected]> AuthorDate: Thu Jan 30 20:47:00 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 tdf#164476 CiaroSDPR: improve ControlPrimitive2D rendering The task shows that for some situations the Controls do not get vbisualized. These *should* be child windows of the panel containing them, but fir some reason these seem to get incarnated by being 'painted'. Problem is that for SDPRs an OutputDevice to do so is not available - by purpose. Luckily it is possible to use a awt::XGraphics and 'paint' from there. It would also be possible to find out why the child windows do not get constructed and where this may need to be done, but for now just add 'painting' the Controls by using the path utilizing the awt::XGraphics mechanism. For that purpose, do set an awt::XGraphics at the CairoSDPR if it gets constructed using an OutputDevice. It may be that we need to think about how to solve this for SDPRs that get constructed from scratch, e.g. when using createPixelProcessor2DFromScratch. This would mean to somehow construct a awt::XGraphics from a cairo surface, probably using an OutputDevice as in-betwen step, but for now this change solves the problem. Change-Id: I3bc653deab7f0b2902081b0fdbd501dfcc78383b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180967 Tested-by: Jenkins Reviewed-by: Armin Le Grand <[email protected]> Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181551 diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index 36bb4bb1b3b9..dc6c637e9330 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -55,8 +55,10 @@ #include <basegfx/utils/systemdependentdata.hxx> #include <basegfx/utils/bgradient.hxx> #include <vcl/BitmapReadAccess.hxx> -#include <officecfg/Office/Common.hxx> #include <vcl/vcllayout.hxx> +#include <officecfg/Office/Common.hxx> +#include <com/sun/star/awt/XView.hpp> +#include <com/sun/star/awt/XControl.hpp> #include <unordered_map> #include <dlfcn.h> @@ -951,6 +953,7 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get()) , mnClipRecursionCount(0) , mbCairoCoordinateLimitWorkaroundActive(false) + , maXGraphics() { if (nWidthPixel <= 0 || nHeightPixel <= 0) // no size, invalid @@ -994,6 +997,7 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get()) , mnClipRecursionCount(0) , mbCairoCoordinateLimitWorkaroundActive(false) + , maXGraphics() { // no target, nothing to initialize if (nullptr == pTarget) @@ -3873,12 +3877,44 @@ void CairoPixelProcessor2D::processControlPrimitive2D( return; } - // process recursively and use the decomposition as Bitmap - // NOTE: The VclPixelProcessor2D tries to paint it using - // UNO API and awt::XView/awt::XGraphics to directly paint the - // control. To do so would need the target OutDev which we - // want to avoid here - process(rControlPrimitive); + bool bDone(false); + + try + { + if (getXGraphics().is()) + { + // Needs to be drawn. Link new graphics and view + const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl()); + uno::Reference<awt::XView> xControlView(rXControl, uno::UNO_QUERY_THROW); + const uno::Reference<awt::XGraphics> xOriginalGraphics(xControlView->getGraphics()); + xControlView->setGraphics(getXGraphics()); + + // get position + const basegfx::B2DHomMatrix aObjectToPixel( + getViewInformation2D().getObjectToViewTransformation() + * rControlPrimitive.getTransform()); + const basegfx::B2DPoint aTopLeftPixel(aObjectToPixel * basegfx::B2DPoint(0.0, 0.0)); + + xControlView->draw(basegfx::fround(aTopLeftPixel.getX()), + basegfx::fround(aTopLeftPixel.getY())); + + // restore original graphics + xControlView->setGraphics(xOriginalGraphics); + bDone = true; + } + } + catch (const uno::Exception&) + { + // #i116763# removing since there is a good alternative when the xControlView + // is not found and it is allowed to happen + // DBG_UNHANDLED_EXCEPTION(); + } + + if (!bDone) + { + // process recursively and use the decomposition as Bitmap + process(rControlPrimitive); + } } void CairoPixelProcessor2D::evaluateCairoCoordinateLimitWorkaround() diff --git a/drawinglayer/source/processor2d/processor2dtools.cxx b/drawinglayer/source/processor2d/processor2dtools.cxx index e90cac41a6c1..f892acfc1563 100644 --- a/drawinglayer/source/processor2d/processor2dtools.cxx +++ b/drawinglayer/source/processor2d/processor2dtools.cxx @@ -30,6 +30,8 @@ #include <officecfg/Office/Common.hxx> #endif +using namespace com::sun::star; + namespace drawinglayer::processor2d { std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromScratch( @@ -128,7 +130,14 @@ std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromOutputDevice( rTargetOutDev.GetOutputWidthPixel(), rTargetOutDev.GetOutputHeightPixel())); if (aRetval->valid()) + { + // if we construct a CairoPixelProcessor2D from OutputDevice, + // additionally set the XGraphics that can be obtained from + // there. It may be used e.g. to render FormControls directly + aRetval->setXGraphics(rTargetOutDev.CreateUnoGraphics()); + return aRetval; + } } #endif diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index d5f878768918..3264cdfc2a4a 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -653,21 +653,19 @@ void VclPixelProcessor2D::processControlPrimitive2D( return; } - // get awt::XControl from control primitive - const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl()); bool bDone(false); try { - // remember old graphics and create new - uno::Reference<awt::XView> xControlView(rXControl, uno::UNO_QUERY_THROW); - const uno::Reference<awt::XGraphics> xOriginalGraphics(xControlView->getGraphics()); - const uno::Reference<awt::XGraphics> xNewGraphics(mpOutputDevice->CreateUnoGraphics()); + const uno::Reference<awt::XGraphics> xTargetGraphics(mpOutputDevice->CreateUnoGraphics()); - if (xNewGraphics.is()) + if (xTargetGraphics.is()) { // Needs to be drawn. Link new graphics and view - xControlView->setGraphics(xNewGraphics); + const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl()); + uno::Reference<awt::XView> xControlView(rXControl, uno::UNO_QUERY_THROW); + const uno::Reference<awt::XGraphics> xOriginalGraphics(xControlView->getGraphics()); + xControlView->setGraphics(xTargetGraphics); // get position const basegfx::B2DHomMatrix aObjectToPixel(maCurrentTransformation diff --git a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx index 3d20f300a972..6f505f8eeb98 100644 --- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx +++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx @@ -13,6 +13,7 @@ #include <basegfx/color/bcolormodifier.hxx> #include <tools/long.hxx> #include <sal/config.h> +#include <com/sun/star/awt/XGraphics.hpp> // cairo-specific #include <cairo.h> @@ -89,6 +90,9 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub // calculated result of if we are in outsideCairoCoordinateLimits mode bool mbCairoCoordinateLimitWorkaroundActive; + // the XGraphics which may be set using setXGraphics() + com::sun::star::uno::Reference<com::sun::star::awt::XGraphics> maXGraphics; + // helpers for direct paints void paintPolyPoylgonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rColor, double fTransparency = 0.0); @@ -188,10 +192,21 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub protected: bool hasError() const { return cairo_status(mpRT) != CAIRO_STATUS_SUCCESS; } bool hasRenderTarget() const { return nullptr != mpRT; } + const com::sun::star::uno::Reference<com::sun::star::awt::XGraphics>& getXGraphics() const + { + return maXGraphics; + } public: bool valid() const { return hasRenderTarget() && !hasError(); } + // set a XGraphics for this CairoPixelProcessor2D when it is available + void + setXGraphics(const com::sun::star::uno::Reference<com::sun::star::awt::XGraphics>& rXGraphics) + { + maXGraphics = rXGraphics; + } + // read access to CairoCoordinateLimitWorkaround mechanism bool isCairoCoordinateLimitWorkaroundActive() const { commit b38ff4c65ccb5850afb8f8fcaf625ba821982588 Author: Armin Le Grand (Collabora) <[email protected]> AuthorDate: Tue Jan 28 21:02:25 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 tdf#164403 CairoSDPR: adapt hairline width If Cairo Coordinate Limit Workaround is Active do also adapt hairline width to 1.0 since we (have to) fallback to render in view coordinates. Change-Id: I2216c1728355b5e76ee04f699193a896f9c4fd4b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180860 Tested-by: Jenkins Reviewed-by: Armin Le Grand <[email protected]> Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181550 diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index a7ae62e85911..36bb4bb1b3b9 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -65,7 +65,8 @@ using namespace com::sun::star; namespace { void impl_cairo_set_hairline(cairo_t* pRT, - const drawinglayer::geometry::ViewInformation2D& rViewInformation) + const drawinglayer::geometry::ViewInformation2D& rViewInformation, + bool bCairoCoordinateLimitWorkaroundActive) { #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0) void* addr(dlsym(nullptr, "cairo_set_hairline")); @@ -75,11 +76,19 @@ void impl_cairo_set_hairline(cairo_t* pRT, return; } #endif - // avoid cairo_device_to_user_distance, see note on that below - const double fPx( - (rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)) - .getLength()); - cairo_set_line_width(pRT, fPx); + if (bCairoCoordinateLimitWorkaroundActive) + { + // we have to render in view coordiantes, set line width to 1.0 + cairo_set_line_width(pRT, 1.0); + } + else + { + // avoid cairo_device_to_user_distance, see note on that below + const double fPx( + (rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)) + .getLength()); + cairo_set_line_width(pRT, fPx); + } } void addB2DPolygonToPathGeometry(cairo_t* pRT, const basegfx::B2DPolygon& rPolygon) @@ -1269,7 +1278,8 @@ void CairoPixelProcessor2D::paintBitmapAlpha(const BitmapEx& rBitmapEx, if (bRenderTransformationBounds) { cairo_set_source_rgba(mpRT, 1, 0, 0, 0.8); - impl_cairo_set_hairline(mpRT, getViewInformation2D()); + impl_cairo_set_hairline(mpRT, getViewInformation2D(), + isCairoCoordinateLimitWorkaroundActive()); cairo_rectangle(mpRT, 0, 0, 1, 1); cairo_stroke(mpRT); } @@ -1404,7 +1414,7 @@ void CairoPixelProcessor2D::processPolygonHairlinePrimitive2D( aHairlineColor.getBlue()); // set LineWidth, use Cairo's special cairo_set_hairline - impl_cairo_set_hairline(mpRT, getViewInformation2D()); + impl_cairo_set_hairline(mpRT, getViewInformation2D(), isCairoCoordinateLimitWorkaroundActive()); if (isCairoCoordinateLimitWorkaroundActive()) { @@ -2429,7 +2439,8 @@ void CairoPixelProcessor2D::processFillGraphicPrimitive2D( if (bRenderTransformationBounds) { cairo_set_source_rgba(mpRT, 0, 1, 0, 0.8); - impl_cairo_set_hairline(mpRT, getViewInformation2D()); + impl_cairo_set_hairline(mpRT, getViewInformation2D(), + isCairoCoordinateLimitWorkaroundActive()); // full object cairo_rectangle(mpRT, 0, 0, 1, 1); // outline of pattern root image commit ceb5051cd9820d767b9cfbed1b164872c3d50725 Author: Armin Le Grand (Collabora) <[email protected]> AuthorDate: Mon Jan 20 19:59:07 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 tdf#164403 CairoSDPR: Solve Cairo's 24.8 coordinate problem Thus Cairo is offering a full-fledged double precision API but internally uses a 24.8 fixed-float format (see https://gitlab. freedesktop.org/cairo/cairo/-/issues/252, thanks Caolan for finding that). This seems to be the case for linux and windows implementations. Due to the API being on double precision this is an implementation detail, but it has to be taken into account when using cairo. It is not officially documented what is a shame - it should be somewhere in the readmes/ documentation at a prominent place. 24.8 means coordinates are limited to +/- 2^23 (usually minus one) and [0/256 .. 255/256] places after comma. This is unfortunately not limited to the view coordinates - that would be acceptable, discrete/pixel areas of that size should be fine, BUT used with transformations. Thus when having any coordinates beyond that limit - and with double precision and transformations we have that here - cairo just 'cuts' the coordinates to it's min/max 24.8 format. This is not acceptable for e.g. a cad system, and even leads to problems in something like an office suite as we see. It implies that using cairo in a safe way means to basically use linear algebra yourself in your app and use cairo only without transformations and with discrete view coordinates (pixels). AND to know about that limitation in the 1st place ... Well, cairo works well and that problem happens until now in one place in writer below page 490. Let's be pragmatic. Key is to *detect* the situation. Always doing own transformations is possible, but not nice: I *could* always transform the polygon to screen coordinates, but that will kill the PolyPolygon buffering mechanism (in chart we have PolyPolygons with 80.000 entries :-); These are held in cairo_path_t form at the original PolyPolygon to not need to transform them every time, but let Cairo do that. The idea is that when Cairo impl may use HW on the system to do that (HW can do that nowadays) while rendering the PolyPolygon from the object model would have to be converted just once to Cairo form and used multiple times... Cairo *should* be fair, document this and allow you to test/ ask if this limit exists in the version you are using, but it does not. Thus I suppose to detect that situation as 'cheap' as possible and react to it - e.g. in writer when below page 490. But not only - it might be possibe to construct draw/impress pages (free definable) that also reach that limit. With detecting as cheap as possible I mean: Naturally you would start to test your geometry to be painted if it is overlapping or outside that range defined by 24.8, but that would already involve transforming all geometry by world and view transformations. I think it should be okay to just take the target area (starting at 0,0 and having a size in pixels) and transforming that back to logical world coordinates. Then this needs to be checked only if view transformation changes, not object transformation. Usually view transformation is setup and all/many objects are painted to it using object transformations. Detection should then only be needed when view transform changes. Thus I added a test (see checkCoordinateLimitWorkaroundNeededForUsedCairo()). This is esecuted once per office runtime. If it detects that the problem is there it sets a flag. Depending on this the view coordinates are then transformed to logic coordinates and checked if these are completely inside the coordinate area that ciaro *can* correctly handle. This has to be done once per CariroSDPR since (currently) ViewTransformation is not changed (has to be adapted if this should happen one day). Based on that the single helpers on the renderer have to be adapted: Simplest is just to render using ViewCoordinates - and do transform object geometry using basegfx/our own stuff that does that correctly (with ease :-). Done that, checked, works AFAICT. What a bad surprise, but I can work around it... Change-Id: Ic33d6ccfe9854af396d0ac9f14c76eb25bb9e4e2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180529 Reviewed-by: Armin Le Grand <[email protected]> Tested-by: Jenkins Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181549 diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index 588afe4b158f..a7ae62e85911 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -860,6 +860,71 @@ basegfx::B2DRange getDiscreteViewRange(cairo_t* pRT) return basegfx::B2DRange(basegfx::B2DPoint(clip_x1, clip_y1), basegfx::B2DPoint(clip_x2, clip_y2)); } + +bool checkCoordinateLimitWorkaroundNeededForUsedCairo() +{ + // setup surface and render context + cairo_surface_t* pSurface(cairo_image_surface_create(CAIRO_FORMAT_RGB24, 8, 8)); + if (!pSurface) + // got no surface -> be pessimistic + return true; + + cairo_t* pRender(cairo_create(pSurface)); + if (!pRender) + { + // got no render -> be pessimistic + cairo_surface_destroy(pSurface); + return true; + } + + // set basic values + cairo_set_antialias(pRender, CAIRO_ANTIALIAS_NONE); + cairo_set_fill_rule(pRender, CAIRO_FILL_RULE_EVEN_ODD); + cairo_set_operator(pRender, CAIRO_OPERATOR_OVER); + cairo_set_source_rgb(pRender, 1.0, 0.0, 0.0); + + // create a to-be rendered area centered at the fNumCairoMax + // spot and 8x8 discrete units in size + constexpr double fNumCairoMax(1 << 23); + const basegfx::B2DPoint aCenter(fNumCairoMax, fNumCairoMax); + const basegfx::B2DPoint aOffset(4, 4); + const basegfx::B2DRange aObject(aCenter - aOffset, aCenter + aOffset); + + // create transformation to render that to an aerea with + // range(0, 0, 8, 8) and set as transformation + const basegfx::B2DHomMatrix aObjectToView(basegfx::utils::createSourceRangeTargetRangeTransform( + aObject, basegfx::B2DRange(0, 0, 8, 8))); + cairo_matrix_t aMatrix; + cairo_matrix_init(&aMatrix, aObjectToView.a(), aObjectToView.b(), aObjectToView.c(), + aObjectToView.d(), aObjectToView.e(), aObjectToView.f()); + cairo_set_matrix(pRender, &aMatrix); + + // get/create the path for an object exactly filling that area + cairo_new_path(pRender); + basegfx::B2DPolyPolygon aObjectPolygon(basegfx::utils::createPolygonFromRect(aObject)); + CairoPathHelper aPathHelper(aObjectPolygon); + cairo_append_path(pRender, aPathHelper.getCairoPath()); + + // render it and flush since we want to immediately inspect result + cairo_fill(pRender); + cairo_surface_flush(pSurface); + + // get access to pixel data + const sal_uInt32 nStride(cairo_image_surface_get_stride(pSurface)); + sal_uInt8* pStartPixelData(cairo_image_surface_get_data(pSurface)); + + // extract red value for pixels at (1,1) and (7,7) + sal_uInt8 aRedAt_1_1((pStartPixelData + (nStride * 1) + 1)[SVP_CAIRO_RED]); + sal_uInt8 aRedAt_6_6((pStartPixelData + (nStride * 6) + 6)[SVP_CAIRO_RED]); + + // cleanup + cairo_destroy(pRender); + cairo_surface_destroy(pSurface); + + // if cairo works or has no 24.8 internal format all pixels + // have to be red (255), thus workaround is needed if != + return aRedAt_1_1 != aRedAt_6_6; +} } namespace drawinglayer::processor2d @@ -876,6 +941,7 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& , mbRenderDecoratedTextDirect( officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get()) , mnClipRecursionCount(0) + , mbCairoCoordinateLimitWorkaroundActive(false) { if (nWidthPixel <= 0 || nHeightPixel <= 0) // no size, invalid @@ -900,6 +966,9 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& : CAIRO_ANTIALIAS_NONE); cairo_set_fill_rule(mpRT, CAIRO_FILL_RULE_EVEN_ODD); cairo_set_operator(mpRT, CAIRO_OPERATOR_OVER); + + // evaluate if CairoCoordinateLimitWorkaround is needed + evaluateCairoCoordinateLimitWorkaround(); } CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& rViewInformation, @@ -915,59 +984,63 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const geometry::ViewInformation2D& , mbRenderDecoratedTextDirect( officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get()) , mnClipRecursionCount(0) + , mbCairoCoordinateLimitWorkaroundActive(false) { - if (pTarget) - { - bool bClipNeeded(false); + // no target, nothing to initialize + if (nullptr == pTarget) + return; - if (0 != nOffsetPixelX || 0 != nOffsetPixelY || 0 != nWidthPixel || 0 != nHeightPixel) + bool bClipNeeded(false); + + if (0 != nOffsetPixelX || 0 != nOffsetPixelY || 0 != nWidthPixel || 0 != nHeightPixel) + { + if (0 != nOffsetPixelX || 0 != nOffsetPixelY) { - if (0 != nOffsetPixelX || 0 != nOffsetPixelY) + // if offset is used we need initial clip + bClipNeeded = true; + } + else + { + // no offset used, compare to real pixel size + const tools::Long nRealPixelWidth(cairo_image_surface_get_width(pTarget)); + const tools::Long nRealPixelHeight(cairo_image_surface_get_height(pTarget)); + + if (nRealPixelWidth != nWidthPixel || nRealPixelHeight != nHeightPixel) { - // if offset is used we need initial clip + // if size differs we need initial clip bClipNeeded = true; } - else - { - // no offset used, compare to real pixel size - const tools::Long nRealPixelWidth(cairo_image_surface_get_width(pTarget)); - const tools::Long nRealPixelHeight(cairo_image_surface_get_height(pTarget)); - - if (nRealPixelWidth != nWidthPixel || nRealPixelHeight != nHeightPixel) - { - // if size differs we need initial clip - bClipNeeded = true; - } - } } + } - if (bClipNeeded) - { - // optional: if the possibility to add an initial clip relative - // to the real pixel dimensions of the target surface is used, - // apply it here using that nice existing method of cairo - mpOwnedSurface = cairo_surface_create_for_rectangle( - pTarget, nOffsetPixelX, nOffsetPixelY, nWidthPixel, nHeightPixel); + if (bClipNeeded) + { + // optional: if the possibility to add an initial clip relative + // to the real pixel dimensions of the target surface is used, + // apply it here using that nice existing method of cairo + mpOwnedSurface = cairo_surface_create_for_rectangle(pTarget, nOffsetPixelX, nOffsetPixelY, + nWidthPixel, nHeightPixel); - if (nullptr != mpOwnedSurface) - mpRT = cairo_create(mpOwnedSurface); - } - else - { - // create RenderTarget for full target - mpRT = cairo_create(pTarget); - } + if (nullptr != mpOwnedSurface) + mpRT = cairo_create(mpOwnedSurface); + } + else + { + // create RenderTarget for full target + mpRT = cairo_create(pTarget); + } - if (nullptr != mpRT) - { - // initialize some basic used values/settings - cairo_set_antialias(mpRT, rViewInformation.getUseAntiAliasing() - ? CAIRO_ANTIALIAS_DEFAULT - : CAIRO_ANTIALIAS_NONE); - cairo_set_fill_rule(mpRT, CAIRO_FILL_RULE_EVEN_ODD); - cairo_set_operator(mpRT, CAIRO_OPERATOR_OVER); - } + if (nullptr != mpRT) + { + // initialize some basic used values/settings + cairo_set_antialias(mpRT, rViewInformation.getUseAntiAliasing() ? CAIRO_ANTIALIAS_DEFAULT + : CAIRO_ANTIALIAS_NONE); + cairo_set_fill_rule(mpRT, CAIRO_FILL_RULE_EVEN_ODD); + cairo_set_operator(mpRT, CAIRO_OPERATOR_OVER); } + + // evaluate if CairoCoordinateLimitWorkaround is needed + evaluateCairoCoordinateLimitWorkaround(); } CairoPixelProcessor2D::~CairoPixelProcessor2D() @@ -1324,16 +1397,6 @@ void CairoPixelProcessor2D::processPolygonHairlinePrimitive2D( cairo_save(mpRT); - // set linear transformation - cairo_matrix_t aMatrix; - const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0); - const basegfx::B2DHomMatrix& rObjectToView( - getViewInformation2D().getObjectToViewTransformation()); - cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), - rObjectToView.d(), rObjectToView.e() + fAAOffset, - rObjectToView.f() + fAAOffset); - cairo_set_matrix(mpRT, &aMatrix); - // determine & set color const basegfx::BColor aHairlineColor( maBColorModifierStack.getModifiedColor(rPolygonHairlinePrimitive2D.getBColor())); @@ -1343,11 +1406,40 @@ void CairoPixelProcessor2D::processPolygonHairlinePrimitive2D( // set LineWidth, use Cairo's special cairo_set_hairline impl_cairo_set_hairline(mpRT, getViewInformation2D()); - // get PathGeometry & paint it - cairo_new_path(mpRT); - getOrCreatePathGeometry(mpRT, rPolygon, getViewInformation2D(), - getViewInformation2D().getUseAntiAliasing()); - cairo_stroke(mpRT); + if (isCairoCoordinateLimitWorkaroundActive()) + { + // need to fallback to paint in view coordinates, unfortunately + // need to transform self (cairo will do it wrong in this coordinate + // space), so no need to try to buffer + cairo_new_path(mpRT); + basegfx::B2DPolygon aAdaptedPolygon(rPolygon); + const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0); + aAdaptedPolygon.transform(basegfx::utils::createTranslateB2DHomMatrix(fAAOffset, fAAOffset) + * getViewInformation2D().getObjectToViewTransformation()); + cairo_identity_matrix(mpRT); + addB2DPolygonToPathGeometry(mpRT, aAdaptedPolygon); + cairo_stroke(mpRT); + } + else + { + // set linear transformation. use own, prepared, re-usable + // ObjectToViewTransformation and PolyPoylgon data and let + // cairo do the transformations + cairo_matrix_t aMatrix; + const basegfx::B2DHomMatrix& rObjectToView( + getViewInformation2D().getObjectToViewTransformation()); + const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0); + cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), + rObjectToView.d(), rObjectToView.e() + fAAOffset, + rObjectToView.f() + fAAOffset); + cairo_set_matrix(mpRT, &aMatrix); + + // get PathGeometry & paint it + cairo_new_path(mpRT); + getOrCreatePathGeometry(mpRT, rPolygon, getViewInformation2D(), + getViewInformation2D().getUseAntiAliasing()); + cairo_stroke(mpRT); + } cairo_restore(mpRT); } @@ -1379,14 +1471,6 @@ void CairoPixelProcessor2D::paintPolyPoylgonRGBA(const basegfx::B2DPolyPolygon& cairo_save(mpRT); - // set linear transformation - cairo_matrix_t aMatrix; - const basegfx::B2DHomMatrix& rObjectToView( - getViewInformation2D().getObjectToViewTransformation()); - cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), - rObjectToView.d(), rObjectToView.e(), rObjectToView.f()); - cairo_set_matrix(mpRT, &aMatrix); - // determine & set color const basegfx::BColor aFillColor(maBColorModifierStack.getModifiedColor(rColor)); @@ -1397,10 +1481,36 @@ void CairoPixelProcessor2D::paintPolyPoylgonRGBA(const basegfx::B2DPolyPolygon& cairo_set_source_rgb(mpRT, aFillColor.getRed(), aFillColor.getGreen(), aFillColor.getBlue()); - // get PathGeometry & paint it - cairo_new_path(mpRT); - getOrCreateFillGeometry(mpRT, rPolyPolygon); - cairo_fill(mpRT); + if (isCairoCoordinateLimitWorkaroundActive()) + { + // need to fallback to paint in view coordinates, unfortunately + // need to transform self (cairo will do it wrong in this coordinate + // space), so no need to try to buffer + cairo_new_path(mpRT); + basegfx::B2DPolyPolygon aAdaptedPolyPolygon(rPolyPolygon); + aAdaptedPolyPolygon.transform(getViewInformation2D().getObjectToViewTransformation()); + cairo_identity_matrix(mpRT); + for (const auto& rPolygon : aAdaptedPolyPolygon) + addB2DPolygonToPathGeometry(mpRT, rPolygon); + cairo_fill(mpRT); + } + else + { + // set linear transformation. use own, prepared, re-usable + // ObjectToViewTransformation and PolyPoylgon data and let + // cairo do the transformations + cairo_matrix_t aMatrix; + const basegfx::B2DHomMatrix& rObjectToView( + getViewInformation2D().getObjectToViewTransformation()); + cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), + rObjectToView.d(), rObjectToView.e(), rObjectToView.f()); + cairo_set_matrix(mpRT, &aMatrix); + + // get PathGeometry & paint it + cairo_new_path(mpRT); + getOrCreateFillGeometry(mpRT, rPolyPolygon); + cairo_fill(mpRT); + } cairo_restore(mpRT); } @@ -1678,24 +1788,41 @@ void CairoPixelProcessor2D::processMaskPrimitive2D( cairo_save(mpRT); - // set linear transformation for applying mask. use no fAAOffset for mask - cairo_matrix_t aMatrix; - const basegfx::B2DHomMatrix& rObjectToView( - getViewInformation2D().getObjectToViewTransformation()); - cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), - rObjectToView.d(), rObjectToView.e(), rObjectToView.f()); - cairo_set_matrix(mpRT, &aMatrix); + if (isCairoCoordinateLimitWorkaroundActive()) + { + // need to fallback to paint in view coordinates, unfortunately + // need to transform self (cairo will do it wrong in this coordinate + // space), so no need to try to buffer + cairo_new_path(mpRT); + basegfx::B2DPolyPolygon aAdaptedPolyPolygon(rMask); + aAdaptedPolyPolygon.transform(getViewInformation2D().getObjectToViewTransformation()); + for (const auto& rPolygon : aAdaptedPolyPolygon) + addB2DPolygonToPathGeometry(mpRT, rPolygon); - // create path geometry and put mask as path - cairo_new_path(mpRT); - getOrCreateFillGeometry(mpRT, rMask); + // clip to this mask + cairo_clip(mpRT); + } + else + { + // set linear transformation for applying mask. use no fAAOffset for mask + cairo_matrix_t aMatrix; + const basegfx::B2DHomMatrix& rObjectToView( + getViewInformation2D().getObjectToViewTransformation()); + cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), + rObjectToView.d(), rObjectToView.e(), rObjectToView.f()); + cairo_set_matrix(mpRT, &aMatrix); - // clip to this mask - cairo_clip(mpRT); + // create path geometry and put mask as path + cairo_new_path(mpRT); + getOrCreateFillGeometry(mpRT, rMask); - // reset transformation to not have it set when processing - // child content below (was only used to set clip path) - cairo_identity_matrix(mpRT); + // clip to this mask + cairo_clip(mpRT); + + // reset transformation to not have it set when processing + // child content below (was only used to set clip path) + cairo_identity_matrix(mpRT); + } // process sub-content (that shall be masked) mnClipRecursionCount++; @@ -1957,14 +2084,6 @@ void CairoPixelProcessor2D::processPolygonStrokePrimitive2D( cairo_save(mpRT); - // set linear transformation - cairo_matrix_t aMatrix; - const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0); - cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), - rObjectToView.d(), rObjectToView.e() + fAAOffset, - rObjectToView.f() + fAAOffset); - cairo_set_matrix(mpRT, &aMatrix); - // setup line attributes cairo_line_join_t eCairoLineJoin = CAIRO_LINE_JOIN_MITER; switch (rLineAttribute.getLineJoin()) @@ -2015,33 +2134,77 @@ void CairoPixelProcessor2D::processPolygonStrokePrimitive2D( aLineColor.setRed(0.5); cairo_set_source_rgb(mpRT, aLineColor.getRed(), aLineColor.getGreen(), aLineColor.getBlue()); - // process/set LineWidth - const double fObjectLineWidth( - bHairline ? (getViewInformation2D().getInverseObjectToViewTransformation() - * basegfx::B2DVector(1.0, 0.0)) - .getLength() - : rLineAttribute.getWidth()); - cairo_set_line_width(mpRT, fObjectLineWidth); - // check stroke const attribute::StrokeAttribute& rStrokeAttribute( rPolygonStrokeCandidate.getStrokeAttribute()); const bool bDashUsed(!rStrokeAttribute.isDefault() && !rStrokeAttribute.getDotDashArray().empty() && 0.0 < rStrokeAttribute.getFullDotDashLen()); - if (bDashUsed) - { - const std::vector<double>& rStroke = rStrokeAttribute.getDotDashArray(); - cairo_set_dash(mpRT, rStroke.data(), rStroke.size(), 0.0); + if (isCairoCoordinateLimitWorkaroundActive()) + { + // need to fallback to paint in view coordinates, unfortunately + // need to transform self (cairo will do it wrong in this coordinate + // space), so no need to try to buffer + cairo_new_path(mpRT); + basegfx::B2DPolygon aAdaptedPolygon(rPolygon); + const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0); + aAdaptedPolygon.transform(basegfx::utils::createTranslateB2DHomMatrix(fAAOffset, fAAOffset) + * getViewInformation2D().getObjectToViewTransformation()); + cairo_identity_matrix(mpRT); + addB2DPolygonToPathGeometry(mpRT, aAdaptedPolygon); + + // process/set LineWidth + const double fObjectLineWidth(bHairline + ? 1.0 + : (getViewInformation2D().getObjectToViewTransformation() + * basegfx::B2DVector(rLineAttribute.getWidth(), 0.0)) + .getLength()); + cairo_set_line_width(mpRT, fObjectLineWidth); + + if (bDashUsed) + { + std::vector<double> aStroke(rStrokeAttribute.getDotDashArray()); + for (auto& rCandidate : aStroke) + rCandidate = (getViewInformation2D().getObjectToViewTransformation() + * basegfx::B2DVector(rCandidate, 0.0)) + .getLength(); + cairo_set_dash(mpRT, aStroke.data(), aStroke.size(), 0.0); + } + + cairo_stroke(mpRT); } + else + { + // set linear transformation + cairo_matrix_t aMatrix; + const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0); + cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), + rObjectToView.d(), rObjectToView.e() + fAAOffset, + rObjectToView.f() + fAAOffset); + cairo_set_matrix(mpRT, &aMatrix); - // create path geometry and put mask as path - cairo_new_path(mpRT); - getOrCreatePathGeometry(mpRT, rPolygon, getViewInformation2D(), - bHairline && getViewInformation2D().getUseAntiAliasing()); + // create path geometry and put mask as path + cairo_new_path(mpRT); + getOrCreatePathGeometry(mpRT, rPolygon, getViewInformation2D(), + bHairline && getViewInformation2D().getUseAntiAliasing()); - // render - cairo_stroke(mpRT); + // process/set LineWidth + const double fObjectLineWidth( + bHairline ? (getViewInformation2D().getInverseObjectToViewTransformation() + * basegfx::B2DVector(1.0, 0.0)) + .getLength() + : rLineAttribute.getWidth()); + cairo_set_line_width(mpRT, fObjectLineWidth); + + if (bDashUsed) + { + const std::vector<double>& rStroke = rStrokeAttribute.getDotDashArray(); + cairo_set_dash(mpRT, rStroke.data(), rStroke.size(), 0.0); + } + + // render + cairo_stroke(mpRT); + } cairo_restore(mpRT); } @@ -2057,16 +2220,11 @@ void CairoPixelProcessor2D::processLineRectanglePrimitive2D( cairo_save(mpRT); - cairo_matrix_t aMatrix; + // work in view coordinates const double fAAOffset(getViewInformation2D().getUseAntiAliasing() ? 0.5 : 0.0); - const basegfx::B2DHomMatrix& rObjectToView( - getViewInformation2D().getObjectToViewTransformation()); - cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), - rObjectToView.d(), rObjectToView.e() + fAAOffset, - rObjectToView.f() + fAAOffset); - - // set linear transformation - cairo_set_matrix(mpRT, &aMatrix); + basegfx::B2DRange aRange(rLineRectanglePrimitive2D.getB2DRange()); + aRange.transform(getViewInformation2D().getObjectToViewTransformation()); + cairo_identity_matrix(mpRT); const basegfx::BColor aHairlineColor( maBColorModifierStack.getModifiedColor(rLineRectanglePrimitive2D.getBColor())); @@ -2078,9 +2236,8 @@ void CairoPixelProcessor2D::processLineRectanglePrimitive2D( .getLength()); cairo_set_line_width(mpRT, fDiscreteLineWidth); - const basegfx::B2DRange& rRange(rLineRectanglePrimitive2D.getB2DRange()); - cairo_rectangle(mpRT, rRange.getMinX(), rRange.getMinY(), rRange.getWidth(), - rRange.getHeight()); + cairo_rectangle(mpRT, aRange.getMinX() + fAAOffset, aRange.getMinY() + fAAOffset, + aRange.getWidth(), aRange.getHeight()); cairo_stroke(mpRT); cairo_restore(mpRT); @@ -2097,22 +2254,17 @@ void CairoPixelProcessor2D::processFilledRectanglePrimitive2D( cairo_save(mpRT); - cairo_matrix_t aMatrix; - const basegfx::B2DHomMatrix& rObjectToView( - getViewInformation2D().getObjectToViewTransformation()); - cairo_matrix_init(&aMatrix, rObjectToView.a(), rObjectToView.b(), rObjectToView.c(), - rObjectToView.d(), rObjectToView.e(), rObjectToView.f()); - - // set linear transformation - cairo_set_matrix(mpRT, &aMatrix); + // work in view coordinates + basegfx::B2DRange aRange(rFilledRectanglePrimitive2D.getB2DRange()); + aRange.transform(getViewInformation2D().getObjectToViewTransformation()); + cairo_identity_matrix(mpRT); const basegfx::BColor aFillColor( maBColorModifierStack.getModifiedColor(rFilledRectanglePrimitive2D.getBColor())); cairo_set_source_rgb(mpRT, aFillColor.getRed(), aFillColor.getGreen(), aFillColor.getBlue()); - const basegfx::B2DRange& rRange(rFilledRectanglePrimitive2D.getB2DRange()); - cairo_rectangle(mpRT, rRange.getMinX(), rRange.getMinY(), rRange.getWidth(), - rRange.getHeight()); + cairo_rectangle(mpRT, aRange.getMinX(), aRange.getMinY(), aRange.getWidth(), + aRange.getHeight()); cairo_fill(mpRT); cairo_restore(mpRT); @@ -2132,6 +2284,7 @@ void CairoPixelProcessor2D::processSingleLinePrimitive2D( getViewInformation2D().getObjectToViewTransformation()); const basegfx::B2DPoint aStart(rObjectToView * rSingleLinePrimitive2D.getStart()); const basegfx::B2DPoint aEnd(rObjectToView * rSingleLinePrimitive2D.getEnd()); + cairo_identity_matrix(mpRT); cairo_set_line_width(mpRT, 1.0f); @@ -3717,6 +3870,47 @@ void CairoPixelProcessor2D::processControlPrimitive2D( process(rControlPrimitive); } +void CairoPixelProcessor2D::evaluateCairoCoordinateLimitWorkaround() +{ + static bool bAlreadyCheckedIfNeeded(false); + static bool bIsNeeded(false); + + if (!bAlreadyCheckedIfNeeded) + { + // check once for office runtime: is workarund needed? + bAlreadyCheckedIfNeeded = true; + bIsNeeded = checkCoordinateLimitWorkaroundNeededForUsedCairo(); + } + + if (!bIsNeeded) + { + // we have a working cairo, so workarund is not needed + // and mbCairoCoordinateLimitWorkaroundActive can stay false + return; + } + + // get discrete size (pixels) + basegfx::B2DRange aLogicViewRange(getDiscreteViewRange(mpRT)); + + // transform to world coordinates -> logic view range + basegfx::B2DHomMatrix aInvViewTrans(getViewInformation2D().getViewTransformation()); + aInvViewTrans.invert(); + aLogicViewRange.transform(aInvViewTrans); + + // create 1<<23 CairoCoordinate limit from 24.8 internal format + // and a range fitting to it (just once, this is static) + constexpr double fNumCairoMax(1 << 23); + static const basegfx::B2DRange aNumericalCairoLimit(-fNumCairoMax, -fNumCairoMax, + fNumCairoMax - 1.0, fNumCairoMax - 1.0); + + if (!aLogicViewRange.isEmpty() && !aNumericalCairoLimit.isInside(aLogicViewRange)) + { + // aLogicViewRange is not completely inside region covered by + // 24.8 cairo format, thus workaround is needed, set flag + mbCairoCoordinateLimitWorkaroundActive = true; + } +} + void CairoPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { const cairo_status_t aStart(cairo_status(mpRT)); diff --git a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx index fc67ed78932b..3d20f300a972 100644 --- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx +++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx @@ -86,6 +86,9 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub // see comment there sal_uInt16 mnClipRecursionCount; + // calculated result of if we are in outsideCairoCoordinateLimits mode + bool mbCairoCoordinateLimitWorkaroundActive; + // helpers for direct paints void paintPolyPoylgonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rColor, double fTransparency = 0.0); @@ -179,6 +182,9 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub void processFillGradientPrimitive2D_square_rect( const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D); + // check if CairoCoordinateLimitWorkaround is needed + void evaluateCairoCoordinateLimitWorkaround(); + protected: bool hasError() const { return cairo_status(mpRT) != CAIRO_STATUS_SUCCESS; } bool hasRenderTarget() const { return nullptr != mpRT; } @@ -186,6 +192,12 @@ protected: public: bool valid() const { return hasRenderTarget() && !hasError(); } + // read access to CairoCoordinateLimitWorkaround mechanism + bool isCairoCoordinateLimitWorkaroundActive() const + { + return mbCairoCoordinateLimitWorkaroundActive; + } + // constructor to create a CairoPixelProcessor2D which // allocates and owns a cairo surface of given size. You // should check the result using valid() commit 35aef2e143f947e9ef931dd30dd4e1fc8ce59e2f Author: Xisco Fauli <[email protected]> AuthorDate: Thu Feb 13 16:24:33 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 curl: upgrade to 8.12.1 Downloaded from https://curl.se/download/curl-8.12.1.tar.xz Change-Id: I038e6bb402a5c6f19ac30efd9e8aa1aaf020b63b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181630 Tested-by: Jenkins Reviewed-by: Xisco Fauli <[email protected]> (cherry picked from commit ff8400cdecfa152ca1a58412f4a52f0467f874d3) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181648 Reviewed-by: Taichi Haradaguchi <[email protected]> diff --git a/download.lst b/download.lst index 7ffd5d7ccf77..0409827ea73e 100644 --- a/download.lst +++ b/download.lst @@ -80,8 +80,8 @@ CPPUNIT_TARBALL := cppunit-1.15.1.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts -CURL_SHA256SUM := 9a4628c764be6b1a9909567c13e8e771041609df43b2158fcac4e05ea7097e5d -CURL_TARBALL := curl-8.12.0.tar.xz +CURL_SHA256SUM := 0341f1ed97a26c811abaebd37d62b833956792b7607ea3f15d001613c76de202 +CURL_TARBALL := curl-8.12.1.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts commit c3de6083f393925ab42c831cf265f4cd4678d61b Author: Xisco Fauli <[email protected]> AuthorDate: Mon Jan 13 10:16:41 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 tdf#164620: sw_uiwriter3: Add unittest and fix another edge case it found. Change-Id: Ia57ae1c9a13279f240b78f90fd05faa2f0da7ce5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180162 Tested-by: Jenkins Reviewed-by: Noel Grandin <[email protected]> (cherry picked from commit ff7bd4d2ac03f39f1da8ead9a6474e84d0f7b277) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181640 Reviewed-by: Xisco Fauli <[email protected]> diff --git a/sw/qa/extras/uiwriter/data/tdf164620.docx b/sw/qa/extras/uiwriter/data/tdf164620.docx new file mode 100644 index 000000000000..6e74b6bf7fe3 Binary files /dev/null and b/sw/qa/extras/uiwriter/data/tdf164620.docx differ diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx index 96ef31c0cc46..de126574ca78 100644 --- a/sw/qa/extras/uiwriter/uiwriter3.cxx +++ b/sw/qa/extras/uiwriter/uiwriter3.cxx @@ -1189,6 +1189,24 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf100691) CPPUNIT_ASSERT_EQUAL(u"Text 1"_ustr, pNext->GetText()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf164620) +{ + createSwDoc("tdf164620.docx"); + + CPPUNIT_ASSERT_EQUAL(2, getPages()); + + dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {}); + + // Without the fix in place, this test would have crashed here + dispatchCommand(mxComponent, u".uno:Delete"_ustr, {}); + + CPPUNIT_ASSERT_EQUAL(1, getPages()); + + dispatchCommand(mxComponent, u".uno:Undo"_ustr, {}); + + CPPUNIT_ASSERT_EQUAL(2, getPages()); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf134404) { createSwDoc("tdf134404.odt"); diff --git a/sw/source/core/fields/reffld.cxx b/sw/source/core/fields/reffld.cxx index 446996f6341a..a18d85650c38 100644 --- a/sw/source/core/fields/reffld.cxx +++ b/sw/source/core/fields/reffld.cxx @@ -1606,6 +1606,9 @@ SwTextNode* SwGetRefFieldType::FindAnchorRefStyleOther(SwDoc* pDoc, SwNodeOffset nReference = pReference->GetIndex(); const SwNodes& nodes = pDoc->GetNodes(); + if (&nodes != &pReference->GetNodes()) + return nullptr; + // It is possible to end up here, with a pReference pointer which points to a node which has already been // removed from the nodes array, which means that calling GetIndex() returns an incorrect index. if (nReference >= nodes.Count() || nodes[nReference] != pReference) commit dc193177eb22c7892c941c74cd4f9c1c6e0ba6e6 Author: Armin Le Grand (Collabora) <[email protected]> AuthorDate: Thu Feb 13 11:44:13 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 tdf#165061 CairoSDPR: regression: Fix RTL usage See comments in task, for now disable using SDPR when RTL is enabled. Change-Id: I9dabe2324fb9e6b190ebb3851dc73b2c7dacf84d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181604 Tested-by: Jenkins Reviewed-by: Armin Le Grand <[email protected]> (cherry picked from commit 8acd6b515e087ce60d3ddefec162a208951fe082) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181625 Reviewed-by: Xisco Fauli <[email protected]> diff --git a/drawinglayer/source/processor2d/processor2dtools.cxx b/drawinglayer/source/processor2d/processor2dtools.cxx index f87bffea6b21..e90cac41a6c1 100644 --- a/drawinglayer/source/processor2d/processor2dtools.cxx +++ b/drawinglayer/source/processor2d/processor2dtools.cxx @@ -106,7 +106,10 @@ std::unique_ptr<BaseProcessor2D> createPixelProcessor2DFromOutputDevice( // possibility to deactivate for easy test/request testing static bool bUsePrimitiveRenderer(nullptr == std::getenv("DISABLE_SYSTEM_DEPENDENT_PRIMITIVE_RENDERER")); - if (bUsePrimitiveRenderer) + if (bUsePrimitiveRenderer + // tdf#165061 do not use SDPR when RTL is enabled, SDPR is designed + // for rendering EditViews and does not support RTL (yet?) + && !rTargetOutDev.IsRTLEnabled()) { SystemGraphicsData aData(rTargetOutDev.GetSystemGfxData()); commit acaed87c12d887e64b6cf299fbe0aa26ec7fba77 Author: Xisco Fauli <[email protected]> AuthorDate: Mon Feb 10 10:35:53 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 libffi: upgrade to 3.4.7 Downloaded from https://github.com/libffi/libffi/releases/download/v3.4.7/libffi-3.4.7.tar.gz Change-Id: I02f4137ed0cdaab74dc3630928e2567d0e9b3360 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181334 Reviewed-by: Xisco Fauli <[email protected]> Tested-by: Jenkins (cherry picked from commit f26e7468cb3467f969a96bf5cebb8d300dc88973) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181365 Reviewed-by: Michael Stahl <[email protected]> diff --git a/download.lst b/download.lst index e00a0c079003..7ffd5d7ccf77 100644 --- a/download.lst +++ b/download.lst @@ -492,8 +492,8 @@ LIBEXTTEXTCAT_TARBALL := libexttextcat-3.4.7.tar.xz # three static lines # so that git cherry-pick # will not run into conflicts -LIBFFI_SHA256SUM := b0dea9df23c863a7a50e825440f3ebffabd65df1497108e5d437747843895a4e -LIBFFI_TARBALL := libffi-3.4.6.tar.gz +LIBFFI_SHA256SUM := 138607dee268bdecf374adf9144c00e839e38541f75f24a1fcf18b78fda48b2d +LIBFFI_TARBALL := libffi-3.4.7.tar.gz # three static lines # so that git cherry-pick # will not run into conflicts commit 5284be6404419ff0d956def7d245599ca4d9d814 Author: Michael Weghorn <[email protected]> AuthorDate: Wed Feb 5 11:26:43 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 browsebox a11y: Use recursive mutex Fixes a deadlock seen for this scenario with the qt6 VCL plugin on Linux: 1) start Orca 2) Start Base, create a new database 2) With the "Tables" section enabled, click on "Create Table in Design View..." 3) click around in the table, use Tab key to move focus AccessibleBrowseBoxAccess::commitEvent (frame 20 in the below backtrace) locks the mutex, and then AccessibleBrowseBoxAccess::getAccessibleContext (frame 8) tries to acquire the mutex again and deadlocks. Locking in AccessibleBrowseBoxAccess::commitEvent was added in commit 67158da00e965c90495bb4f339ea25bbec898c60 Date: Fri Oct 4 14:22:22 2024 +0100 cid#1608061 Data race condition and cid#1607995 Data race condition Backtrace: Thread 1 "soffice.bin" received signal SIGINT, Interrupt. futex_wait (futex_word=0x7fffd804ba30, expected=2, private=0) at ../sysdeps/nptl/futex-internal.h:146 warning: 146 ../sysdeps/nptl/futex-internal.h: No such file or directory (gdb) bt #0 futex_wait (futex_word=0x7fffd804ba30, expected=2, private=0) at ../sysdeps/nptl/futex-internal.h:146 #1 __GI___lll_lock_wait (futex=futex@entry=0x7fffd804ba30, private=0) at ./nptl/lowlevellock.c:49 #2 0x00007ffff789f3a2 in lll_mutex_lock_optimized (mutex=0x7fffd804ba30) at ./nptl/pthread_mutex_lock.c:48 #3 ___pthread_mutex_lock (mutex=0x7fffd804ba30) at ./nptl/pthread_mutex_lock.c:93 #4 0x00007fffee0d742f in __gthread_mutex_lock (__mutex=0x7fffd804ba30) at /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14/bits/gthr-default.h:762 #5 0x00007fffee0d9915 in std::mutex::lock (this=0x7fffd804ba30) at /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/std_mutex.h:113 #6 0x00007fffee0d98e4 in std::unique_lock<std::mutex>::lock (this=0x7fffffff3b48) at /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:147 #7 0x00007fffee0d8108 in std::unique_lock<std::mutex>::unique_lock (this=0x7fffffff3b48, __m=...) at /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/unique_lock.h:73 #8 0x00007fffee0d729d in AccessibleBrowseBoxAccess::getAccessibleContext (this=0x7fffd804ba00) at /home/michi/development/git/libreoffice/vcl/source/accessibility/AccessibleBrowseBox.cxx:281 #9 0x00007fffee0d7404 in non-virtual thunk to AccessibleBrowseBoxAccess::getAccessibleContext() () at /home/michi/development/git/libreoffice/instdir/program/libvcllo.so #10 0x00007fffe42c3b8c in QtAccessibleWidget::getAccessibleContextImpl (this=0x7fffd804b9a0) at vcl/qt6/../qt5/QtAccessibleWidget.cxx:93 #11 0x00007fffe42c451d in QtAccessibleWidget::childCount (this=0x7fffd804b9a0) at vcl/qt6/../qt5/QtAccessibleWidget.cxx:149 #12 0x00007fffe290e9d5 in AtSpiAdaptor::notifyAboutCreation (this=0x555556916e10, interface=0x7fffd8051df0) at /home/michi/development/git/qt5/qtbase/src/gui/accessible/linux/atspiadaptor.cpp:1403 #13 0x00007fffe290ad18 in AtSpiAdaptor::notify (this=0x555556916e10, event=0x7fffffff5e40) at /home/michi/development/git/qt5/qtbase/src/gui/accessible/linux/atspiadaptor.cpp:971 #14 0x00007fffe2966779 in QSpiAccessibleBridge::notifyAccessibilityUpdate (this=0x5555568aab30, event=0x7fffffff5e40) at /home/michi/development/git/qt5/qtbase/src/gui/accessible/linux/qspiaccessiblebridge.cpp:85 #15 0x00007fffe28e5c89 in QAccessible::updateAccessibility (event=0x7fffffff5e40) at /home/michi/development/git/qt5/qtbase/src/gui/accessible/qaccessible.cpp:943 #16 0x00007fffe42bb466 in QtAccessibleEventListener::notifyEvent (this=0x555557d6de30, rEvent=...) at vcl/qt6/../qt5/QtAccessibleEventListener.cxx:231 #17 0x00007ffff60ec617 in comphelper::AccessibleEventNotifier::addEvent (_nClient=288, _rEvent=...) at /home/michi/development/git/libreoffice/comphelper/source/misc/accessibleeventnotifier.cxx:256 #18 0x00007ffff60e8107 in comphelper::OCommonAccessibleComponent::NotifyAccessibleEvent (this=0x55555be2f520, _nEventId=7, _rOldValue=uno::Any(void), _rNewValue=uno::Any("com.sun.star.accessibility.XAccessible": ...), nIndexHint=-1) at /home/michi/development/git/libreoffice/comphelper/source/misc/accessiblecomponenthelper.cxx:127 #19 0x00007fffee0dd7c9 in AccessibleBrowseBoxBase::commitEvent (this=0x55555be2f520, _nEventId=7, _rNewValue=uno::Any("com.sun.star.accessibility.XAccessible": ...), _rOldValue=uno::Any(void)) at /home/michi/development/git/libreoffice/vcl/source/accessibility/AccessibleBrowseBoxBase.cxx:310 #20 0x00007fffee0d8fb0 in AccessibleBrowseBoxAccess::commitEvent (this=0x7fffd804ba00, nEventId=7, rNewValue=uno::Any("com.sun.star.accessibility.XAccessible": ...), rOldValue=uno::Any(void)) at vcl/inc/accessibility/AccessibleBrowseBox.hxx:250 #21 0x00007ffff08806b6 in BrowseBox::commitBrowseBoxEvent (this=0x55555bdc8bf0, _nEventId=7, _rNewValue=uno::Any("com.sun.star.accessibility.XAccessible": ...), _rOldValue=uno::Any(void)) at /home/michi/development/git/libreoffice/svtools/source/brwbox/brwbox3.cxx:406 #22 0x00007ffff08a090b in svt::EditBrowseBox::implCreateActiveAccessible (this=0x55555bdc8bf0) at /home/michi/development/git/libreoffice/svtools/source/brwbox/editbrowsebox2.cxx:87 #23 0x00007ffff089c7af in svt::EditBrowseBox::ActivateCell (this=0x55555bdc8bf0, nRow=0, nCol=1, bCellFocus=true) at /home/michi/development/git/libreoffice/svtools/source/brwbox/editbrowsebox.cxx:945 #24 0x00007ffff089e6c0 in svt::EditBrowseBox::ActivateCell (this=0x55555bdc8bf0) at include/svtools/editbrowsebox.hxx:1029 #25 0x00007ffff089b291 in svt::EditBrowseBox::implActivateCellOnMouseEvent (this=0x55555bdc8bf0, _rEvt=..., _bUp=true) at /home/michi/development/git/libreoffice/svtools/source/brwbox/editbrowsebox.cxx:482 #26 0x00007ffff089b43c in svt::EditBrowseBox::MouseButtonUp (this=0x55555bdc8bf0, rEvt=...) at /home/michi/development/git/libreoffice/svtools/source/brwbox/editbrowsebox.cxx:468 #27 0x00007ffff08876ad in BrowserDataWin::MouseButtonUp (this=0x555556fed350, rEvt=...) at /home/michi/development/git/libreoffice/svtools/source/brwbox/datwin.cxx:490 #28 0x00007fffee4b1055 in ImplHandleMouseEvent (xWindow=..., nSVEvent=NotifyEventType::MOUSEBUTTONUP, bMouseLeave=false, nX=73, nY=89, nMsgTime=10536810, nCode=1, nMode=(MouseEventModifiers::SIMPLECLICK | MouseEventModifiers::SELECT)) at /home/michi/development/git/libreoffice/vcl/source/window/winproc.cxx:719 #29 0x00007fffee4b5571 in ImplHandleSalMouseButtonUp (pWindow=0x7fffd80482c0, pEvent=0x7fffffff8118) at /home/michi/development/git/libreoffice/vcl/source/window/winproc.cxx:2351 #30 0x00007fffee4b4280 in ImplWindowFrameProc (_pWindow=0x7fffd80482c0, nEvent=SalEvent::MouseButtonUp, pEvent=0x7fffffff8118) at /home/michi/development/git/libreoffice/vcl/source/window/winproc.cxx:2700 #31 0x00007fffe435910c in SalFrame::CallCallback (this=0x555556abc050, nEvent=SalEvent::MouseButtonUp, pEvent=0x7fffffff8118) at vcl/inc/salframe.hxx:311 #32 0x00007fffe43563b5 in QtFrame::CallCallback (this=0x555556abc040, nEvent=SalEvent::MouseButtonUp, pEvent=0x7fffffff8118) at vcl/inc/qt6/../qt5/QtFrame.hxx:235 #33 0x00007fffe445475a in QtWidget::handleMouseButtonEvent (rFrame=..., pEvent=0x7fffffff93c0) at vcl/qt6/../qt5/QtWidget.cxx:117 #34 0x00007fffe4454a11 in QtWidget::mouseReleaseEvent (this=0x7fffd8048d90, pEvent=0x7fffffff93c0) at vcl/qt6/../qt5/QtWidget.cxx:128 #35 0x00007fffe149f8ad in QWidget::event (this=0x7fffd8048d90, event=0x7fffffff93c0) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qwidget.cpp:8964 #36 0x00007fffe44569ae in QtWidget::event (this=0x7fffd8048d90, pEvent=0x7fffffff93c0) at vcl/qt6/../qt5/QtWidget.cxx:678 #37 0x00007fffe13e2e20 in QApplicationPrivate::notify_helper (this=0x555555577ae0, receiver=0x7fffd8048d90, e=0x7fffffff93c0) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3305 #38 0x00007fffe13e4af2 in QApplication::notify (this=0x555555564d60, receiver=0x7fffd8048d90, e=0x7fffffff93c0) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:2782 #39 0x00007fffe344b419 in QCoreApplication::notifyInternal2 (receiver=0x7fffd8048d90, event=0x7fffffff93c0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1112 #40 0x00007fffe344c119 in QCoreApplication::sendSpontaneousEvent (receiver=0x7fffd8048d90, event=0x7fffffff93c0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1566 #41 0x00007fffe13e3747 in QApplicationPrivate::sendMouseEvent (receiver=0x7fffd8048d90, event=0x7fffffff93c0, alienWidget=0x7fffd8048d90, nativeWidget=0x555556f2f660, buttonDown=0x7fffe1fca488 <qt_button_down>, lastMouseReceiver=..., spontaneous=true, onlyDispatchEnterLeave=false) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:2363 #42 0x00007fffe14ded48 in QWidgetWindow::handleMouseEvent (this=0x5555577f5b40, event=0x7fffffffa498) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qwidgetwindow.cpp:669 #43 0x00007fffe14dd555 in QWidgetWindow::event (this=0x5555577f5b40, event=0x7fffffffa498) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qwidgetwindow.cpp:292 #44 0x00007fffe13e2e20 in QApplicationPrivate::notify_helper (this=0x555555577ae0, receiver=0x5555577f5b40, e=0x7fffffffa498) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3305 #45 0x00007fffe13e6d3d in QApplication::notify (this=0x555555564d60, receiver=0x5555577f5b40, e=0x7fffffffa498) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3255 #46 0x00007fffe344b419 in QCoreApplication::notifyInternal2 (receiver=0x5555577f5b40, event=0x7fffffffa498) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1112 #47 0x00007fffe344c119 in QCoreApplication::sendSpontaneousEvent (receiver=0x5555577f5b40, event=0x7fffffffa498) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1566 #48 0x00007fffe2285ca2 in QGuiApplicationPrivate::processMouseEvent (e=0x7fffd0001560) at /home/michi/development/git/qt5/qtbase/src/gui/kernel/qguiapplication.cpp:2485 #49 0x00007fffe2284e66 in QGuiApplicationPrivate::processWindowSystemEvent (e=0x7fffd0001560) at /home/michi/development/git/qt5/qtbase/src/gui/kernel/qguiapplication.cpp:2212 #50 0x00007fffe236d57d in QWindowSystemInterface::sendWindowSystemEvents (flags=...) at /home/michi/development/git/qt5/qtbase/src/gui/kernel/qwindowsysteminterface.cpp:1113 #51 0x00007fffe236d42e in QWindowSystemInterface::flushWindowSystemEvents (flags=...) at /home/michi/development/git/qt5/qtbase/src/gui/kernel/qwindowsysteminterface.cpp:1082 #52 0x00007fffdf8b2685 in QtWaylandClient::QWaylandDisplay::flushRequests (this=0x5555555c8390) at /home/michi/development/git/qt5/qtwayland/src/client/qwaylanddisplay.cpp:526 #53 0x00007fffdf8ce4e5 in QtPrivate::FunctorCall<std::integer_sequence<unsigned long>, QtPrivate::List<>, void, void (QtWaylandClient::QWaylandDisplay::*)()>::call(void (QtWaylandClient::QWaylandDisplay::*)(), QtWaylandClient::QWaylandDisplay*, void**)::{lambda()#1}::operator()() const (this=0x7fffffffa9a0) at qtbase/src/corelib/kernel/qobjectdefs_impl.h:127 #54 0x00007fffdf8ce40d in QtPrivate::FunctorCallBase::call_internal<void, QtPrivate::FunctorCall<std::integer_sequence<unsigned long>, QtPrivate::List<>, void, void (QtWaylandClient::QWaylandDisplay::*)()>::call(void (QtWaylandClient::QWaylandDisplay::*)(), QtWaylandClient::QWaylandDisplay*, void**)::{lambda()#1}>(void**, QtPrivate::FunctorCall<std::integer_sequence<unsigned long>, QtPrivate::List<>, void, void (QtWaylandClient::QWaylandDisplay::*)()>::call(void (QtWaylandClient::QWaylandDisplay::*)(), QtWaylandClient::QWaylandDisplay*, void**)::{lambda()#1}&&) (args=0x7fffd0002f98, fn=...) at qtbase/src/corelib/kernel/qobjectdefs_impl.h:65 #55 0x00007fffdf8ce32f in QtPrivate::FunctorCall<std::integer_sequence<unsigned long>, QtPrivate::List<>, void, void (QtWaylandClient::QWaylandDisplay::*)()>::call(void (QtWaylandClient::QWaylandDisplay::*)(), QtWaylandClient::QWaylandDisplay*, void**) (f=(void (QtWaylandClient::QWaylandDisplay::*)(class QtWaylandClient::QWaylandDisplay * const)) 0x7fffdf8b2640 <QtWaylandClient::QWaylandDisplay::flushRequests()>, o=0x5555555c8390, arg=0x7fffd0002f98) at qtbase/src/corelib/kernel/qobjectdefs_impl.h:126 #56 0x00007fffdf8ce2a1 in QtPrivate::FunctionPointer<void (QtWaylandClient::QWaylandDisplay::*)()>::call<QtPrivate::List<>, void>(void (QtWaylandClient::QWaylandDisplay::*)(), QtWaylandClient::QWaylandDisplay*, void**) (f=(void (QtWaylandClient::QWaylandDisplay::*)(class QtWaylandClient::QWaylandDisplay * const)) 0x7fffdf8b2640 <QtWaylandClient::QWaylandDisplay::flushRequests()>, o=0x5555555c8390, arg=0x7fffd0002f98) at qtbase/src/corelib/kernel/qobjectdefs_impl.h:174 #57 0x00007fffdf8ce1cb in QtPrivate::QCallableObject<void (QtWaylandClient::QWaylandDisplay::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0x5555555e1390, r=0x5555555c8390, a=0x7fffd0002f98, ret=0x0) at qtbase/src/corelib/kernel/qobjectdefs_impl.h:545 #58 0x00007fffe3461362 in QtPrivate::QSlotObjectBase::call (this=0x5555555e1390, r=0x5555555c8390, a=0x7fffd0002f98) at qtbase/src/corelib/kernel/qobjectdefs_impl.h:461 #59 0x00007fffe350ad5c in QMetaCallEvent::placeMetaCall (this=0x7fffd0002f50, object=0x5555555c8390) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qobject.cpp:620 #60 0x00007fffe350cab1 in QObject::event (this=0x5555555c8390, e=0x7fffd0002f50) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qobject.cpp:1429 #61 0x00007fffe13e2e20 in QApplicationPrivate::notify_helper (this=0x555555577ae0, receiver=0x5555555c8390, e=0x7fffd0002f50) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3305 #62 0x00007fffe13e6d3d in QApplication::notify (this=0x555555564d60, receiver=0x5555555c8390, e=0x7fffd0002f50) at /home/michi/development/git/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3255 #63 0x00007fffe344b419 in QCoreApplication::notifyInternal2 (receiver=0x5555555c8390, event=0x7fffd0002f50) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1112 #64 0x00007fffe344c089 in QCoreApplication::sendEvent (receiver=0x5555555c8390, event=0x7fffd0002f50) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1552 #65 0x00007fffe344cfc8 in QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=0, data=0x55555559f110) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1892 #66 0x00007fffe344becc in QCoreApplication::sendPostedEvents (receiver=0x0, event_type=0) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp:1746 #67 0x00007fffe3a3d4a1 in postEventSourceDispatch (s=0x5555555f0f80) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:246 #68 0x00007fffea10b81f in ??? () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 #69 0x00007fffea10da57 in ??? () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 #70 0x00007fffea10e1c0 in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 #71 0x00007fffe3a3c6db in QEventDispatcherGlib::processEvents (this=0x555555568dc0, flags=...) at /home/michi/development/git/qt5/qtbase/src/corelib/kernel/qeventdispatcher_glib.cpp:399 #72 0x00007fffe2b7a148 in QPAEventDispatcherGlib::processEvents (this=0x555555568dc0, flags=...) at /home/michi/development/git/qt5/qtbase/src/gui/platform/unix/qeventdispatcher_glib.cpp:89 #73 0x00007fffe4376a82 in QtInstance::ImplYield (this=0x5555555f5a00, bWait=true, bHandleAllCurrentEvents=false) at vcl/qt6/../qt5/QtInstance.cxx:485 #74 0x00007fffe4379d51 in QtInstance::DoYield (this=0x5555555f5a00, bWait=true, bHandleAllCurrentEvents=false) at vcl/qt6/../qt5/QtInstance.cxx:496 #75 0x00007fffeec869b6 in ImplYield (i_bWait=true, i_bAllEvents=false) at /home/michi/development/git/libreoffice/vcl/source/app/svapp.cxx:385 #76 0x00007fffeec862cf in Application::Yield () at /home/michi/development/git/libreoffice/vcl/source/app/svapp.cxx:488 #77 0x00007fffeec860b0 in Application::Execute () at /home/michi/development/git/libreoffice/vcl/source/app/svapp.cxx:360 #78 0x00007ffff7b287f9 in desktop::Desktop::Main (this=0x7fffffffd5d0) at /home/michi/development/git/libreoffice/desktop/source/app/app.cxx:1679 #79 0x00007fffeeca7e36 in ImplSVMain () at /home/michi/development/git/libreoffice/vcl/source/app/svmain.cxx:230 #80 0x00007fffeeca9a29 in SVMain () at /home/michi/development/git/libreoffice/vcl/source/app/svmain.cxx:248 #81 0x00007ffff7ba20da in soffice_main () at /home/michi/development/git/libreoffice/desktop/source/app/sofficemain.cxx:122 #82 0x0000555555555a6d in sal_main () at /home/michi/development/git/libreoffice/desktop/source/app/main.c:51 #83 0x0000555555555a47 in main (argc=2, argv=0x7fffffffd7d8) at /home/michi/development/git/libreoffice/desktop/source/app/main.c:49 Change-Id: Id3832663f5c5c66a4d624054fee4d48219732b95 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181155 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> (cherry picked from commit 71d1432714b7aba0a10ca5d072c87e46ec325271) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181542 Reviewed-by: Michael Stahl <[email protected]> diff --git a/accessibility/inc/extended/AccessibleBrowseBox.hxx b/accessibility/inc/extended/AccessibleBrowseBox.hxx index 50486973d4cd..9de32ccc1d8e 100644 --- a/accessibility/inc/extended/AccessibleBrowseBox.hxx +++ b/accessibility/inc/extended/AccessibleBrowseBox.hxx @@ -194,7 +194,7 @@ private: class AccessibleBrowseBoxAccess final : public ::vcl::IAccessibleBrowseBox { private: - mutable std::mutex m_aMutex; + mutable std::recursive_mutex m_aMutex; css::uno::Reference< css::accessibility::XAccessible > m_xParent; ::vcl::IAccessibleTableProvider& m_rBrowseBox; commit bd086f52ba6954b1a1eecacc2adba4cfa3601604 Author: Thorsten Behrens <[email protected]> AuthorDate: Fri Feb 7 04:40:44 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 IASS: Update mouse-as-pen status into live slideshow If live mode is enabled, reflect new settings of slideshow pen directly into the running slideshow. Change-Id: Ic44dc3b28c682366aba72383d24c552b7dd826da Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181227 Reviewed-by: Thorsten Behrens <[email protected]> Tested-by: Jenkins (cherry picked from commit 44575876825f1af7c5d0cf9c5f0c2450d61f4634) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181253 Reviewed-by: Adolfo Jayme Barrientos <[email protected]> diff --git a/sd/source/ui/func/fusldlg.cxx b/sd/source/ui/func/fusldlg.cxx index 95df1ad81c42..9198fa351194 100644 --- a/sd/source/ui/func/fusldlg.cxx +++ b/sd/source/ui/func/fusldlg.cxx @@ -32,6 +32,11 @@ #include <Window.hxx> #include <optsitem.hxx> #include <sdabstdlg.hxx> +#include <slideshow.hxx> +#include <ViewShell.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::presentation; namespace sd { @@ -166,13 +171,6 @@ void FuSlideShowDlg::DoExecute( SfxRequest& ) rPresentationSettings.mbMouseVisible = bValue; } - bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_PEN, SfxBoolItem ); - if ( bValue != rPresentationSettings.mbMouseAsPen ) - { - bValuesChanged = true; - rPresentationSettings.mbMouseAsPen = bValue; - } - bValue = !ITEMVALUE( aDlgSet, ATTR_PRESENT_CHANGE_PAGE, SfxBoolItem ); if ( bValue != rPresentationSettings.mbLockedPages ) { @@ -222,6 +220,20 @@ void FuSlideShowDlg::DoExecute( SfxRequest& ) rPresentationSettings.mbInteractive = bValue; } + bValue = ITEMVALUE( aDlgSet, ATTR_PRESENT_PEN, SfxBoolItem ); + if ( bValue != rPresentationSettings.mbMouseAsPen ) + { + bValuesChanged = true; + rPresentationSettings.mbMouseAsPen = bValue; + + // live slideshow? pass pen state on immediately + Reference< XSlideShowController > xSlideShowController( + SlideShow::GetSlideShowController(mpViewShell->GetViewShellBase() ) ); + if( xSlideShowController.is() ) + if(rPresentationSettings.mbInteractive) + xSlideShowController->setUsePen( bValue ); + } + pOptions->SetDisplay( aDlgSet.Get(ATTR_PRESENT_DISPLAY).GetValue() ); // is something has changed, we set the modified flag commit 29029dcb55f90f5a2d5cb466bca053e1f435ea85 Author: László Németh <[email protected]> AuthorDate: Tue Feb 11 01:22:42 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:21 2025 +0100 tdf#164499 sw smart justify: disable in tabulated lines to fix ToC Calculated extra text content without shrinking resulted overhanging text lines, e.g page numbers over the margin in ToC. Fix it by skipping space shrinking completely in tabulated lines, restoring also interoperability. Regression since commit 53de98b29548ded88e0a44c80256fc5e340d551e "tdf#158333 sw smart justify: fix multiple text portions". Change-Id: I390a254b8a47c6563d2c01a2f818f5ac6122e2ac Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181397 Tested-by: Jenkins Reviewed-by: László Németh <[email protected]> (cherry picked from commit ed7fbfce0b434f7d2a5542483d2838af51958e34) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181450 Reviewed-by: Adolfo Jayme Barrientos <[email protected]> diff --git a/sw/qa/extras/layout/data/tdf164499.docx b/sw/qa/extras/layout/data/tdf164499.docx new file mode 100644 index 000000000000..d970bb29affa Binary files /dev/null and b/sw/qa/extras/layout/data/tdf164499.docx differ diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx index af6dac583f29..5460eae5199a 100644 --- a/sw/qa/extras/layout/layout3.cxx +++ b/sw/qa/extras/layout/layout3.cxx @@ -479,12 +479,10 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf161810) auto pTextArrayAction = static_cast<MetaTextArrayAction*>(pAction); auto pDXArray = pTextArrayAction->GetDXArray(); - // There should be 73 chars on the first line - CPPUNIT_ASSERT_EQUAL(size_t(73), pDXArray.size()); + // There should be 70 chars on the first line + // (tdf#164499 no space shrinking in lines with tabulation) + CPPUNIT_ASSERT_EQUAL(size_t(70), pDXArray.size()); - // Assert we are using the expected position for the last char - // This was 9369, now 9165, according to the fixed space shrinking - CPPUNIT_ASSERT_LESS(sal_Int32(9300), sal_Int32(pDXArray[72])); break; } } @@ -535,6 +533,26 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf163149) } } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf164499) +{ + createSwDoc("tdf164499.docx"); + + // Ensure that all text portions are calculated before testing. + SwViewShell* pViewShell = getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell(); + CPPUNIT_ASSERT(pViewShell); + pViewShell->Reformat(); + + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + + // no shrinking in tabulated text lines + + // This was 1 (no line break in heading 2.5.5) + assertXPath(pXmlDoc, "/root/page[1]/body/section/txt[18]/SwParaPortion/SwLineLayout", 2); + // line break in heading 2.5.5: the second line contains only the page number + assertXPath(pXmlDoc, "/root/page[1]/body/section/txt[18]/SwParaPortion/SwLineLayout[2]", + "portion", u"*1"); +} + CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf132599_always) { uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator(); diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx index 8fd5f1c07623..d72bc719a730 100644 --- a/sw/source/core/text/portxt.cxx +++ b/sw/source/core/text/portxt.cxx @@ -333,6 +333,8 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf ) pGuess->BreakPos() != TextFrameIndex(COMPLETE_STRING) && rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get( DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING) && + // tdf#164499 no shrinking in tabulated line + ( !rInf.GetLast() || !rInf.GetLast()->InTabGrp() ) && // tdf#158436 avoid shrinking at underflow, e.g. no-break space after a // very short word resulted endless loop !rInf.IsUnderflow() ) commit c2a032ecce7d7e011df5a32afac4de6453c8adcb Author: Aron Budea <[email protected]> AuthorDate: Tue Feb 11 11:57:22 2025 +1030 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:20 2025 +0100 tdf#165181 Don't overwrite guessed media MIME type with default on load MIME types for media can be the default one, 'application/vnd.sun.star.media'. In ODFs coming from old versions, for media unsupported at the time, this default MIME type was used, and is read when opening them in new versions. MIME type is also guessed more accurately from the URI (file name and extension), but was overwritten by the saved MIME type. When using the UI, it is again overwritten by the guessed MIME type, but not when using '--convert-to'. This can cause a problem when saving ODPs to PPTX, PP will consider these files corrupted. Started happening after bc72514f90d90e1ab3fed8167663e835edf03508. Change-Id: Icd95b06d54154f3b533840f8a5f381400f2e6108 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181399 Reviewed-by: Mike Kaganski <[email protected]> Tested-by: Jenkins (cherry picked from commit cde91f936d8b569278f63205e942ea3ded5907b3) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181478 Reviewed-by: Adolfo Jayme Barrientos <[email protected]> diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx index a57dc111b0d2..9015eca50e09 100644 --- a/sd/qa/unit/export-tests.cxx +++ b/sd/qa/unit/export-tests.cxx @@ -354,8 +354,7 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testMediaEmbedding) CPPUNIT_ASSERT_MESSAGE("missing media object", pMediaObj != nullptr); CPPUNIT_ASSERT_EQUAL(u"vnd.sun.star.Package:Media/button-1.wav"_ustr, pMediaObj->getMediaProperties().getURL()); - CPPUNIT_ASSERT_EQUAL(u"application/vnd.sun.star.media"_ustr, - pMediaObj->getMediaProperties().getMimeType()); + CPPUNIT_ASSERT_EQUAL(u"audio/x-wav"_ustr, pMediaObj->getMediaProperties().getMimeType()); } CPPUNIT_TEST_FIXTURE(SdExportTest, testFillBitmapUnused) diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index f6bec74799ab..6b742be164ae 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -3097,8 +3097,20 @@ void SdXMLPluginShapeContext::endFastElement(sal_Int32 nElement) { // in case we have a media object xProps->setPropertyValue( u"MediaURL"_ustr, uno::Any(maHref)); - - xProps->setPropertyValue(u"MediaMimeType"_ustr, uno::Any(maMimeType) ); + // could be from old times when a format was unsupported + // likely already guessed a possibly more accurate MIME type from MediaURL, don't override + bool bUpdateMimeType = false; + if (maMimeType != AVMEDIA_MIMETYPE_COMMON) + bUpdateMimeType = true; + else + { + OUString aExistingMimeType; + xProps->getPropertyValue(u"MediaMimeType"_ustr) >>= aExistingMimeType; + if (aExistingMimeType.isEmpty()) + bUpdateMimeType = true; + } + if (bUpdateMimeType) + xProps->setPropertyValue(u"MediaMimeType"_ustr, uno::Any(maMimeType) ); for (const auto& rParam : maParams) { commit 5ba0b2cea67d49bbd78fb42d175df3d6c453d2c7 Author: افشین <[email protected]> AuthorDate: Sun Feb 2 05:06:59 2025 +0100 Commit: Andras Timar <[email protected]> CommitDate: Fri Feb 14 12:25:20 2025 +0100 tdf#164996 Optimize Persian (Farsi) AutoCorrect list This patch provides an optimized version of the AutoCorrect list for Persian (Farsi) language. The old version was created to resolve i#95322, eleven years ago. In the old file, there were over 6,000 words in the list, nearly 2/3 of which were unnecessary and essentially did not belong to the database. It would be better to move them to spell-checking. Change-Id: Ibe3a2e07ebecdf4a541a5cfacf6fefa8ade4e300 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181004 Tested-by: Jenkins Reviewed-by: Hossein <[email protected]> (cherry picked from commit e142387ffd70d357c0830a9f07d59e4a5b5135f5) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181358 Reviewed-by: افشین <[email protected]> Reviewed-by: Adolfo Jayme Barrientos <[email protected]> diff --git a/extras/source/autocorr/lang/fa/DocumentList.xml b/extras/source/autocorr/lang/fa/DocumentList.xml index 48f4ff372bc2..e9d2bef95746 100644 --- a/extras/source/autocorr/lang/fa/DocumentList.xml +++ b/extras/source/autocorr/lang/fa/DocumentList.xml @@ -1,6325 +1,2046 @@ <?xml version="1.0" encoding="utf-8"?> <block-list:block-list xmlns:block-list="http://openoffice.org/2001/block-list"> - <block-list:block block-list:abbreviated-name="÷س" block-list:name="پس"/> - <block-list:block block-list:abbreviated-name="آب ها" block-list:name="آبها"/> - <block-list:block block-list:abbreviated-name="آب های" block-list:name="آبهای"/> - <block-list:block block-list:abbreviated-name="آب هایی" block-list:name="آبهایی"/> - <block-list:block block-list:abbreviated-name="آبدارچی ام" block-list:name="آبدارچیام"/> - <block-list:block block-list:abbreviated-name="آبکی اند" block-list:name="آبکیاند"/> - <block-list:block block-list:abbreviated-name="آبی ها" block-list:name="آبیها"/> - <block-list:block block-list:abbreviated-name="آبی های" block-list:name="آبیهای"/> - <block-list:block block-list:abbreviated-name="آدرس ها" block-list:name="آدرسها"/> - <block-list:block block-list:abbreviated-name="آدرس های" block-list:name="آدرسهای"/> - <block-list:block block-list:abbreviated-name="آدرس هایی" block-list:name="آدرسهایی"/> - <block-list:block block-list:abbreviated-name="آدم ها" block-list:name="آدمها"/> - <block-list:block block-list:abbreviated-name="آدم های" block-list:name="آدمهای"/> - <block-list:block block-list:abbreviated-name="آدم هایش" block-list:name="آدمهایش"/> - <block-list:block block-list:abbreviated-name="آدم هایی" block-list:name="آدمهایی"/> - <block-list:block block-list:abbreviated-name="آذوقه" block-list:name="آزوقه"/> - <block-list:block block-list:abbreviated-name="آرام بخش" block-list:name="آرامبخش"/> - <block-list:block block-list:abbreviated-name="آرام تر" block-list:name="آرامتر"/> - <block-list:block block-list:abbreviated-name="آرام تری" block-list:name="آرامتری"/> - <block-list:block block-list:abbreviated-name="آرام ترین" block-list:name="آرامترین"/> - <block-list:block block-list:abbreviated-name="آرمان ها" block-list:name="آرمانها"/> - <block-list:block block-list:abbreviated-name="آرمان های" block-list:name="آرمانهای"/> - <block-list:block block-list:abbreviated-name="آرمان هایش" block-list:name="آرمانهایش"/> - <block-list:block block-list:abbreviated-name="آرمان هایی" block-list:name="آرمانهایی"/> - <block-list:block block-list:abbreviated-name="آزاده ام" block-list:name="آزادهام"/> - <block-list:block block-list:abbreviated-name="آزاده ای" block-list:name="آزادهای"/> - <block-list:block block-list:abbreviated-name="آزادی طلب" block-list:name="آزادیطلب"/> - <block-list:block block-list:abbreviated-name="آزادی ها" block-list:name="آزادیها"/> - <block-list:block block-list:abbreviated-name="آزادی های" block-list:name="آزادیهای"/> - <block-list:block block-list:abbreviated-name="آزادی هایی" block-list:name="آزادیهایی"/> - <block-list:block block-list:abbreviated-name="آزار دهنده" block-list:name="آزاردهنده"/> - <block-list:block block-list:abbreviated-name="آزردگی اش" block-list:name="آزردگیاش"/> - <block-list:block block-list:abbreviated-name="آزردگی ها" block-list:name="آزردگیها"/> - <block-list:block block-list:abbreviated-name="آزردگی های" block-list:name="آزردگیهای"/> - <block-list:block block-list:abbreviated-name="آزردگی هایی" block-list:name="آزردگیهایی"/> - <block-list:block block-list:abbreviated-name="آزرده ام" block-list:name="آزردهام"/> - <block-list:block block-list:abbreviated-name="آزرده ای" block-list:name="آزردهای"/> - <block-list:block block-list:abbreviated-name="آزرده اید" block-list:name="آزردهاید"/> - <block-list:block block-list:abbreviated-name="آزرده ایم" block-list:name="آزردهایم"/> - <block-list:block block-list:abbreviated-name="آزمایشات" block-list:name="آزمایشها"/> - <block-list:block block-list:abbreviated-name="آزمایشگاه ها" block-list:name="آزمایشگاهها"/> - <block-list:block block-list:abbreviated-name="آزمایشگاه های" block-list:name="آزمایشگاههای"/> - <block-list:block block-list:abbreviated-name="آزمایشگاه هایی" block-list:name="آزمایشگاههایی"/> - <block-list:block block-list:abbreviated-name="آسان تر" block-list:name="آسانتر"/> - <block-list:block block-list:abbreviated-name="آسان تری" block-list:name="آسانتری"/> - <block-list:block block-list:abbreviated-name="آسان ترین" block-list:name="آسانترین"/> - <block-list:block block-list:abbreviated-name="آسانتر" block-list:name="آسانتر"/> - <block-list:block block-list:abbreviated-name="آسمان ها" block-list:name="آسمانها"/> - <block-list:block block-list:abbreviated-name="آسمان های" block-list:name="آسمانهای"/> - <block-list:block block-list:abbreviated-name="آسمان هایی" block-list:name="آسمانهایی"/> - <block-list:block block-list:abbreviated-name="آسیایی ام" block-list:name="آسیاییام"/> - <block-list:block block-list:abbreviated-name="آسیب پذیر" block-list:name="آسیبپذیر"/> - <block-list:block block-list:abbreviated-name="آسیب پذیری" block-list:name="آسیبپذیری"/> - <block-list:block block-list:abbreviated-name="آسیب پذیری ها" block-list:name="آسیبپذیریها"/> - <block-list:block block-list:abbreviated-name="آسیب شناسی" block-list:name="آسیبشناسی"/> - <block-list:block block-list:abbreviated-name="آفریده ام" block-list:name="آفریدهام"/> - <block-list:block block-list:abbreviated-name="آفریده ای" block-list:name="آفریدهای"/> - <block-list:block block-list:abbreviated-name="آگاه تر" block-list:name="آگاهتر"/> - <block-list:block block-list:abbreviated-name="آگاه تری" block-list:name="آگاهتری"/> - <block-list:block block-list:abbreviated-name="آگاه ترین" block-list:name="آگاهترین"/> - <block-list:block block-list:abbreviated-name="آگاهی ات" block-list:name="آگاهیات"/> - <block-list:block block-list:abbreviated-name="آگاهی اش" block-list:name="آگاهیاش"/> - <block-list:block block-list:abbreviated-name="آگاهی ام" block-list:name="آگاهیام"/> - <block-list:block block-list:abbreviated-name="آگاهی بخش" block-list:name="آگاهیبخش"/> - <block-list:block block-list:abbreviated-name="آگاهی مان" block-list:name="آگاهیمان"/> - <block-list:block block-list:abbreviated-name="آگاهی ها" block-list:name="آگاهیها"/> - <block-list:block block-list:abbreviated-name="آگاهی های" block-list:name="آگاهیهای"/> - <block-list:block block-list:abbreviated-name="آگاهی هایم" block-list:name="آگاهیهایم"/> - <block-list:block block-list:abbreviated-name="آگاهی هایی" block-list:name="آگاهیهایی"/> - <block-list:block block-list:abbreviated-name="آلودگی ها" block-list:name="آلودگیها"/> - <block-list:block block-list:abbreviated-name="آلودگی های" block-list:name="آلودگیهای"/> - <block-list:block block-list:abbreviated-name="آلودگی هایی" block-list:name="آلودگیهایی"/> - <block-list:block block-list:abbreviated-name="آلوده اش" block-list:name="آلودهاش"/> - <block-list:block block-list:abbreviated-name="آلوده ام" block-list:name="آلودهام"/> - <block-list:block block-list:abbreviated-name="آلوده ای" block-list:name="آلودهای"/> - <block-list:block block-list:abbreviated-name="آلوده تر" block-list:name="آلودهتر"/> - <block-list:block block-list:abbreviated-name="آلوده تری" block-list:name="آلودهتری"/> - <block-list:block block-list:abbreviated-name="آلوده ترین" block-list:name="آلودهترین"/> - <block-list:block block-list:abbreviated-name="آلوده کننده" block-list:name="آلودهکننده"/> - <block-list:block block-list:abbreviated-name="آماده اش" block-list:name="آمادهاش"/> - <block-list:block block-list:abbreviated-name="آماده ام" block-list:name="آمادهام"/> - <block-list:block block-list:abbreviated-name="آماده ای" block-list:name="آمادهای"/> - <block-list:block block-list:abbreviated-name="آماده تر" block-list:name="آمادهتر"/> - <block-list:block block-list:abbreviated-name="آماده ترم" block-list:name="آمادهترم"/> - <block-list:block block-list:abbreviated-name="آماده تری" block-list:name="آمادهتری"/> - <block-list:block block-list:abbreviated-name="آماده ترین" block-list:name="آمادهترین"/> - <block-list:block block-list:abbreviated-name="آمده ام" block-list:name="آمدهام"/> - <block-list:block block-list:abbreviated-name="آمده اند" block-list:name="آمدهاند"/> - <block-list:block block-list:abbreviated-name="آمده ای" block-list:name="آمدهای"/> - <block-list:block block-list:abbreviated-name="آمده اید" block-list:name="آمدهاید"/> - <block-list:block block-list:abbreviated-name="آمده ایم" block-list:name="آمدهایم"/> - <block-list:block block-list:abbreviated-name="آموخته ام" block-list:name="آموختهام"/> - <block-list:block block-list:abbreviated-name="آموخته ای" block-list:name="آموختهای"/> - <block-list:block block-list:abbreviated-name="آموخته ایم" block-list:name="آموختهایم"/> - <block-list:block block-list:abbreviated-name="آموزش ها" block-list:name="آموزشها"/> - <block-list:block block-list:abbreviated-name="آموزش های" block-list:name="آموزشهای"/> - <block-list:block block-list:abbreviated-name="آموزش هایی" block-list:name="آموزشهایی"/> - <block-list:block block-list:abbreviated-name="آموزشگاه ها" block-list:name="آموزشگاهها"/> - <block-list:block block-list:abbreviated-name="آموزشگاه های" block-list:name="آموزشگاههای"/> - <block-list:block block-list:abbreviated-name="آموزشگاه هایی" block-list:name="آموزشگاههایی"/> - <block-list:block block-list:abbreviated-name="آموزنده ای" block-list:name="آموزندهای"/> - <block-list:block block-list:abbreviated-name="آن جا" block-list:name="آنجا"/> - <block-list:block block-list:abbreviated-name="آن جور" block-list:name="آنجور"/> - <block-list:block block-list:abbreviated-name="آن جوری" block-list:name="آنجوری"/> - <block-list:block block-list:abbreviated-name="آن چنان" block-list:name="آنچنان"/> - <block-list:block block-list:abbreviated-name="آن چه" block-list:name="آنچه"/> - <block-list:block block-list:abbreviated-name="آن شاء الله" block-list:name="انشاءالله"/> - <block-list:block block-list:abbreviated-name="آن قدر" block-list:name="آنقدر"/> - <block-list:block block-list:abbreviated-name="آن که" block-list:name="آنکه"/> - <block-list:block block-list:abbreviated-name="آن گونه" block-list:name="آنگونه"/> - <block-list:block block-list:abbreviated-name="آن ها" block-list:name="آنها"/> - <block-list:block block-list:abbreviated-name="آن هایی" block-list:name="آنهایی"/> - <block-list:block block-list:abbreviated-name="آنچنان تر" block-list:name="آنچنانتر"/> - <block-list:block block-list:abbreviated-name="آنچه" block-list:name="آنچه"/> - <block-list:block block-list:abbreviated-name="آنرا" block-list:name="آن را"/> - <block-list:block block-list:abbreviated-name="آنکه" block-list:name="آن که"/> - <block-list:block block-list:abbreviated-name="آنها" block-list:name="آنها"/> - <block-list:block block-list:abbreviated-name="آنهایی" block-list:name="آنهایی"/> - <block-list:block block-list:abbreviated-name="آواره تر" block-list:name="آوارهتر"/> - <block-list:block block-list:abbreviated-name="آواره تری" block-list:name="آوارهتری"/> - <block-list:block block-list:abbreviated-name="آواره ترید" block-list:name="آوارهترید"/> - <block-list:block block-list:abbreviated-name="آواره تریم" block-list:name="آوارهتریم"/> - <block-list:block block-list:abbreviated-name="آواره ترین" block-list:name="آوارهترین"/> - <block-list:block block-list:abbreviated-name="آورده ام" block-list:name="آوردهام"/> - <block-list:block block-list:abbreviated-name="آورده اند" block-list:name="آوردهاند"/> - <block-list:block block-list:abbreviated-name="آورده اید" block-list:name="آوردهاید"/> - <block-list:block block-list:abbreviated-name="آورده ایم" block-list:name="آوردهایم"/> - <block-list:block block-list:abbreviated-name="آهن فروش" block-list:name="آهنفروش"/> - <block-list:block block-list:abbreviated-name="آهنگ ها" block-list:name="آهنگها"/> - <block-list:block block-list:abbreviated-name="آهنگ های" block-list:name="آهنگهای"/> - <block-list:block block-list:abbreviated-name="آهنگ هایی" block-list:name="آهنگهایی"/> - <block-list:block block-list:abbreviated-name="آینده ات" block-list:name="آیندهات"/> - <block-list:block block-list:abbreviated-name="آینده اش" block-list:name="آیندهاش"/> - <block-list:block block-list:abbreviated-name="آینده ام" block-list:name="آیندهام"/> - <block-list:block block-list:abbreviated-name="آینده ای" block-list:name="آیندهای"/> - <block-list:block block-list:abbreviated-name="آینده نگر" block-list:name="آیندهنگر"/> - <block-list:block block-list:abbreviated-name="آینه اش" block-list:name="آینهاش"/> - <block-list:block block-list:abbreviated-name="آیه اش" block-list:name="آیهاش"/> - <block-list:block block-list:abbreviated-name="آیه ای" block-list:name="آیهای"/> - <block-list:block block-list:abbreviated-name="آیه ها" block-list:name="آیهها"/> - <block-list:block block-list:abbreviated-name="آیه های" block-list:name="آیههای"/> - <block-list:block block-list:abbreviated-name="آیه هایی" block-list:name="آیههایی"/> - <block-list:block block-list:abbreviated-name="آیین ها" block-list:name="آیینها"/> -e ... etc. - the rest is truncated
