officecfg/registry/schema/org/openoffice/Office/Writer.xcs    |    8 
 officecfg/registry/schema/org/openoffice/Office/WriterWeb.xcs |    8 
 sw/inc/viewopt.hxx                                            |   15 +
 sw/source/core/txtnode/fntcache.cxx                           |  113 +++++++---
 sw/source/ui/config/optpage.cxx                               |    3 
 sw/source/uibase/config/cfgitems.cxx                          |    6 
 sw/source/uibase/config/usrpref.cxx                           |   71 +++---
 sw/source/uibase/config/viewopt.cxx                           |    3 
 sw/source/uibase/inc/cfgitems.hxx                             |    3 
 sw/source/uibase/inc/optpage.hxx                              |    1 
 sw/uiconfig/swriter/ui/viewoptionspage.ui                     |   70 ++++--
 11 files changed, 211 insertions(+), 90 deletions(-)

New commits:
commit 39a57fa8c047227060915534e64c4e90affa4b1a
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Tue Dec 21 14:15:59 2021 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Wed Dec 22 10:12:01 2021 +0100

    tdf#144862 explore alternatives to writer's on-screen glyph positioning
    
    writer does glyph position adjusting to try and split the difference of
    the "printing" positions and "screen" positions.
    
    it seems to have been there from the initial import
    
    commit 84a3db80b4fd66c6854b3135b5f69b61fd828e62
    Date:   Mon Sep 18 23:08:29 2000 +0000
    
        initial import
    
    we seem to sync with the printing positions after each whitespace so
    each initial glyph after whitespace is a stable position and is the
    'printing' position while each following glyph is in a position which is
    somewhere between the 'printing' position and 'screen' position. Which
    leads to noticeably unstable positions of text during editing at various
    zoom levels and without a clear rationale for the heuristic.
    
    GlyphPositioningMode::Classic, the original mode which remains the
    default.
    
    GlyphPositioningMode::PreferLayout, takes the vcl provided print
    positions and just uses those unmodified for screen layout like editeng
    does.
    
    GlyphPositioningMode::ClassicInspired, which is similar to
    GlyphPositioningMode::Classic in using 'printing' positions for the
    start of runs, but using 'screen' positions for run content.
    
    GlyphPositioningMode::PreferReadability, replace the 'printing'
    positions with the screen-optimized positions for all content.
    
    use tools, options, writer, view, glyph positioning to change
    
    Change-Id: I6677af973268bc586d825c7fbf0b483aaf651ca0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127089
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs 
b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
index 1fe57e99cd72..af944c23c03f 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
@@ -1459,6 +1459,14 @@
           </info>
           <value>false</value>
         </prop>
+        <prop oor:name="GlyphPositioningMode" oor:type="xs:int" 
oor:nillable="false">
+          <!-- UIHints: Tools - Option - Text document - Layout - [Section] 
Window -->
+          <info>
+            <desc>Specifies the Glyph Positioning Mode.</desc>
+            <label>Glyph Positioning Mode</label>
+          </info>
+          <value>0</value>
+        </prop>
       </group>
       <group oor:name="Other">
         <info>
diff --git a/officecfg/registry/schema/org/openoffice/Office/WriterWeb.xcs 
b/officecfg/registry/schema/org/openoffice/Office/WriterWeb.xcs
index 8d633caae4f0..12ffb09a2755 100644
--- a/officecfg/registry/schema/org/openoffice/Office/WriterWeb.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/WriterWeb.xcs
@@ -340,6 +340,14 @@
           </info>
           <value>false</value>
         </prop>
+        <prop oor:name="GlyphPositioningMode" oor:type="xs:int" 
oor:nillable="false">
+          <!-- UIHints: Tools - Option - HTML-Document - Layout - [Section] 
Window -->
+          <info>
+            <desc>Specifies the Glyph Positioning Mode.</desc>
+            <label>Glyph Positioning Mode</label>
+          </info>
+          <value>0</value>
+        </prop>
       </group>
       <group oor:name="Other">
         <info>
diff --git a/sw/inc/viewopt.hxx b/sw/inc/viewopt.hxx
index e8a1c299b496..6c93602a85ae 100644
--- a/sw/inc/viewopt.hxx
+++ b/sw/inc/viewopt.hxx
@@ -126,6 +126,13 @@ namespace o3tl {
     template<> struct typed_flags<ViewOptFlags> : is_typed_flags<ViewOptFlags, 
0x01ff> {};
 }
 
