sw/source/core/inc/scriptinfo.hxx |    4 +-
 sw/source/core/text/porlay.cxx    |   74 +++++++++++++++++++++++++++++---------
 sw/source/core/text/porrst.cxx    |   65 +++++++++++++++++++++++++++++++++
 sw/source/core/text/porrst.hxx    |    4 +-
 4 files changed, 127 insertions(+), 20 deletions(-)

New commits:
commit 3393e52be0900ad63ceee0a43cd44d473ec8248a
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Tue Oct 1 19:33:46 2024 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Sat Oct 5 16:20:57 2024 +0200

    tdf#163309 sw: show rdf:type as labels on bookmark boundary marks
    
    OOo's RDF handling had limited support to optional metadata visualization, 
like custom prefix/suffix of metadata fields.
    This is a similar visualization for bookmark rdf:type metadata,
    but without changing the text layout by enabling/disabling
    View->Field Shading.
    
    The labels, i.e. text content of rdf:type have left-aligned
    top position after the opening bracket of the optional bookmark
    boundary mark, and right-aligned bottom position before the
    closing bracket. The labels don't overlap at multiple brackets.
    
    Note: the labels are very next to the line text vertically
    to support fixed line height better.
    
    Follow-up to commit 412e0ab26618c38f548c340f85ef63bbe73ef6b2
    "tdf#150717 sw RDF metadata: add custom color bookmark boundary marks"
    
    Change-Id: I0756c91b51c706f4c7b70fa07f1c7e8fbbf0dc90
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174486
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sw/source/core/inc/scriptinfo.hxx 
b/sw/source/core/inc/scriptinfo.hxx
index 60cf9c542eab..65c34f407a3e 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -72,7 +72,7 @@ private:
     std::deque<TextFrameIndex> m_NoKashidaLine;
     std::deque<TextFrameIndex> m_NoKashidaLineEnd;
     std::vector<TextFrameIndex> m_HiddenChg;
-    std::vector<std::tuple<TextFrameIndex, MarkKind, Color, OUString>> 
m_Bookmarks;
+    std::vector<std::tuple<TextFrameIndex, MarkKind, Color, OUString, 
OUString>> m_Bookmarks;
     //! Records a single change in compression.
     struct CompressionChangeInfo
     {
@@ -184,7 +184,7 @@ public:
     }
     TextFrameIndex NextHiddenChg(TextFrameIndex nPos) const;
     TextFrameIndex NextBookmark(TextFrameIndex nPos) const;
