From 769c82b57964c41e0febe7d2848e0925b3e13f53 Mon Sep 17 00:00:00 2001 From: nirvn Date: Thu, 3 Nov 2016 09:57:03 +0700 Subject: [PATCH] [pal] fix curved labels failure with zero-width characters (fixes 15801) --- src/core/pal/feature.cpp | 4 ++++ .../src/python/test_qgspallabeling_placement.py | 12 ++++++++++++ tests/src/python/test_qgspallabeling_tests.py | 3 ++- .../sp_label_curved_zero_width_char.png | Bin 0 -> 8497 bytes 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/testdata/control_images/expected_pal_placement/sp_label_curved_zero_width_char/sp_label_curved_zero_width_char.png diff --git a/src/core/pal/feature.cpp b/src/core/pal/feature.cpp index 266adf1cff3c..f8918c4134b1 100644 --- a/src/core/pal/feature.cpp +++ b/src/core/pal/feature.cpp @@ -1059,6 +1059,10 @@ LabelPosition* FeaturePart::curvedPlacementAtOffset( PointSet* path_positions, d // grab the next character according to the orientation LabelInfo::CharacterInfo& ci = ( orientation > 0 ? li->char_info[i] : li->char_info[li->char_num-i-1] ); + if ( qgsDoubleNear( ci.width, 0.0 ) ) + // Certain scripts rely on zero-width character, skip those to prevent failure (see #15801) + continue; + double start_x, start_y, end_x, end_y; if ( nextCharPosition( ci.width, path_distances[index], path_positions, index, distance, start_x, start_y, end_x, end_y ) == false ) { diff --git a/tests/src/python/test_qgspallabeling_placement.py b/tests/src/python/test_qgspallabeling_placement.py index 571d2b75501b..14368ba41d72 100644 --- a/tests/src/python/test_qgspallabeling_placement.py +++ b/tests/src/python/test_qgspallabeling_placement.py @@ -433,6 +433,18 @@ def test_label_line_avoid_jaggy(self): self.removeMapLayer(self.layer) self.layer = None + def test_label_curved_zero_width_char(self): + # Test that curved label work with zero-width characters + self.layer = TestQgsPalLabeling.loadFeatureLayer('line') + self._TestMapSettings = self.cloneMapSettings(self._MapSettings) + self.lyr.placement = QgsPalLayerSettings.Curved + self.lyr.placementFlags = QgsPalLayerSettings.OnLine + self.lyr.fieldName = "'invisible​space'" + self.lyr.isExpression = True + self.checkTest() + self.removeMapLayer(self.layer) + self.layer = None + if __name__ == '__main__': # NOTE: unless PAL_SUITE env var is set all test class methods will be run # SEE: test_qgspallabeling_tests.suiteTests() to define suite diff --git a/tests/src/python/test_qgspallabeling_tests.py b/tests/src/python/test_qgspallabeling_tests.py index bdad4cbdae09..f121c752e94e 100644 --- a/tests/src/python/test_qgspallabeling_tests.py +++ b/tests/src/python/test_qgspallabeling_tests.py @@ -308,8 +308,9 @@ def test_curved_placement_below(self): self.lyr.placementFlags = QgsPalLayerSettings.BelowLine | QgsPalLayerSettings.MapOrientation self.checkTest() - # noinspection PyPep8Naming + + def suiteTests(): """ Use to define which tests are run when PAL_SUITE is set. diff --git a/tests/testdata/control_images/expected_pal_placement/sp_label_curved_zero_width_char/sp_label_curved_zero_width_char.png b/tests/testdata/control_images/expected_pal_placement/sp_label_curved_zero_width_char/sp_label_curved_zero_width_char.png new file mode 100644 index 0000000000000000000000000000000000000000..555b8a814e1a2404bb8c5eda78d8b2cbf1e094bb GIT binary patch literal 8497 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 RFkm7Gu4SlMrEx#%e*m|g03iSX literal 0 HcmV?d00001