+enum class GlyphPositioningMode {
+    Classic,
+    ClassicInspired,
+    PreferLayout,
+    PreferReadability
+};
+
 class SW_DLLPUBLIC SwViewOption
 {
     static Color    s_aDocColor;  // color of document boundaries
@@ -163,6 +170,7 @@ class SW_DLLPUBLIC SwViewOption
     sal_uInt8       m_nPagePreviewRow;       // Page Preview Row/Columns.
     sal_uInt8       m_nPagePreviewCol;       // Page Preview Row/Columns.
     SwFillMode      m_nShadowCursorFillMode;  // FillMode for ShadowCursor.
+    GlyphPositioningMode m_eGlyphPositioningMode; // Positioning strategy for 
screen glyphs
     bool            m_bReadonly : 1;      // Readonly-Doc.
     bool            m_bStarOneSetting : 1;// Prevent from UI automatics (no 
scrollbars in readonly documents).
     bool            m_bIsPagePreview : 1; // The preview mustn't print 
field/footnote/... shadings.
@@ -426,6 +434,12 @@ public:
     void SetPrinting(bool b)
         { SetCore2Option(b, ViewOptCoreFlags2::Printing); }
 
+    GlyphPositioningMode GetGlyphPositioningMode() const
+        { return m_eGlyphPositioningMode; }
+
+    void SetGlyphPositioningMode(GlyphPositioningMode eMode)
+        { m_eGlyphPositioningMode = eMode; }
+
     void SetCore2Option(bool b, ViewOptCoreFlags2 f)
     {
         if (b)
@@ -697,6 +711,7 @@ inline void SwViewOption::SetUIOptions( const SwViewOption& 
rVOpt )
     m_nUIOptions = rVOpt.m_nUIOptions;
     m_nTableDestination = rVOpt.m_nTableDestination;
     m_nShadowCursorFillMode = rVOpt.m_nShadowCursorFillMode;
+    m_eGlyphPositioningMode = rVOpt.m_eGlyphPositioningMode;
 }
 
 // Helper function for checking HTML-capabilities.