-    std::vector<std::tuple<MarkKind, Color, OUString>>
+    std::vector<std::tuple<MarkKind, Color, OUString, OUString>>
             GetBookmarks(TextFrameIndex const nPos);
     static void CalcHiddenRanges(const SwTextNode& rNode,
             MultiSelection& rHiddenMulti,
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 39a260ac0ef8..9f0fd502114f 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -909,13 +909,54 @@ static Color getBookmarkColor(const SwTextNode& rNode, 
const sw::mark::Bookmark*
     return c;
 }
 
+static OUString getBookmarkType(const SwTextNode& rNode, const 
sw::mark::Bookmark* pBookmark)
+{
+    // search ODF_PREFIX in metadata, otherwise use empty string;
+    OUString sRet;
+
+    try
+    {
+        SwDoc& rDoc = const_cast<SwDoc&>(rNode.GetDoc());
+        const rtl::Reference< SwXBookmark > xRef = 
SwXBookmark::CreateXBookmark(rDoc,
+                const_cast<sw::mark::MarkBase*>(static_cast<const 
sw::mark::MarkBase*>(pBookmark)));
+        const css::uno::Reference<css::rdf::XResource> xSubject(xRef);
+        rtl::Reference<SwXTextDocument> xModel = 
rDoc.GetDocShell()->GetBaseModel();
+
+        static uno::Reference< uno::XComponentContext > xContext(
+            ::comphelper::getProcessComponentContext());
+
+        static uno::Reference< rdf::XURI > xODF_PREFIX(
+            rdf::URI::createKnown(xContext, rdf::URIs::RDF_TYPE), 
uno::UNO_SET_THROW);
+
+        uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(
+            rDoc.GetDocShell()->GetBaseModel());
+        const uno::Reference<rdf::XRepository>& xRepository =
+            xDocumentMetadataAccess->getRDFRepository();
+        const uno::Reference<container::XEnumeration> xEnum(
+            xRepository->getStatements(xSubject, xODF_PREFIX, nullptr), 
uno::UNO_SET_THROW);
+
+        rdf::Statement stmt;
+        if ( xEnum->hasMoreElements() && (xEnum->nextElement() >>= stmt) )
+        {
+            const uno::Reference<rdf::XLiteral> xObject(stmt.Object, 
uno::UNO_QUERY);
+            if ( xObject.is() )
+                sRet = xObject->getValue();
+        }
+    }
+    catch (const lang::IllegalArgumentException&)
+    {
+    }
+
+    return sRet;
+}
+
 static void InitBookmarks(
     std::optional<std::vector<sw::Extent>::const_iterator> oPrevIter,
     std::vector<sw::Extent>::const_iterator iter,
     std::vector<sw::Extent>::const_iterator const end,
     TextFrameIndex nOffset,
     std::vector<std::pair<sw::mark::Bookmark const*, SwScriptInfo::MarkKind>> 
& rBookmarks,
-    std::vector<std::tuple<TextFrameIndex, SwScriptInfo::MarkKind, Color, 
OUString>> & o_rBookmarks)
+    std::vector<std::tuple<TextFrameIndex, SwScriptInfo::MarkKind, Color, 
OUString, OUString>> & o_rBookmarks)
 {
     SwTextNode const*const pNode(iter->pNode);
     for (auto const& it : rBookmarks)
@@ -925,7 +966,7 @@ static void InitBookmarks(
 
         // search for custom bookmark boundary mark color
         Color c = getBookmarkColor(*pNode, it.first);
-
+        OUString sType = getBookmarkType(*pNode, it.first);
         switch (it.second)
         {
             case SwScriptInfo::MarkKind::Start:
@@ -953,7 +994,7 @@ static void InitBookmarks(
                         }
                         else
                         {
-                            o_rBookmarks.emplace_back(nOffset, it.second, c, 
it.first->GetName());
+                            o_rBookmarks.emplace_back(nOffset, it.second, c, 
it.first->GetName(), sType);
                             break;
                         }
                     }
@@ -972,7 +1013,7 @@ static void InitBookmarks(
                         {
                             o_rBookmarks.emplace_back(
                                 nOffset + 
TextFrameIndex(rStart.GetContentIndex() - iter->nStart),
-                                it.second, c, it.first->GetName());
+                                it.second, c, it.first->GetName(), sType);
                             break;
                         }
                     }
@@ -991,7 +1032,7 @@ static void InitBookmarks(
                     }
                     else
                     {
-                        o_rBookmarks.emplace_back(nOffset, it.second, c, 
it.first->GetName());
+                        o_rBookmarks.emplace_back(nOffset, it.second, c, 
it.first->GetName(), sType);
                     }
                 }
                 break;
@@ -1020,7 +1061,7 @@ static void InitBookmarks(
                         }
                         else
                         {
-                            o_rBookmarks.emplace_back(nOffset, it.second, c, 
it.first->GetName());
+                            o_rBookmarks.emplace_back(nOffset, it.second, c, 
it.first->GetName(), sType);
                             break;
                         }
                     }
@@ -1028,7 +1069,7 @@ static void InitBookmarks(
                     {
                         o_rBookmarks.emplace_back(
                             nOffset + TextFrameIndex(rEnd.GetContentIndex() - 
iter->nStart),
-                            it.second, c, it.first->GetName());
+                            it.second, c, it.first->GetName(), sType);
                         break;
                     }
                     else
@@ -1062,7 +1103,7 @@ static void InitBookmarks(
                         {
                             o_rBookmarks.emplace_back(
                                 nOffset + 
TextFrameIndex(rPos.GetContentIndex() - iter->nStart),
-                                it.second, c, it.first->GetName());
+                                it.second, c, it.first->GetName(), sType);
                         }
                         break;
                     }
@@ -1210,17 +1251,18 @@ void SwScriptInfo::InitScriptInfo(const SwTextNode& 
rNode,
 
             // search for custom bookmark boundary mark color
             Color c = getBookmarkColor(rNode, it.first);
+            OUString sType = getBookmarkType(rNode, it.first);
 
             switch (it.second)
             {
                 case MarkKind::Start:
-                    
m_Bookmarks.emplace_back(TextFrameIndex(it.first->GetMarkStart().GetContentIndex()),
 it.second, c, it.first->GetName());
+                    
m_Bookmarks.emplace_back(TextFrameIndex(it.first->GetMarkStart().GetContentIndex()),
 it.second, c, it.first->GetName(), sType);
                     break;
                 case MarkKind::End:
-                    
m_Bookmarks.emplace_back(TextFrameIndex(it.first->GetMarkEnd().GetContentIndex()),
 it.second, c, it.first->GetName());
+                    
m_Bookmarks.emplace_back(TextFrameIndex(it.first->GetMarkEnd().GetContentIndex()),
 it.second, c, it.first->GetName(), sType);
                     break;
                 case MarkKind::Point:
-                    
m_Bookmarks.emplace_back(TextFrameIndex(it.first->GetMarkPos().GetContentIndex()),
 it.second, c, it.first->GetName());
+                    
m_Bookmarks.emplace_back(TextFrameIndex(it.first->GetMarkPos().GetContentIndex()),
 it.second, c, it.first->GetName(), sType);
                     break;
             }
         }
