From 519432a0128901d9532b27509fbab3d985b042d1 Mon Sep 17 00:00:00 2001 From: Mathieu Pellerin Date: Wed, 22 Jan 2025 17:09:24 +0700 Subject: [PATCH] Add test case --- tests/src/core/testqgslabelingengine.cpp | 59 ++++++++++++++++++ .../expected_data_defined_tabs.png | Bin 0 -> 9355 bytes 2 files changed, 59 insertions(+) create mode 100644 tests/testdata/control_images/labelingengine/expected_data_defined_tabs/expected_data_defined_tabs.png diff --git a/tests/src/core/testqgslabelingengine.cpp b/tests/src/core/testqgslabelingengine.cpp index e6a224a2c5aa..5c629a987ca4 100644 --- a/tests/src/core/testqgslabelingengine.cpp +++ b/tests/src/core/testqgslabelingengine.cpp @@ -123,6 +123,7 @@ class TestQgsLabelingEngine : public QgsTest void parallelOverrun(); void testDataDefinedLabelAllParts(); void testDataDefinedPlacementPositionPoint(); + void testDataDefinedLabelTabs(); void testVerticalOrientation(); void testVerticalOrientationLetterLineSpacing(); void testRotationBasedOrientationPoint(); @@ -5185,6 +5186,64 @@ void TestQgsLabelingEngine::testDataDefinedPlacementPositionPoint() vl->setLabeling( nullptr ); } +void TestQgsLabelingEngine::testDataDefinedLabelTabs() +{ + // test curved label rendering with tab characters + QgsPalLayerSettings settings; + setDefaultLabelParams( settings ); + + QgsTextFormat format = settings.format(); + format.setSize( 30 ); + format.setColor( QColor( 0, 0, 0 ) ); + format.setTabStopDistance( 28 ); + format.setTabStopDistanceUnit( Qgis::RenderUnit::Millimeters ); + settings.setFormat( format ); + settings.dataDefinedProperties().setProperty( QgsPalLayerSettings::Property::TabStopDistance, QgsProperty::fromExpression( QStringLiteral( "48" ) ) ); + + settings.fieldName = QStringLiteral( "'test of\ttab\ttext'" ); + settings.isExpression = true; + settings.placement = Qgis::LabelPlacement::Horizontal; + settings.labelPerPart = false; + settings.lineSettings().setLineAnchorPercent( 0.5 ); + settings.lineSettings().setAnchorType( QgsLabelLineSettings::AnchorType::Strict ); + settings.lineSettings().setPlacementFlags( Qgis::LabelLinePlacementFlag::AboveLine | Qgis::LabelLinePlacementFlag::MapOrientation ); + settings.lineSettings().setAnchorTextPoint( QgsLabelLineSettings::AnchorTextPoint::CenterOfText ); + + std::unique_ptr vl2( new QgsVectorLayer( QStringLiteral( "LineString?crs=epsg:3946&field=id:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) ); + vl2->setRenderer( new QgsNullSymbolRenderer() ); + + QgsFeature f; + f.setAttributes( QgsAttributes() << 1 ); + f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineString (190000 5000010, 190100 5000000, 190200 5000000)" ) ) ); + QVERIFY( vl2->dataProvider()->addFeature( f ) ); + + vl2->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary! + vl2->setLabelsEnabled( true ); + + // make a fake render context + const QSize size( 640, 480 ); + QgsMapSettings mapSettings; + mapSettings.setLabelingEngineSettings( createLabelEngineSettings() ); + mapSettings.setDestinationCrs( vl2->crs() ); + + mapSettings.setOutputSize( size ); + mapSettings.setExtent( f.geometry().boundingBox() ); + mapSettings.setLayers( QList() << vl2.get() ); + mapSettings.setOutputDpi( 96 ); + + QgsLabelingEngineSettings engineSettings = mapSettings.labelingEngineSettings(); + engineSettings.setFlag( Qgis::LabelingFlag::UsePartialCandidates, false ); + engineSettings.setFlag( Qgis::LabelingFlag::DrawCandidates, true ); + mapSettings.setLabelingEngineSettings( engineSettings ); + + QgsMapRendererSequentialJob job( mapSettings ); + job.start(); + job.waitForFinished(); + + QImage img = job.renderedImage(); + QGSVERIFYIMAGECHECK( "data_defined_tabs", "data_defined_tabs", img, QString(), 20, QSize( 0, 0 ), 2 ); +} + void TestQgsLabelingEngine::testVerticalOrientation() { const QSize size( 640, 480 ); diff --git a/tests/testdata/control_images/labelingengine/expected_data_defined_tabs/expected_data_defined_tabs.png b/tests/testdata/control_images/labelingengine/expected_data_defined_tabs/expected_data_defined_tabs.png new file mode 100644 index 0000000000000000000000000000000000000000..4e20e4a98fe895fee63d54045d519bc93a4111cc GIT binary patch literal 9355 zcmeHNXIN8r+znd9QKVEEGOJWkW~m4$t5%U(1yp1UCd=XcJzBwR5!72PYd7llHJ zUi|I+H56(`ED9wwzIzwEa;lFu2@iV$ezOZkq4vK=euYT>1-DVCA5a(1pS>QQwJ;j- zL{9Klcyavz&M#C7 zUr4xg@qGHzr@}BEX?>l%i*|Oc3pKhcS5T+|%@mnP80Ubd&~DU2>HiM@t-*gd_^%B9 zZ>ZqeF;TczZ;`X$bLq|)sW+2naBcaN>8@F z6s^5GQ#Y+GNlJHR5jFc{8THQk_F$paRcmX>by~1R)im1bIibRDlwe!q=Xg$R=S!#E z&AYc^-}-`+jXdr!d0)yYp2HwXWra=tW!etUYZqefU{tamxtK7+)LpR)&+}t%sXlbGi{^1ib^Q;-6rIxYg>FVEqi(4#4twNI zDfCfm0~vQ!)V>_6O_I8;5c+Yj%~M{l`YCePw;A)d&(ucSRJWFl;V@()uo?fAATcQNVSg>sT zbzG-|-PPiebV0 zXk5F-$j~tUD#c@gT7zHPS{w1k`@H*OkDZ&FTa`lRyZiepPWI?2sh&9TW^jYM&L(zj z0U)fEsZ-OL{`9<=f`|WH%5b;25okgtgwA=Txx$D(!cY0q(h_YIio42T#nz$n&efT; zs_Hd*6k8q3S{p@=b(5o7grx=|G2Jgtb@u498;bMt^6b<821M1(*~9tOutM__Nt&fg z*r*leUuL;RjitI;tMhPf@ngy>DW~wm>qe3qH=a30bK2~ZB-INWo6hY&{Ui6i;`Wu0 zd1QylrH=KqP=lopN_CwY_LT)pqC9#GgHCs|3j;bG>{yFf=`*b`7HsxbMWz-smY1t7 zODu-D_hg+8gpwycwQ)MMPfDY>F9^yYG7GadTsK45`V|UJE^O!)=hHbclXSN#nHhvA z?A2|?oG`0{dW+3FUAvxXl|^qZd1=-}uFgv9hxx3qM)hA`e!g@nHGpe9Z+XA4*r7&) z)x>2nVY7G$VM(UA!a``>`Sh}Op_*Elg4h|(Kpv$s8lgFyiGlf zs!C^b4j@Z-i$q-0fifX>;0b+{NIBH3a)atxopaoQMJTL_pW%QR6Um@m#T&a zgH)p}<_5B?50vtcA+FS`&mbzK}~Cc(XRd!lgNn zYWW=j`ei=D|*Kj%Dm z^R}lqOgUs>(O4#ddQqIMkpOFa$_ngKt zGf#Xz>CuxVZ4@2e*QpmaKctmoSOtUDGR%sM({U+r^9mlkl2H>qqq9RAW2YBX8V*hquOTe?RvZv65(6CsEM z=(xT?Tma4WMehg4%wDv<7c-Vq&W#Sz_Nx5CO@!)vrjPbBSnfKBw6*quHg-cpbGp)w9$u!Ya$W67=XIR-FAD$KhL;q%Y0E^0-tFlpYqd$UfT%)xGb zLFl}M{rJzmdNkW?o7J8wpDF8`e<9@~KZ-Z&Jvf!&oKvrV5g}lpm*mIhXFM6ozQ~Rj zl@e6e$KNDrHtCt4`SR+Xh#hosZ7cwYBqSntWzk3z#Dm`SGgp^h!}a8oy#^R9hH7|gnjTY@-JK-=&G+JV@UsR=#J8FT zsHyOeX2{lcipuG|y^!|2#IlSs^ebNEegpK7x;dmFu0b_SX+)9jJmA==UURT+~qX zBV10TR|UEuA~&ZiTfc^R!ndgy3WNj1^wxe^=MRsZh-2&7*ozl0(x8@wiDW+z$jF~{ zxc-iEpZZ#|KjsYcW!zruLcONo&CXd1`r+i}fZSp3|YHuLtsBUF1Nb zS!4yg+Y>l`SL8yPf}smYtpvlhA=k_(&c;$5vB~Sh!^341r>H4&HW+}cppPdqqX)Te zL;;`8$Q5kn)`Ta&d7`&Jv}{J_zfN)R}kv{{P{C& z${)b}44eh;i$zQ!*)~(#^Lyg{%ZAT`cu(%@|f6J;LnEPihKI-r%7g8B}=m z(tkvWd@KDOaG!ekwE+vG%^#0le)hJ*yaRMyf)Qrxe6A5D&ws25X@Vu&FCU`m5z1)$ z&^4|3ew>9Lswc;=p3L}t5G43Ssy-_o>2l0qOZiLbYHtREtPI)N`sh>;TapG<7g}d} z>rs~-(%np)i$Fyy0MIoEsSOwrRaI36DDFwCA zK2@eqB&a!#gpfBun}|7b1f4;p;qpY?mL@v_XW!r?4GE3MmiChieh}3Ms&gJ4_?ilT8HYAHpWJ`sIsDm5n_9ENn<#V^LDjDY&`7cG3Dc>Z+;al z(gWU$B5iHZ3!`dNnvCcI7&?*j`IbYb3w1ejjOYHeQ%b+B2P{#N)3rpw7~%=0-lWW4 zst;Qz%)$*VZ+9r?4on3M?ZRZ^`^E1&7wtO@G*(E%hc(9vIfPUiPrY-?BG2Y;E5}|deVK+OSB^%egbC7M?o^swk3eK>UAnl&*HA)C&+1yu*;RQbJ zj0rsRQnoDd$>3t^WSD1ZD>mNvnp+bCZ#`}@Wq*QrE>j8^okXC^VUu3U`D?CWh z11DZ*`l*D!c(FQ1AtBQlZ@znqK%Di<7@37LSXHjhphi_PG{X*h0h4$cmM)wP&8>G4 zLJwRuopO3}EN|niLDlMP5xyN5GDDxApJt@8^;&s#1`}nIJvR5~(IY5d(}vCIOkrFM zmpYdE_qhk;)lWK++nX~C*y*A*Uhqs$%07+S9~2^)f2(8rw?c{TmikST{x{p!+6q|a z;3ma-vULI{TJPar7yJ%drNrX7IA^m(0Z|S`_@*-mhNgQm)}MMg`eclpfsPi8L!{kw z*Yn5v7+`M>OnuVa7;ssA$A@~45Y9?;ygyZB^W#SOQ&pRGkQ&!YxCIFUUavrnuv4(X zVFU|$WKMZa-ubxDOyS!*&VQfT77aGcie=Fl@b5c4M)JuZ^p_59I`iKLim8xt;O!ZA zK2UtTOi?;-U7SVDvh>RA*;!58QTDWxy9Y3XmV4JTuQU(-)+z_QSt|%+=Kw(im>WbK zrkMNGzu&Jv5N`i<0{{MTAjo1`jYBP1}T=h|zVjw~Jq23*z&uwnpRPH+bI+4xYwX zIr=EhX5eFGZF_SJg9S`Bbp2;qt{3JZz_@B}PvE$2Ai$HbxltC_1Ve8txSBuFF6*yW zn}dj;>7H!aeABd4LuhCfUpmv(lc0sRwI&>3Kw?0x6;R{Fm2@)EQy-sdc?}fQP9&;M zY%tQ&05$C(%k!Xj2osNmFH}(`pbR=Nya?rV76R0t(+rk=Yv8oY1~v?=2)c8BE z6t&Ebgi;(CwBX(p5P1R>Jq$vk8~;A|sys#HL#}B1(e&uyj1+0Z$PiXltkMzeVw~bZ z!-SQ!yrJM4a9>FMBOU}UNbHb}1vRYQv|8eCa^8pMe;8D#4=rLQTPtYtLyDqzUjas^OEH;H_O} z2i|aCok$SHIF>ALj)wG`aq7qTrQ?LwrE0h2Sv%DYV#v}=WtGnI&E**n`7)5q3A)W^Ys_@o)G6>xO6ma6cbot+i!DY8=8G3%q~-ao%R^axl@(;En&isd@_ z;jcPI>8yQo)#hm+_uv@Pa5V%!>Zh>V7LW^elb1oV-!6e2B;0s>%&Z*9+nppAd^rqM zo5ur%$UD_@rS;Q2#t09&VmGHUf(5D2)Ux?}cFdTbKhTm+2=fz-yU}5Ry%xfS?JsSo z&VVlpQy<@T%{tv}$6E!7z0IPsI=3PI@krUevsd_Ly4x_6Pv+C~bn>vV)2ThpBRm8* zXa@)hJnRs{t!yHE+pN}E4${y@U#&1wD+Y)&iB4HN7;BgAhM2gNn*NNPKXsPRlZ>|m zOR862o{bB_QFKsH5FcdH+(4al(P7!~QI?h#NY1eU#eQl_{`l7m03v%p>0k4}|8svw zK*yt_CixtoG`i1opeCOT$FL5^X(-IjQ6mWn2|FlPZ*4!Jp#aEbx{P8)ivt<$9O!S9 zjyG43Oa^$MT_=$BT9MB*4Fs1mY3>iGGg$d_PL#kNfM`KZvvK8GA6}{GGj!~5n2C4v ztL17IXp;oMsaFy?aJgHT1R0b~z8j(g)SJeBRe%PsHxaK?Xcz<0F$02vz!i4bB%)1d z5blNs-J3*=`aaEu?~rsV}DR!%*sCGi%hIg7t7P{c)0-tO-oh~dfg?;7CwTQGz3U_ZLU#xUzL#K&st>fIm# z{u+f(4ujZk7$zXF183aO&i;eA0jb=jFadwvXf%|+ zXIv^>!|?@w-ov;P;N!SJ8isgn9%sz=w03fGD&Y>%jfA?&)wnDD78QUvjX5w#Rn@~b z#_(#dz#XvwDj5r)=yW2MCIJ{ekP_7`53U_(Hc66n1252lRD1EOSFf11U|x~Hi| z)h<3^`TF)wk^RMFb_iWL*14dd;6rJ{(#K*D(xK)C%7kA3ZlWJ8J~xHDd|`agblP z@-~-~u!Tst9S(cSfCWmP>dYW*t`B4K;W>O9yXB+7=H1rYh!f~#)voPiLwU49(sTmHbY%kl7317a5` zq_2X9xqx?SoOohsp78Jc2c{5ZC;AgZc7}#yUer3P4;D|_AUt4YcCcvtE*c5*q01W9 zWn>wE;?0Nn+k^z)_@WkgKe)Gg5i(_6*azznd1P#$Sq5R7KY7BMo1QFB*AcYKGsRu;~25gI~aw=8FbzCrz#ih@J(|8}@sDsJ%@h5AMd z`CouR58gjL+Fk?4;f~iq0Es8_Z@7o$&=g&F0H^z%kZl@t6IUXCO*LF%AL=(V7?~?j zo+tCxj~7wolSC%!mva?jKcIeb`R2dFe{1j`4*p-2!HZ;h>Zfxk)XS!1d0CD?sOEZo Wa0>2iCj8e9>Y|DH`O;r+-uoXS4&0#t literal 0 HcmV?d00001