diff --git a/sw/source/core/txtnode/fntcache.cxx 
b/sw/source/core/txtnode/fntcache.cxx
index e02b3aa52602..df213b9553e9 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -857,26 +857,64 @@ static void lcl_DrawLineForWrongListData(
 
 namespace
 {
-    void AdjustKernArray(sal_Int32 i, tools::Long& rScrPos, sal_Unicode 
cChPrev, sal_Unicode nCh,
+    void AdjustKernArray(GlyphPositioningMode eGlyphPositioningMode, sal_Int32 
i, tools::Long& rScrPos,
+                         sal_Unicode cChPrev, sal_Unicode nCh,
                          const std::vector<sal_Int32>& rScrArray, 
std::vector<sal_Int32>& rKernArray,
                          int nMul)
     {
         tools::Long nScr = rScrArray[i] - rScrArray[i - 1];
-        if (nCh == CH_BLANK)
-            rScrPos = rKernArray[i - 1] + nScr;
-        else
+        switch (eGlyphPositioningMode)
         {
-            if (cChPrev == CH_BLANK || cChPrev == '-')
+            case GlyphPositioningMode::PreferLayout:
                 rScrPos = rKernArray[i - 1] + nScr;
-            else
+                // just accept the print layout positions, this is what 
editeng does
+                break;
+            case GlyphPositioningMode::PreferReadability:
             {
+                // Overwrite KernArray with the screen-optimized glyph 
positions
+                rKernArray[i - 1] = rScrPos;
                 rScrPos += nScr;
+                break;
+            }
+            case GlyphPositioningMode::Classic:
+            {
+                if (nCh == CH_BLANK)
+                    rScrPos = rKernArray[i - 1] + nScr;
+                else
+                {
+                    if (cChPrev == CH_BLANK || cChPrev == '-')
+                        rScrPos = rKernArray[i - 1] + nScr;
+                    else
+                    {
+                        rScrPos += nScr;
 
-                const int nDiv = nMul+1;
-                rScrPos = (nMul * rScrPos + rKernArray[i]) / nDiv;
+                        const int nDiv = nMul+1;
+                        rScrPos = (nMul * rScrPos + rKernArray[i]) / nDiv;
+                    }
+                }
+                rKernArray[i - 1] = rScrPos - nScr;
+                break;
+            }
+            case GlyphPositioningMode::ClassicInspired:
+            {
+                // use the print layout positions for blanks and the first 
glyph after a blank or -
+                // and use screen layout within a run of glyphs
+                const bool bSyncWithPrintLayout = nCh == CH_BLANK || cChPrev 
== CH_BLANK || cChPrev == '-';
+                if (bSyncWithPrintLayout)
+                {
+                    // Leave KernArray untouched at its print layout position 
in this case
+                    // sync ScreenPos to print layout position
+                    rScrPos = rKernArray[i - 1] + nScr;
+                }
+                else
+                {
+                    // Overwrite KernArray within the run to use 
screen-optimized glyph positions
+                    rKernArray[i - 1] = rScrPos;
+                    rScrPos += nScr;
+                }
+                break;
             }
         }
-        rKernArray[i - 1] = rScrPos - nScr;
     }
 }
 
@@ -1689,6 +1727,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
         }
         else
         {
+            GlyphPositioningMode eGlyphPositioningMode = 
rInf.GetShell()->GetViewOptions()->GetGlyphPositioningMode();
+
             // In case of Pair Kerning the printer influence on the positioning
             // grows
             const int nMul = m_pPrtFont->GetKerning() != FontKerning::NONE ? 1 
: 3;
@@ -1712,7 +1752,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
             for (sal_Int32 i = 1; i < sal_Int32(nCnt); ++i, nKernSum += 
rInf.GetKern())
             {
                 sal_Unicode nCh = rInf.GetText()[sal_Int32(rInf.GetIdx()) + i];
-                AdjustKernArray(i, nScrPos, cChPrev, nCh, aScrArray, 
aKernArray, nMul);
+                AdjustKernArray(eGlyphPositioningMode, i, nScrPos, cChPrev, 
nCh, aScrArray, aKernArray, nMul);
 
                 // Apply SpaceSum
                 if (cChPrev == CH_BLANK)
@@ -2012,7 +2052,6 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
         CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
         if( !GetScrFont()->IsSameInstance( rInf.GetOut().GetFont() ) )
             rInf.GetOut().SetFont( *m_pScrFont );
-        tools::Long nScrPos;
 
         m_pPrinter->GetTextArray(rInf.GetText(), &aKernArray,
                 sal_Int32(rInf.GetIdx()), sal_Int32(nLn));
@@ -2024,34 +2063,44 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
             rInf.SetKanaDiff( 0 );
 
         if ( rInf.GetKanaDiff() )
-            nScrPos = aKernArray[ sal_Int32(nLn) - 1 ];
+        {
+            aTextSize.setWidth(aKernArray[sal_Int32(nLn) - 1]);
+        }
         else
         {
-            std::vector<sal_Int32> aScrArray;
-            rInf.GetOut().GetTextArray( rInf.GetText(), &aScrArray,
-                        sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
-            nScrPos = aScrArray[ 0 ];
-            TextFrameIndex nCnt(rInf.GetText().getLength());
-            if ( nCnt < rInf.GetIdx() )
-                nCnt = TextFrameIndex(0); // assert???
+            GlyphPositioningMode eGlyphPositioningMode = 
rInf.GetShell()->GetViewOptions()->GetGlyphPositioningMode();
+            if (eGlyphPositioningMode == GlyphPositioningMode::PreferLayout)
+            {
+                aTextSize.setWidth(aKernArray[sal_Int32(nLn) - 1]);
+            }
             else
-                nCnt = nCnt - rInf.GetIdx();
-            nCnt = std::min(nCnt, nLn);
-            sal_Unicode nChPrev = rInf.GetText()[ sal_Int32(rInf.GetIdx()) ];
+            {
+                std::vector<sal_Int32> aScrArray;
+                rInf.GetOut().GetTextArray( rInf.GetText(), &aScrArray,
+                            sal_Int32(rInf.GetIdx()), 
sal_Int32(rInf.GetLen()));
+                tools::Long nScrPos = aScrArray[ 0 ];
+                TextFrameIndex nCnt(rInf.GetText().getLength());
+                if ( nCnt < rInf.GetIdx() )
+                    nCnt = TextFrameIndex(0); // assert???
+                else
+                    nCnt = nCnt - rInf.GetIdx();
+                nCnt = std::min(nCnt, nLn);
+                sal_Unicode nChPrev = rInf.GetText()[ sal_Int32(rInf.GetIdx()) 
];
 
-            // In case of Pair Kerning the printer influence on the positioning
-            // grows
-            const int nMul = m_pPrtFont->GetKerning() != FontKerning::NONE ? 1 
: 3;
+                // In case of Pair Kerning the printer influence on the 
positioning
+                // grows
+                const int nMul = m_pPrtFont->GetKerning() != FontKerning::NONE 
? 1 : 3;
 
-            for (sal_Int32 i = 1; i < sal_Int32(nCnt); i++)
-            {
-                sal_Unicode nCh = rInf.GetText()[sal_Int32(rInf.GetIdx()) + i];
-                AdjustKernArray(i, nScrPos, nChPrev, nCh, aScrArray, 
aKernArray, nMul);
-                nChPrev = nCh;
+                for (sal_Int32 i = 1; i < sal_Int32(nCnt); i++)
+                {
+                    sal_Unicode nCh = rInf.GetText()[sal_Int32(rInf.GetIdx()) 
+ i];
+                    AdjustKernArray(eGlyphPositioningMode, i, nScrPos, 
nChPrev, nCh, aScrArray, aKernArray, nMul);
+                    nChPrev = nCh;
+                }
+
+                aTextSize.setWidth( nScrPos );
             }
         }
-
-        aTextSize.setWidth( nScrPos );
     }
     else
     {
diff --git a/sw/source/ui/config/optpage.cxx b/sw/source/ui/config/optpage.cxx
index 30a3c4cac6e4..6cfe9b99d1c6 100644
--- a/sw/source/ui/config/optpage.cxx
+++ b/sw/source/ui/config/optpage.cxx
@@ -91,6 +91,7 @@ SwContentOptPage::SwContentOptPage(weld::Container* pPage, 
weld::DialogControlle
     , m_xVRulerRightCBox(m_xBuilder->weld_check_button("vrulerright"))
     , m_xVMetric(m_xBuilder->weld_combo_box("vrulercombobox"))
     , m_xSmoothCBox(m_xBuilder->weld_check_button("smoothscroll"))
+    , m_xGlyphPosModeLB(m_xBuilder->weld_combo_box("glyphposmode"))
     , m_xGrfCB(m_xBuilder->weld_check_button("graphics"))
     , m_xTableCB(m_xBuilder->weld_check_button("tables"))
     , m_xDrwCB(m_xBuilder->weld_check_button("drawings"))
@@ -219,6 +220,7 @@ void SwContentOptPage::Reset(const SfxItemSet* rSet)
         m_xShowChangesInMargin->set_active(pElemAttr->m_bShowChangesInMargin);
         m_xFieldHiddenCB->set_active( pElemAttr->m_bFieldHiddenText );
         m_xFieldHiddenParaCB->set_active( pElemAttr->m_bShowHiddenPara );
+        
m_xGlyphPosModeLB->set_active(static_cast<int>(pElemAttr->m_eGlyphPositioningMode));
     }
     m_xMetricLB->set_active(-1);
     lcl_SelectMetricLB(*m_xMetricLB, SID_ATTR_METRIC, *rSet);
@@ -246,6 +248,7 @@ bool SwContentOptPage::FillItemSet(SfxItemSet* rSet)
     aElem.m_bShowChangesInMargin  = m_xShowChangesInMargin->get_active();
     aElem.m_bFieldHiddenText      = m_xFieldHiddenCB->get_active();
     aElem.m_bShowHiddenPara       = m_xFieldHiddenParaCB->get_active();
+    aElem.m_eGlyphPositioningMode = 
static_cast<GlyphPositioningMode>(m_xGlyphPosModeLB->get_active());
 
     bool bRet = !pOldAttr || aElem != *pOldAttr;
     if(bRet)
diff --git a/sw/source/uibase/config/cfgitems.cxx 
b/sw/source/uibase/config/cfgitems.cxx
index e32c86e14c52..39f4d43d63bf 100644
--- a/sw/source/uibase/config/cfgitems.cxx
+++ b/sw/source/uibase/config/cfgitems.cxx
@@ -104,6 +104,7 @@ SwElemItem::SwElemItem() :
     m_bShowChangesInMargin =
     m_bFieldHiddenText =
     m_bShowHiddenPara  = false;
+    m_eGlyphPositioningMode = GlyphPositioningMode::Classic;
 }
 
 SwElemItem::SwElemItem(const SwViewOption& rVOpt) :
@@ -123,6 +124,7 @@ SwElemItem::SwElemItem(const SwViewOption& rVOpt) :
     m_bShowChangesInMargin = rVOpt.IsShowChangesInMargin();
     m_bFieldHiddenText = rVOpt.IsShowHiddenField();
     m_bShowHiddenPara  = rVOpt.IsShowHiddenPara();
+    m_eGlyphPositioningMode = rVOpt.GetGlyphPositioningMode();
 }
 
 SwElemItem* SwElemItem::Clone( SfxItemPool* ) const
@@ -149,7 +151,8 @@ bool SwElemItem::operator==( const SfxPoolItem& rAttr ) 
const
                 m_bTreatSubOutlineLevelsAsContent == 
rItem.m_bTreatSubOutlineLevelsAsContent &&
                 m_bShowChangesInMargin  == rItem.m_bShowChangesInMargin &&
                 m_bFieldHiddenText == rItem.m_bFieldHiddenText &&
-                m_bShowHiddenPara  == rItem.m_bShowHiddenPara);
+                m_bShowHiddenPara  == rItem.m_bShowHiddenPara &&
+                m_eGlyphPositioningMode == rItem.m_eGlyphPositioningMode);
 }
 
 void SwElemItem::FillViewOptions( SwViewOption& rVOpt) const
