summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2020-01-24 19:05:40 +0100
committerMichael Stahl <Michael.Stahl@cib.de>2020-06-04 18:30:21 +0200
commit5a7288901fad8bd833357f1672213bce8273ab3c (patch)
tree83f4bec2d475b3ab9316d4e0308bc1f7c11641e7
parentdcadfae807de0ef81183d4e95126aa140cb707e2 (diff)
tdf#45589 sw: create and paint text portions for bookmarks
Add a new SwBookmarkPortion, derived from SwControlCharPortion. There is no character for the bookmark in the text so the portion has length of 0, which makes things quite a bit more tricky. Formatting: * SwBookmarkPortion is created last in WhichFirstPortion(). * In an empty paragraph the SwTextFrame::FormatEmpty() must be disabled. * If there's a bookmark at the end of a paragraph, SwTextFormatter::CalcAscent() must use the font of the previous character, not the paragraph font, because that could grow the line if it's higher. * The SwMultiPortion complicates matters, because it uses a nested SwTextFormatInfo and thus we need some extra steps to prevent duplicate SwBookmarkPortions; this is particluarly a problem for rotated text portions. - SwTextFormatter::BuildPortions() must advance the outer SwTextFormatInfo's bookmark position because BuildMultiPortion() has already created the SwBookmarkPortion. - If a SwBookmarkPortion is at the start of a SwMultiPortion, it will be created before the SwMultiPortion but must be painted inside the SwMultiPortion because its font is going to be initialised as inside the SwMultiPortion (e.g. it will be rotated) so its position must also be adapted to be inside, and only SwTextPainter::PaintMultiPortion() does the setup for that; add a hack to move it in SwTextFormatter::BuildMultiPortion(). Painting: * Using the original font seems rather difficult, hard to predict what some character is going to look like, and how it scales if the size is increased; use OpenSymbol instead. Unfortunately OpenSymbol doesn't have a good glyph that could be used for both the end of a bookmark and start of another bookmark at the same position. * SwLinePortion::PrePaint() wants to avoid moving the portion half-outside the frame but often it looks better that way (previously it was misaligned, now it's half-outside). * Not sure if it makes sense to draw a field shading in SwTextPaintInfo::DrawViewOpt() too; let's try it out, but dependent on the same IsViewMetaChars() setting as the bookmark character itself, not on the field shading setting. Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87364 Reviewed-by: Michael Stahl <michael.stahl@cib.de> Tested-by: Michael Stahl <michael.stahl@cib.de> (cherry picked from commit 4ce8120f1e53f7b81e653b01d141643013bc69ab) Change-Id: I1ab94afb417221e278dbb3afd6c978a05fc78497
-rw-r--r--sw/qa/extras/ooxmlimport/ooxmlimport.cxx10
-rw-r--r--sw/source/core/access/accportions.cxx3
-rw-r--r--sw/source/core/inc/scriptinfo.hxx11
-rw-r--r--sw/source/core/inc/txttypes.hxx1
-rw-r--r--sw/source/core/text/inftxt.cxx23
-rw-r--r--sw/source/core/text/inftxt.hxx3
-rwxr-xr-xsw/source/core/text/itrform2.cxx51
-rw-r--r--sw/source/core/text/porlay.cxx17
-rw-r--r--sw/source/core/text/porlin.cxx4
-rw-r--r--sw/source/core/text/porlin.hxx2
-rw-r--r--sw/source/core/text/pormulti.cxx14
-rw-r--r--sw/source/core/text/porrst.cxx122
-rw-r--r--sw/source/core/text/porrst.hxx30
-rw-r--r--sw/source/core/text/xmldump.cxx1
14 files changed, 265 insertions, 27 deletions
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index 4743cbc8afed..300bc3a70499 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -311,8 +311,14 @@ DECLARE_OOXMLIMPORT_TEST(testN758883, "n758883.docx")
* The problem was that direct formatting of the paragraph was not applied
* to the numbering. This is easier to test using a layout dump.
*/
- OUString aHeight = parseDump("/root/page/body/txt/Special", "nHeight");
- CPPUNIT_ASSERT_EQUAL(sal_Int32(220), aHeight.toInt32()); // It was 280
+ xmlDocPtr pXmlDoc = parseLayoutDump();
+ assertXPath(pXmlDoc, "/root/page/body/txt/Special[1]", "nHeight", "220");
+
+ // check the bookmark portions are of the expected height
+ assertXPath(pXmlDoc, "/root/page/body/txt/Special[2]", "nType", "POR_BOOKMARK");
+ assertXPath(pXmlDoc, "/root/page/body/txt/Special[2]", "nHeight", "253");
+ assertXPath(pXmlDoc, "/root/page/body/txt/Special[3]", "nType", "POR_BOOKMARK");
+ assertXPath(pXmlDoc, "/root/page/body/txt/Special[3]", "nHeight", "253");
/*
* Next problem was that the page margin contained the width of the page border as well.
diff --git a/sw/source/core/access/accportions.cxx b/sw/source/core/access/accportions.cxx
index 14b00e1b3dd4..32723457d50b 100644
--- a/sw/source/core/access/accportions.cxx
+++ b/sw/source/core/access/accportions.cxx
@@ -180,6 +180,9 @@ void SwAccessiblePortionData::Special(
case POR_CONTROLCHAR:
sDisplay = rText + OUStringLiteral1( m_pTextNode->GetText()[m_nModelPosition] );
break;
+ case POR_BOOKMARK:
+ // TODO
+ break;
default:
sDisplay = rText;
break;
diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
index 124709786e9e..9a408f52abe6 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -25,6 +25,7 @@
#include <swscanner.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>
+#include <o3tl/typed_flags_set.hxx>
#include "TextFrameIndex.hxx"
class SwTextNode;
@@ -43,7 +44,7 @@ class SwScriptInfo
{
public:
enum CompType { KANA, SPECIAL_LEFT, SPECIAL_RIGHT, NONE, SPECIAL_MIDDLE};
- enum class MarkKind { Start, End, Point };
+ enum class MarkKind { Start = (1<<0), End = (1<<1), Point = (1<<2) };
private:
//! Records a single change in script type.
@@ -182,6 +183,7 @@ public:
return m_HiddenChg[ nCnt ];
}
TextFrameIndex NextBookmark(TextFrameIndex nPos) const;
+ MarkKind GetBookmark(TextFrameIndex nPos) const;
static void CalcHiddenRanges(const SwTextNode& rNode,
MultiSelection& rHiddenMulti,
std::vector<std::pair<sw::mark::IBookmark const*, MarkKind>> * pBookmarks);
@@ -385,6 +387,13 @@ public:
static SwFontScript WhichFont(sal_Int32 nIdx, OUString const & rText);
};
+namespace o3tl
+{
+
+template<> struct typed_flags<SwScriptInfo::MarkKind> : is_typed_flags<SwScriptInfo::MarkKind, 0x07> {};
+
+}
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/txttypes.hxx b/sw/source/core/inc/txttypes.hxx
index 1633afc07f69..3925e98796d9 100644
--- a/sw/source/core/inc/txttypes.hxx
+++ b/sw/source/core/inc/txttypes.hxx
@@ -33,6 +33,7 @@
#define POR_MULTI 0x0085
#define POR_HIDDEN_TXT 0x0086
#define POR_CONTROLCHAR 0x0087
+#define POR_BOOKMARK 0x0088
#define POR_TXT 0x8000
#define POR_LAY 0x8001
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index 5c7faa1b8511..bd1c45721bc1 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -1296,6 +1296,14 @@ void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
bDraw = true;
}
break;
+ case POR_BOOKMARK:
+ if (!GetOpt().IsPagePreview()
+ && !GetOpt().IsReadonly()
+ && GetOpt().IsViewMetaChars())
+ {
+ bDraw = true;
+ }
+ break;
case POR_INPUTFLD:
// input field shading also in read-only mode
if ( !GetOpt().IsPagePreview()
@@ -1484,6 +1492,7 @@ void SwTextFormatInfo::Init()
m_nForcedLeftMargin = 0;
m_nSoftHyphPos = TextFrameIndex(0);
m_nUnderScorePos = TextFrameIndex(COMPLETE_STRING);
+ m_nLastBookmarkPos = TextFrameIndex(-1);
m_cHookChar = 0;
SetIdx(TextFrameIndex(0));
SetLen(TextFrameIndex(GetText().getLength()));
@@ -1895,4 +1904,18 @@ bool SwTextFormatInfo::ChgHyph( const bool bNew )
return bOld;
}
+
+bool SwTextFormatInfo::CheckCurrentPosBookmark()
+{
+ if (m_nLastBookmarkPos != GetIdx())
+ {
+ m_nLastBookmarkPos = GetIdx();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index 1156e1197c14..2ee460e35a2e 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -484,6 +484,7 @@ class SwTextFormatInfo : public SwTextPaintInfo
TextFrameIndex m_nSoftHyphPos; ///< SoftHyphPos for Hyphenation
TextFrameIndex m_nLineStart; ///< Current line start in rText
TextFrameIndex m_nUnderScorePos; ///< enlarge repaint if underscore has been found
+ TextFrameIndex m_nLastBookmarkPos; ///< need to check for bookmarks at every portion
// #i34348# Changed type from sal_uInt16 to SwTwips
SwTwips m_nLeft; // Left margin
SwTwips m_nRight; // Right margin
@@ -640,6 +641,8 @@ public:
bool IsArrowDone() const { return m_bArrowDone; }
void SetArrowDone( const bool bNew ) { m_bArrowDone = bNew; }
+ bool CheckCurrentPosBookmark();
+
// For SwTextPortion::Hyphenate
bool ChgHyph( const bool bNew );
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index f3fca32c60c7..e838b8c08289 100755
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -705,6 +705,10 @@ void SwTextFormatter::BuildPortions( SwTextFormatInfo &rInf )
CalcAscent( rInf, pPor );
InsertPortion( rInf, pPor );
+ if (pPor->IsMultiPortion() && (!pMulti || pMulti->IsBidi()))
+ {
+ (void) rInf.CheckCurrentPosBookmark(); // bookmark was already created inside MultiPortion!
+ }
pPor = NewPortion( rInf );
}
@@ -767,6 +771,19 @@ void SwTextFormatter::CalcAscent( SwTextFormatInfo &rInf, SwLinePortion *pPor )
pPor->Height( pLast->Height() );
pPor->SetAscent( pLast->GetAscent() );
}
+ else if (pPor->GetWhichPor() == POR_BOOKMARK
+ && rInf.GetIdx() == TextFrameIndex(rInf.GetText().getLength()))
+ {
+ // bookmark at end of paragraph: *don't* advance iterator, use the
+ // current font instead; it's possible that there's a font size on the
+ // paragraph and it's overridden on the last line of the paragraph and
+ // we don't want to apply it via SwBookmarkPortion and grow the line
+ // height (example: n758883.docx)
+ SwLinePortion const*const pLast = rInf.GetLast();
+ assert(pLast);
+ pPor->Height( pLast->Height() );
+ pPor->SetAscent( pLast->GetAscent() );
+ }
else
{
const SwLinePortion *pLast = rInf.GetLast();
@@ -1008,6 +1025,7 @@ SwTextPortion *SwTextFormatter::NewTextPortion( SwTextFormatInfo &rInf )
return pPor;
}
+// first portions have no length
SwLinePortion *SwTextFormatter::WhichFirstPortion(SwTextFormatInfo &rInf)
{
SwLinePortion *pPor = nullptr;
@@ -1140,6 +1158,39 @@ SwLinePortion *SwTextFormatter::WhichFirstPortion(SwTextFormatInfo &rInf)
pPor = TryNewNoLengthPortion(rInf);
}
+ // 12. bookmarks
+ // check this *last* so that BuildMultiPortion() can find it!
+ if (!pPor && rInf.CheckCurrentPosBookmark())
+ {
+ auto const bookmark(m_pScriptInfo->GetBookmark(rInf.GetIdx()));
+ if (static_cast<bool>(bookmark))
+ {
+ sal_Unicode mark;
+ if ((bookmark & (SwScriptInfo::MarkKind::Start|SwScriptInfo::MarkKind::End))
+ == (SwScriptInfo::MarkKind::Start|SwScriptInfo::MarkKind::End))
+ {
+ //mark = u'\u2336'; // not in OpenSymbol :(
+ mark = '|';
+ // hmm ... paint U+2345 over U+2346 should be same width?
+ // and U+237F // or U+2E20/U+2E21
+ }
+ else if (bookmark & SwScriptInfo::MarkKind::Start)
+ {
+ mark = '[';
+ }
+ else if (bookmark & SwScriptInfo::MarkKind::End)
+ {
+ mark = ']';
+ }
+ else
+ {
+ assert(bookmark & SwScriptInfo::MarkKind::Point);
+ mark = '|';
+ }
+ pPor = new SwBookmarkPortion(rInf.GetLast(), mark);
+ }
+ }
+
return pPor;
}
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index bf9d78c4228a..ce2b16c74323 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -1654,6 +1654,23 @@ TextFrameIndex SwScriptInfo::NextBookmark(TextFrameIndex const nPos) const
return TextFrameIndex(COMPLETE_STRING);
}
+auto SwScriptInfo::GetBookmark(TextFrameIndex const nPos) const -> MarkKind
+{
+ MarkKind ret{0};
+ for (auto const& it : m_Bookmarks)
+ {
+ if (nPos == it.first)
+ {
+ ret |= it.second;
+ }
+ else if (nPos < it.first)
+ {
+ break;
+ }
+ }
+ return ret;
+}
+
// Takes a string and replaced the hidden ranges with cChar.
sal_Int32 SwScriptInfo::MaskHiddenRanges( const SwTextNode& rNode, OUStringBuffer & rText,
const sal_Int32 nStt, const sal_Int32 nEnd,
diff --git a/sw/source/core/text/porlin.cxx b/sw/source/core/text/porlin.cxx
index a7a6a09457ea..86e6e5547c2f 100644
--- a/sw/source/core/text/porlin.cxx
+++ b/sw/source/core/text/porlin.cxx
@@ -105,7 +105,9 @@ void SwLinePortion::PrePaint( const SwTextPaintInfo& rInf,
1800 :
rInf.GetFont()->GetOrientation( rInf.GetTextFrame()->IsVertical() );
- if (nLastWidth > nHalfView)
+ // pLast == this *only* for the 1st portion in the line so nLastWidth is 0;
+ // allow this too, will paint outside the frame but might look better...
+ if (nLastWidth > nHalfView || pLast == this)
{
switch (nDir)
{
diff --git a/sw/source/core/text/porlin.hxx b/sw/source/core/text/porlin.hxx
index 729740024890..0a9ac2fac875 100644
--- a/sw/source/core/text/porlin.hxx
+++ b/sw/source/core/text/porlin.hxx
@@ -135,7 +135,7 @@ public:
bool IsArrowPortion() const { return nWhichPor == POR_ARROW; }
bool IsMultiPortion() const { return nWhichPor == POR_MULTI; }
bool IsNumberPortion() const { return nWhichPor == POR_NUMBER; } // #i23726#
- bool IsControlCharPortion() const { return nWhichPor == POR_CONTROLCHAR; }
+ bool IsControlCharPortion() const { return nWhichPor == POR_CONTROLCHAR || nWhichPor == POR_BOOKMARK; }
// Positioning
SwLinePortion *FindPrevPortion( const SwLinePortion *pRoot );
diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 78423e440a6f..5ff1fceb5a92 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -43,6 +43,7 @@
#include "porfld.hxx"
#include "porglue.hxx"
#include <breakit.hxx>
+#include "porrst.hxx"
#include <pagefrm.hxx>
#include <rowfrm.hxx>
#include <pagedesc.hxx>
@@ -2026,6 +2027,19 @@ bool SwTextFormatter::BuildMultiPortion( SwTextFormatInfo &rInf,
aInf.SetNumDone( rInf.IsNumDone() );
aInf.SetFootnoteDone( rInf.IsFootnoteDone() );
+ // if there's a bookmark at the start of the MultiPortion, it will be
+ // painted with the rotation etc. of the MultiPortion; move it *inside*
+ // so it gets positioned correctly; currently there's no other portion
+ // inserted between the end of WhichFirstPortion() and
+ // BuildMultiPortion()
+ if (rInf.GetLast()->GetWhichPor() == POR_BOOKMARK)
+ {
+ auto const pBookmark(static_cast<SwBookmarkPortion*>(rInf.GetLast()));
+ rInf.SetLast(pBookmark->Unchain());
+ assert(m_pCurr->GetPortion() == nullptr);
+ m_pCurr->SetPortion(pBookmark);
+ }
+
if( pFirstRest )
{
OSL_ENSURE( pFirstRest->InFieldGrp(), "BuildMulti: Fieldrest expected");
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index d52e6ef2fb5e..067ae9d477f0 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -309,6 +309,17 @@ bool SwTextFrame::FormatEmpty()
aTextFly.IsOn() && aTextFly.IsAnyObj( aRect ) )
return false;
+ // only need to check one node because of early return on GetMerged()
+ for (SwIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex();
+ pIndex; pIndex = pIndex->GetNext())
+ {
+ sw::mark::IMark const*const pMark = pIndex->GetMark();
+ if (dynamic_cast<const sw::mark::IBookmark*>(pMark) != nullptr)
+ { // need bookmark portions!
+ return false;
+ }
+ }
+
SwTwips nHeight = EmptyHeight();
if (aSet.GetParaGrid().GetValue() &&
@@ -484,35 +495,92 @@ bool SwHiddenTextPortion::Format( SwTextFormatInfo &rInf )
return false;
};
+bool SwControlCharPortion::DoPaint(SwTextPaintInfo const&,
+ OUString & rOutString, SwFont & rTmpFont, int &) const
+{
+ if (mcChar == CHAR_ZWNBSP || !SwViewOption::IsFieldShadings())
+ {
+ return false;
+ }
+
+ switch (mcChar)
+ {
+ case CHAR_ZWSP:
+ rOutString = "/"; break;
+// case CHAR_LRM :
+// rText = sal_Unicode(0x2514); break;
+// case CHAR_RLM :
+// rText = sal_Unicode(0x2518); break;
+ default:
+ assert(false);
+ break;
+ }
+
+ rTmpFont.SetEscapement( CHAR_ZWSP == mcChar ? DFLT_ESC_AUTO_SUB : -25 );
+ const sal_uInt16 nProp = 40;
+ rTmpFont.SetProportion( nProp ); // a smaller font
+
+ return true;
+}
+
+bool SwBookmarkPortion::DoPaint(SwTextPaintInfo const& rInf,
+ OUString & rOutString, SwFont & rTmpFont, int & rDeltaY) const
+{
+ if (!rInf.GetOpt().IsViewMetaChars())
+ {
+ return false;
+ }
+
+ rOutString = OUStringLiteral1(mcChar);
+
+ // init font: we want OpenSymbol to ensure it doesn't look too crazy;
+ // thin and a bit higher than the surrounding text
+ auto const nOrigAscent(rTmpFont.GetAscent(rInf.GetVsh(), *rInf.GetOut()));
+ rTmpFont.SetName("OpenSymbol", rTmpFont.GetActual());
+ Size size(rTmpFont.GetSize(rTmpFont.GetActual()));
+ // use also the external leading (line gap) of the portion, but don't use
+ // 100% of it because i can't figure out how to baseline align that
+ auto const nFactor = (Height() * 95) / size.Height();
+ rTmpFont.SetProportion(nFactor);
+ rTmpFont.SetWeight(WEIGHT_THIN, rTmpFont.GetActual());
+ rTmpFont.SetColor(NON_PRINTING_CHARACTER_COLOR);
+ // reset these to default...
+ rTmpFont.SetAlign(ALIGN_BASELINE);
+ rTmpFont.SetUnderline(LINESTYLE_NONE);
+ rTmpFont.SetOverline(LINESTYLE_NONE);
+ rTmpFont.SetStrikeout(STRIKEOUT_NONE);
+ rTmpFont.SetOutline(false);
+ rTmpFont.SetShadow(false);
+ rTmpFont.SetTransparent(false);
+ rTmpFont.SetEmphasisMark(FontEmphasisMark::NONE);
+ rTmpFont.SetEscapement(0);
+ rTmpFont.SetPitch(PITCH_DONTKNOW, rTmpFont.GetActual());
+ rTmpFont.SetRelief(FontRelief::NONE);
+
+ // adjust Y position to account for different baselines of the fonts
+ auto const nOSAscent(rTmpFont.GetAscent(rInf.GetVsh(), *rInf.GetOut()));
+ rDeltaY = nOSAscent - nOrigAscent;
+
+ return true;
+}
+
void SwControlCharPortion::Paint( const SwTextPaintInfo &rInf ) const
{
if ( Width() ) // is only set during prepaint mode
{
- rInf.DrawViewOpt( *this, POR_CONTROLCHAR );
+ rInf.DrawViewOpt(*this, GetWhichPor());
- if ( !rInf.GetOpt().IsPagePreview() &&
- !rInf.GetOpt().IsReadonly() &&
- SwViewOption::IsFieldShadings() &&
- CHAR_ZWNBSP != mcChar )
+ int deltaY(0);
+ SwFont aTmpFont( *rInf.GetFont() );
+ OUString aOutString;
+
+ if (rInf.OnWin()
+ && !rInf.GetOpt().IsPagePreview()
+ && !rInf.GetOpt().IsReadonly()
+ && DoPaint(rInf, aOutString, aTmpFont, deltaY))
{
- SwFont aTmpFont( *rInf.GetFont() );
- aTmpFont.SetEscapement( CHAR_ZWSP == mcChar ? DFLT_ESC_AUTO_SUB : -25 );
- const sal_uInt16 nProp = 40;
- aTmpFont.SetProportion( nProp ); // a smaller font
SwFontSave aFontSave( rInf, &aTmpFont );
- OUString aOutString;
-
- switch ( mcChar )
- {
- case CHAR_ZWSP :
- aOutString = "/"; break;
-// case CHAR_LRM :
-// rText = sal_Unicode(0x2514); break;
-// case CHAR_RLM :
-// rText = sal_Unicode(0x2518); break;
- }
-
if ( !mnHalfCharWidth )
mnHalfCharWidth = rInf.GetTextSize( aOutString ).Width() / 2;
@@ -523,12 +591,15 @@ void SwControlCharPortion::Paint( const SwTextPaintInfo &rInf ) const
{
case 0:
aNewPos.AdjustX(deltaX);
+ aNewPos.AdjustY(deltaY);
break;
case 900:
aNewPos.AdjustY(-deltaX);
+ aNewPos.AdjustX(deltaY);
break;
case 2700:
aNewPos.AdjustY(deltaX);
+ aNewPos.AdjustX(-deltaY);
break;
default:
assert(false);
@@ -561,4 +632,13 @@ sal_uInt16 SwControlCharPortion::GetViewWidth( const SwTextSizeInfo& rInf ) cons
return mnViewWidth;
}
+SwLinePortion * SwBookmarkPortion::Unchain()
+{
+ assert(!m_pPrevious || m_pPrevious->GetPortion() == this);
+ m_pPrevious->SetPortion(nullptr);
+ auto const pTmp(m_pPrevious);
+ m_pPrevious = nullptr;
+ return pTmp;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porrst.hxx b/sw/source/core/text/porrst.hxx
index cadd8f871b43..6b930d4f0262 100644
--- a/sw/source/core/text/porrst.hxx
+++ b/sw/source/core/text/porrst.hxx
@@ -18,9 +18,12 @@
*/
#ifndef INCLUDED_SW_SOURCE_CORE_TEXT_PORRST_HXX
#define INCLUDED_SW_SOURCE_CORE_TEXT_PORRST_HXX
+
#include "porlay.hxx"
#include "porexp.hxx"
+class SwFont;
+
#define LINE_BREAK_WIDTH 150
#define SPECIAL_FONT_HEIGHT 200
@@ -122,7 +125,8 @@ class SwControlCharPortion : public SwLinePortion
private:
mutable sal_uInt16 mnViewWidth; // used to cache a calculated value
mutable sal_uInt16 mnHalfCharWidth; // used to cache a calculated value
- sal_Unicode mcChar;
+protected:
+ sal_Unicode const mcChar;
public:
@@ -132,11 +136,35 @@ public:
SetWhichPor( POR_CONTROLCHAR ); SetLen( TextFrameIndex(1) );
}
+ virtual bool DoPaint(SwTextPaintInfo const& rInf,
+ OUString & rOutString, SwFont & rTmpFont, int & rDeltaY) const;
virtual void Paint( const SwTextPaintInfo &rInf ) const override;
virtual bool Format( SwTextFormatInfo &rInf ) override;
virtual sal_uInt16 GetViewWidth( const SwTextSizeInfo& rInf ) const override;
};
+/// for showing bookmark starts and ends; note that in contrast to
+/// SwControlCharPortion these do not have a character in the text.
+class SwBookmarkPortion : public SwControlCharPortion
+{
+private:
+ SwLinePortion * m_pPrevious;
+
+public:
+ explicit SwBookmarkPortion(SwLinePortion *const pPrevious, sal_Unicode const cChar)
+ : SwControlCharPortion(cChar)
+ , m_pPrevious(pPrevious)
+ {
+ SetWhichPor(POR_BOOKMARK);
+ SetLen(TextFrameIndex(0));
+ }
+
+ virtual bool DoPaint(SwTextPaintInfo const& rInf,
+ OUString & rOutString, SwFont & rTmpFont, int & rDeltaY) const override;
+ virtual SwLinePortion * Compress() override { return this; }
+ SwLinePortion * Unchain();
+};
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/xmldump.cxx b/sw/source/core/text/xmldump.cxx
index d29d7abdbd7a..7c4ac4b4b034 100644
--- a/sw/source/core/text/xmldump.cxx
+++ b/sw/source/core/text/xmldump.cxx
@@ -48,6 +48,7 @@ class XmlPortionDumper:public SwPortionHandler
case POR_MULTI: return "POR_MULTI";
case POR_HIDDEN_TXT: return "POR_HIDDEN_TXT";
case POR_CONTROLCHAR: return "POR_CONTROLCHAR";
+ case POR_BOOKMARK: return "POR_BOOKMARK";
case POR_TXT: return "POR_TXT";
case POR_LAY: return "POR_LAY";