@@ -1762,10 +1804,10 @@ TextFrameIndex 
SwScriptInfo::NextBookmark(TextFrameIndex const nPos) const
     return TextFrameIndex(COMPLETE_STRING);
 }
 
-std::vector<std::tuple<SwScriptInfo::MarkKind, Color, OUString>>
+std::vector<std::tuple<SwScriptInfo::MarkKind, Color, OUString, OUString>>
                                     SwScriptInfo::GetBookmarks(TextFrameIndex 
const nPos)
 {
-    std::vector<std::tuple<SwScriptInfo::MarkKind, Color, OUString>> aColors;
+    std::vector<std::tuple<SwScriptInfo::MarkKind, Color, OUString, OUString>> 
aColors;
     for (auto const& it : m_Bookmarks)
     {
         if (nPos == std::get<0>(it))
@@ -1774,8 +1816,8 @@ std::vector<std::tuple<SwScriptInfo::MarkKind, Color, 
OUString>>
             // filter hidden bookmarks imported from OOXML
             // TODO import them as hidden bookmarks
             if ( !( sName.startsWith("_Toc") || sName.startsWith("_Ref") ) )
-                aColors.push_back(std::tuple<MarkKind, Color,
-                                    OUString>(std::get<1>(it), 
std::get<2>(it), std::get<3>(it)));
+                aColors.push_back(std::tuple<MarkKind, Color, OUString,
+                                    OUString>(std::get<1>(it), 
std::get<2>(it), std::get<3>(it), std::get<4>(it)));
         }
         else if (nPos < std::get<0>(it))
         {
@@ -1787,7 +1829,7 @@ std::vector<std::tuple<SwScriptInfo::MarkKind, Color, 
OUString>>
     // mark order: ] | [
     // color order: [c1 [c2 [c3 ... c3] c2] c1]
     sort(aColors.begin(), aColors.end(),
-                 [](std::tuple<MarkKind, Color, OUString> const a, 
std::tuple<MarkKind, Color, OUString> const b) {
+                 [](std::tuple<MarkKind, Color, OUString, OUString> const a, 
std::tuple<MarkKind, Color, OUString, OUString> const b) {
          return (MarkKind::End == std::get<0>(a) && MarkKind::End != 
std::get<0>(b)) ||
              (MarkKind::Point == std::get<0>(a) && MarkKind::Start == 
std::get<0>(b)) ||
              // if both are end or start, order by color
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index ee409a4c80e2..0a8bab3d66ea 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -819,6 +819,8 @@ void SwBookmarkPortion::Paint( const SwTextPaintInfo &rInf 
) const
     if ( !mnHalfCharWidth )
         mnHalfCharWidth = rInf.GetTextSize( aOutString ).Width() / 2;
 
+    auto nHeight = rInf.GetTextSize( aOutString ).Height();
+
     Point aOldPos = rInf.GetPos();
     Point aNewPos( aOldPos );
     auto const deltaX((Width() / 2) - mnHalfCharWidth);
@@ -858,6 +860,9 @@ void SwBookmarkPortion::Paint( const SwTextPaintInfo &rInf 
) const
 
     const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );
 
+    SwTwips nTypePos = 0; // shift to the position of the next rdf:type label
+    sal_Int32 nDirection = -1; // start with the closing brackets
+    bool bStart = true;
     for ( const auto& it : m_aColors )
     {
         // set bold for custom colored bookmark symbol
@@ -866,6 +871,17 @@ void SwBookmarkPortion::Paint( const SwTextPaintInfo &rInf 
) const
         aTmpFont.SetColor( COL_TRANSPARENT == std::get<1>(it) ? 
rInf.GetOpt().GetFieldShadingsColor() : std::get<1>(it) );
         aOutString = OUString(std::get<0>(it) == SwScriptInfo::MarkKind::Start 
? '[' : ']');
 
+        if (nDirection == -1 && std::get<0>(it) != SwScriptInfo::MarkKind::End)
+        {
+            nDirection = 1;
+            nTypePos = mnHalfCharWidth * 2; // start label after the opening 
bracket
+        }
+
+        // vertical rdf:type label position for the opening and closing 
brackets
+        sal_Int32 fPos = std::get<0>(it) == SwScriptInfo::MarkKind::Start
+                ? -0.6 * nHeight
+                : 0.3 * nHeight;
+
         // MarkKind::Point: drawn I-beam (e.g. U+2336) as overlapping ][
         if ( std::get<0>(it) == SwScriptInfo::MarkKind::Point )
         {
@@ -880,6 +896,55 @@ void SwBookmarkPortion::Paint( const SwTextPaintInfo &rInf 
) const
             aOutString = OUString('[');
         }
         rInf.DrawText( aOutString, *this );
+
+        // show rdf:type labels, left-aligned top position after the opening 
brackets
+        // right-aligned bottom position before the closing brackets
+        // if there are multiple opening or closing brackets, collect
+        // their length in nTypePos to show non-overlapping labels
+        OUString sType = std::get<3>(it);
+        if ( !sType.isEmpty() )
+        {
+            Size aTmpSz = aTmpFont.GetSize( SwFontScript::Latin );
+            auto origSize = aTmpSz;
+
+            // calculate label size
+            aTmpSz.setHeight( ( 100 * aTmpSz.Height() ) / 250 );
+            aTmpSz.setWidth( ( 100 * aTmpSz.Width() ) / 250 );
+
+            if ( aTmpSz.Width() || aTmpSz.Height() )
+            {
+                aTmpFont.SetSize( aTmpSz, SwFontScript::Latin );
+
+                aNewPos.AdjustY(fPos);
+                if ( nDirection == -1 )
+                {
+                    if (bStart)
+                    {
+                        nTypePos += rInf.GetTextSize( sType ).Width();
+                        bStart = false;
+                    }
+                    else
+                        nTypePos += rInf.GetTextSize( sType + " " ).Width() + 
2 * mnHalfCharWidth;
+                }
+                aNewPos.AdjustX( nDirection * nTypePos );
+
+                const_cast< SwTextPaintInfo& >( rInf ).SetPos( aNewPos );
+
+                rInf.DrawText( sType, *this );
+
+                // restore original position
+                aNewPos.AdjustX( -nDirection * nTypePos );
+                if ( nDirection == 1 )
+                    nTypePos += rInf.GetTextSize( sType + " " ).Width() - 
mnHalfCharWidth * 2;
+
+                aNewPos.AdjustY(-fPos);
+            }
+            // restore original text size
+            aTmpSz.setHeight(origSize.Height());
+            aTmpSz.setWidth(origSize.Width());
+            aTmpFont.SetSize( origSize, SwFontScript::Latin );
+        }
+
         // place the next symbol after the previous one
         // TODO: fix orientation and start/end
         aNewPos.AdjustX(mnHalfCharWidth * 2);
diff --git a/sw/source/core/text/porrst.hxx b/sw/source/core/text/porrst.hxx
index 889f7e7d775a..85c58d6e2619 100644
--- a/sw/source/core/text/porrst.hxx
+++ b/sw/source/core/text/porrst.hxx
@@ -185,13 +185,13 @@ public:
 class SwBookmarkPortion : public SwControlCharPortion
 {
     // custom colors defined by metadata
-    std::vector<std::tuple<SwScriptInfo::MarkKind, Color, OUString>> m_aColors;
+    std::vector<std::tuple<SwScriptInfo::MarkKind, Color, OUString, OUString>> 
m_aColors;
     // number of MarkKind marks
     sal_Int16 m_nStart, m_nEnd, m_nPoint;
     bool m_bHasCustomColor;
 
 public:
-    explicit SwBookmarkPortion(sal_Unicode const cChar, 
std::vector<std::tuple<SwScriptInfo::MarkKind, Color, OUString>> aColors)
+    explicit SwBookmarkPortion(sal_Unicode const cChar, 
std::vector<std::tuple<SwScriptInfo::MarkKind, Color, OUString, OUString>> 
aColors)
         : SwControlCharPortion(cChar), m_aColors(std::move(aColors)), 
m_nStart(0), m_nEnd(0), m_nPoint(0), m_bHasCustomColor(false)
     {
         SetWhichPor(PortionType::Bookmark);

Reply via email to