@@ -169,6 +172,7 @@ void SwElemItem::FillViewOptions( SwViewOption& rVOpt) const
     rVOpt.SetShowChangesInMargin( m_bShowChangesInMargin );
     rVOpt.SetShowHiddenField(m_bFieldHiddenText );
     rVOpt.SetShowHiddenPara(m_bShowHiddenPara );
+    rVOpt.SetGlyphPositioningMode(m_eGlyphPositioningMode);
 }
 
 // CTOR for empty Item
diff --git a/sw/source/uibase/config/usrpref.cxx 
b/sw/source/uibase/config/usrpref.cxx
index 0c759a78cf94..e0949660471d 100644
--- a/sw/source/uibase/config/usrpref.cxx
+++ b/sw/source/uibase/config/usrpref.cxx
@@ -259,20 +259,21 @@ Sequence<OUString> SwLayoutViewConfig::GetPropertyNames() 
const
         "Window/HorizontalRulerUnit",           // 6
         "Window/VerticalRulerUnit",             // 7
         "Window/SmoothScroll",                  // 8
-        "Zoom/Value",                           // 9
-        "Zoom/Type",                            //10
-        "Other/IsAlignMathObjectsToBaseline",   //11
-        "Other/MeasureUnit",                    //12
+        "Window/GlyphPositioningMode",          // 9
+        "Zoom/Value",                           //10
+        "Zoom/Type",                            //11
+        "Other/IsAlignMathObjectsToBaseline",   //12
+        "Other/MeasureUnit",                    //13
         // below properties are not available in WriterWeb
-        "Other/TabStop",                        //13
-        "Window/IsVerticalRulerRight",          //14
-        "ViewLayout/Columns",                   //15
-        "ViewLayout/BookMode",                  //16
-        "Other/IsSquaredPageMode",              //17
-        "Other/ApplyCharUnit",                  //18
-        "Window/ShowScrollBarTips"              //19
+        "Other/TabStop",                        //14
+        "Window/IsVerticalRulerRight",          //15
+        "ViewLayout/Columns",                   //16
+        "ViewLayout/BookMode",                  //17
+        "Other/IsSquaredPageMode",              //18
+        "Other/ApplyCharUnit",                  //19
+        "Window/ShowScrollBarTips"              //20
     };
-    const int nCount = m_bWeb ? 13 : 20;
+    const int nCount = m_bWeb ? 14 : 21;
     Sequence<OUString> aNames(nCount);
     OUString* pNames = aNames.getArray();
     for(int i = 0; i < nCount; i++)
@@ -323,17 +324,18 @@ void SwLayoutViewConfig::ImplCommit()
                     rVal <<= 
static_cast<sal_Int32>(m_rParent.m_eVScrollMetric);                     // 
"Window/VerticalRulerUnit"
             break;
             case  8: rVal <<= m_rParent.IsSmoothScroll(); break;               
       // "Window/SmoothScroll",
-            case  9: rVal <<= static_cast<sal_Int32>(m_rParent.GetZoom()); 
break;                  // "Zoom/Value",
-            case 10: rVal <<= static_cast<sal_Int32>(m_rParent.GetZoomType()); 
break;              // "Zoom/Type",
-            case 11: rVal <<= m_rParent.IsAlignMathObjectsToBaseline(); break; 
       // "Other/IsAlignMathObjectsToBaseline"
-            case 12: rVal <<= static_cast<sal_Int32>(m_rParent.GetMetric()); 
break;                // "Other/MeasureUnit",
-            case 13: rVal <<= m_rParent.GetDefTabInMm100(); break;// 
"Other/TabStop",
-            case 14: rVal <<= m_rParent.IsVRulerRight(); break;                
       // "Window/IsVerticalRulerRight",
-            case 15: rVal <<= 
static_cast<sal_Int32>(m_rParent.GetViewLayoutColumns()); break;     // 
"ViewLayout/Columns",
-            case 16: rVal <<= m_rParent.IsViewLayoutBookMode(); break;         
       // "ViewLayout/BookMode",
-            case 17: rVal <<= m_rParent.IsSquaredPageMode(); break;            
       // "Other/IsSquaredPageMode",
-            case 18: rVal <<= m_rParent.IsApplyCharUnit(); break;              
       // "Other/ApplyCharUnit",
-            case 19: rVal <<= m_rParent.IsShowScrollBarTips(); break;          
       // "Window/ShowScrollBarTips",
+            case  9: rVal <<= 
static_cast<sal_Int32>(m_rParent.GetGlyphPositioningMode()); break;  // 
"Window/GlyphPositioningMode",
+            case 10: rVal <<= static_cast<sal_Int32>(m_rParent.GetZoom()); 
break;                  // "Zoom/Value",
+            case 11: rVal <<= static_cast<sal_Int32>(m_rParent.GetZoomType()); 
break;              // "Zoom/Type",
+            case 12: rVal <<= m_rParent.IsAlignMathObjectsToBaseline(); break; 
       // "Other/IsAlignMathObjectsToBaseline"
+            case 13: rVal <<= static_cast<sal_Int32>(m_rParent.GetMetric()); 
break;                // "Other/MeasureUnit",
+            case 14: rVal <<= m_rParent.GetDefTabInMm100(); break;// 
"Other/TabStop",
+            case 15: rVal <<= m_rParent.IsVRulerRight(); break;                
       // "Window/IsVerticalRulerRight",
+            case 16: rVal <<= 
static_cast<sal_Int32>(m_rParent.GetViewLayoutColumns()); break;     // 
"ViewLayout/Columns",
+            case 17: rVal <<= m_rParent.IsViewLayoutBookMode(); break;         
       // "ViewLayout/BookMode",
+            case 18: rVal <<= m_rParent.IsSquaredPageMode(); break;            
       // "Other/IsSquaredPageMode",
+            case 19: rVal <<= m_rParent.IsApplyCharUnit(); break;              
       // "Other/ApplyCharUnit",
+            case 20: rVal <<= m_rParent.IsShowScrollBarTips(); break;          
       // "Window/ShowScrollBarTips",
         }
     }
     PutProperties(aNames, aValues);
@@ -378,17 +380,18 @@ void SwLayoutViewConfig::Load()
                 }
                 break;
                 case  8: m_rParent.SetSmoothScroll(bSet); break;// 
"Window/SmoothScroll",
-                case  9: m_rParent.SetZoom( static_cast< sal_uInt16 
>(nInt32Val) ); break;// "Zoom/Value",
-                case 10: m_rParent.SetZoomType( static_cast< SvxZoomType 
>(nInt32Val) ); break;// "Zoom/Type",
-                case 11: m_rParent.SetAlignMathObjectsToBaseline(bSet, true); 
break;// "Other/IsAlignMathObjectsToBaseline"
-                case 12: 
m_rParent.SetMetric(static_cast<FieldUnit>(nInt32Val), true); break;// 
"Other/MeasureUnit",
-                case 13: m_rParent.SetDefTabInMm100(nInt32Val, true); break;// 
"Other/TabStop",
-                case 14: m_rParent.SetVRulerRight(bSet); break;// 
"Window/IsVerticalRulerRight",
-                case 15: m_rParent.SetViewLayoutColumns( 
o3tl::narrowing<sal_uInt16>(nInt32Val) ); break;// "ViewLayout/Columns",
-                case 16: m_rParent.SetViewLayoutBookMode(bSet); break;// 
"ViewLayout/BookMode",
-                case 17: m_rParent.SetDefaultPageMode(bSet,true); break;// 
"Other/IsSquaredPageMode",
-                case 18: m_rParent.SetApplyCharUnit(bSet, true); break;// 
"Other/ApplyUserChar"
-                case 19: m_rParent.SetShowScrollBarTips(bSet); break;// 
"Window/ShowScrollBarTips",
+                case  9: 
m_rParent.SetGlyphPositioningMode(static_cast<GlyphPositioningMode>(nInt32Val));
 break;// "Window/GlyphPositioningMode",
+                case 10: m_rParent.SetZoom( static_cast< sal_uInt16 
>(nInt32Val) ); break;// "Zoom/Value",
+                case 11: m_rParent.SetZoomType( static_cast< SvxZoomType 
>(nInt32Val) ); break;// "Zoom/Type",
+                case 12: m_rParent.SetAlignMathObjectsToBaseline(bSet, true); 
break;// "Other/IsAlignMathObjectsToBaseline"
+                case 13: 
m_rParent.SetMetric(static_cast<FieldUnit>(nInt32Val), true); break;// 
"Other/MeasureUnit",
+                case 14: m_rParent.SetDefTabInMm100(nInt32Val, true); break;// 
"Other/TabStop",
+                case 15: m_rParent.SetVRulerRight(bSet); break;// 
"Window/IsVerticalRulerRight",
+                case 16: m_rParent.SetViewLayoutColumns( 
o3tl::narrowing<sal_uInt16>(nInt32Val) ); break;// "ViewLayout/Columns",
+                case 17: m_rParent.SetViewLayoutBookMode(bSet); break;// 
"ViewLayout/BookMode",
+                case 18: m_rParent.SetDefaultPageMode(bSet,true); break;// 
"Other/IsSquaredPageMode",
+                case 19: m_rParent.SetApplyCharUnit(bSet, true); break;// 
"Other/ApplyUserChar"
+                case 20: m_rParent.SetShowScrollBarTips(bSet); break;// 
"Window/ShowScrollBarTips",
             }
         }
     }
diff --git a/sw/source/uibase/config/viewopt.cxx 
b/sw/source/uibase/config/viewopt.cxx
index 66ea4daa05f4..12a7336f62ad 100644
--- a/sw/source/uibase/config/viewopt.cxx
+++ b/sw/source/uibase/config/viewopt.cxx
@@ -166,6 +166,7 @@ SwViewOption::SwViewOption() :
     m_nPagePreviewRow( 1 ),
     m_nPagePreviewCol( 2 ),
     m_nShadowCursorFillMode( SwFillMode::Tab ),
+    m_eGlyphPositioningMode( GlyphPositioningMode::Classic ),
     m_bReadonly(false),
     m_bStarOneSetting(false),
     m_bIsPagePreview(false),
@@ -253,6 +254,7 @@ SwViewOption::SwViewOption(const SwViewOption& rVOpt)
     m_aRetouchColor  = rVOpt.GetRetoucheColor();
     m_sSymbolFont     = rVOpt.m_sSymbolFont;
     m_nShadowCursorFillMode = rVOpt.m_nShadowCursorFillMode;
+    m_eGlyphPositioningMode = rVOpt.m_eGlyphPositioningMode;
     m_bStarOneSetting = rVOpt.m_bStarOneSetting;
     mbBookView      = rVOpt.mbBookView;
     mbBrowseMode    = rVOpt.mbBrowseMode;
@@ -295,6 +297,7 @@ SwViewOption& SwViewOption::operator=( const SwViewOption 
&rVOpt )
     m_aRetouchColor  = rVOpt.GetRetoucheColor();
     m_sSymbolFont     = rVOpt.m_sSymbolFont;
     m_nShadowCursorFillMode = rVOpt.m_nShadowCursorFillMode;
+    m_eGlyphPositioningMode = rVOpt.m_eGlyphPositioningMode;
     m_bStarOneSetting = rVOpt.m_bStarOneSetting;
     mbBookView      = rVOpt.mbBookView;
     mbBrowseMode    = rVOpt.mbBrowseMode;
diff --git a/sw/source/uibase/inc/cfgitems.hxx 
b/sw/source/uibase/inc/cfgitems.hxx
index 34ffa2d24e12..18ffc5c9b40b 100644
--- a/sw/source/uibase/inc/cfgitems.hxx
+++ b/sw/source/uibase/inc/cfgitems.hxx
@@ -35,6 +35,7 @@ class SwViewShell;
 class SwViewOption;
 class SwContentOptPage;
 class SwShdwCursorOptionsTabPage;
+enum class GlyphPositioningMode;
 enum class SwFillMode;
 
 /// Item for settings dialog - document view
@@ -84,6 +85,8 @@ class SW_DLLPUBLIC SwElemItem final : public SfxPoolItem
     bool m_bFieldHiddenText   :1;
     bool m_bShowHiddenPara    :1;
 
+    GlyphPositioningMode m_eGlyphPositioningMode;
+
     friend class SwContentOptPage;
 
 public:
diff --git a/sw/source/uibase/inc/optpage.hxx b/sw/source/uibase/inc/optpage.hxx
index 99e24ed7f487..e7a6fe34b1fb 100644
--- a/sw/source/uibase/inc/optpage.hxx
+++ b/sw/source/uibase/inc/optpage.hxx
@@ -42,6 +42,7 @@ class SwContentOptPage final : public SfxTabPage
     std::unique_ptr<weld::CheckButton> m_xVRulerRightCBox;
     std::unique_ptr<weld::ComboBox> m_xVMetric;
     std::unique_ptr<weld::CheckButton> m_xSmoothCBox;
+    std::unique_ptr<weld::ComboBox> m_xGlyphPosModeLB;
 
     std::unique_ptr<weld::CheckButton> m_xGrfCB;
     std::unique_ptr<weld::CheckButton> m_xTableCB;
diff --git a/sw/uiconfig/swriter/ui/viewoptionspage.ui 
b/sw/uiconfig/swriter/ui/viewoptionspage.ui
index 69dd85ed86ab..d8ca6ed7495c 100644
--- a/sw/uiconfig/swriter/ui/viewoptionspage.ui
+++ b/sw/uiconfig/swriter/ui/viewoptionspage.ui
@@ -357,7 +357,7 @@
                 <property name="label-xalign">0</property>
                 <property name="shadow-type">none</property>
                 <child>
-                  <!-- n-columns=1 n-rows=2 -->
+                  <!-- n-columns=1 n-rows=3 -->
                   <object class="GtkGrid" id="grid4">
                     <property name="visible">True</property>
                     <property name="can-focus">False</property>
@@ -488,6 +488,50 @@
                         <property name="top-attach">0</property>
                       </packing>
                     </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="spacing">12</property>
+                        <child>
+                          <object class="GtkLabel" id="glyphposlabel">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="label" translatable="yes" 
context="viewoptionspage|glyphposlabel">Glyph positioning:</property>
+                            <property name="use-underline">True</property>
+                            <property 
name="mnemonic-widget">glyphposmode</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBoxText" id="glyphposmode">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="active">0</property>
+                            <items>
+                              <item translatable="yes" 
context="viewoptionspage|glyphposmode">Classic</item>
+                              <item translatable="yes" 
context="viewoptionspage|glyphposmode">ClassicInspired</item>
+                              <item translatable="yes" 
context="viewoptionspage|glyphposmode">Layout</item>
+                              <item translatable="yes" 
context="viewoptionspage|glyphposmode">Readability</item>
+                            </items>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="top-attach">2</property>
+                      </packing>
+                    </child>
                   </object>
                 </child>
                 <child type="label">
@@ -574,7 +618,7 @@
                 <property name="label-xalign">0</property>
                 <property name="shadow-type">none</property>
                 <child>
-                  <!-- n-columns=3 n-rows=3 -->
+                  <!-- n-columns=1 n-rows=2 -->
                   <object class="GtkGrid">
                     <property name="visible">True</property>
                     <property name="can-focus">False</property>
@@ -621,27 +665,6 @@
                         <property name="top-attach">1</property>
                       </packing>
                     </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
                   </object>
                 </child>
                 <child type="label">
@@ -684,6 +707,7 @@
     <widgets>
       <widget name="vruler"/>
       <widget name="hruler"/>
+      <widget name="glyphposlabel"/>
       <widget name="measureunitlabel"/>
     </widgets>
   </object>

Reply via email to