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-01-30 14:36:32 +0100
commit4ce8120f1e53f7b81e653b01d141643013bc69ab (patch)
treeaf0373eb2c4107b776961d2236b66c87bbd3d30d
parent8029179e35fcda5867769d4ca6f7ee32bca3e9bc (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. Change-Id: I1ab94afb417221e278dbb3afd6c978a05fc78497 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>
-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
-rw-r--r--sw/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.hxx26
-rw-r--r--sw/source/core/text/xmldump.cxx1
14 files changed, 262 insertions, 26 deletions
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index a9edd2b66eb1..fb6fbde35536 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -318,8 +318,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", "PortionType::Bookmark");
+ assertXPath(pXmlDoc, "/root/page/body/txt/Special[2]", "nHeight", "253");
+ assertXPath(pXmlDoc, "/root/page/body/txt/Special[3]", "nType", "PortionType::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 00cabbe14eba..b929bc54b5ac 100644
--- a/sw/source/core/access/accportions.cxx
+++ b/sw/source/core/access/accportions.cxx
@@ -170,6 +170,9 @@ void SwAccessiblePortionData::Special(
case PortionType::ControlChar:
sDisplay = rText + OUStringChar(m_pTextFrame->GetText()[sal_Int32(m_nViewPosition)]);
break;
+ case PortionType::Bookmark:
+ // TODO
+ break;
default:
sDisplay = rText;
break;
diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
index 6d7ad0f4dfff..bb91dedea1a7 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -24,6 +24,7 @@
#include <deque>
#include <unordered_set>
#include <rtl/ustrbuf.hxx>
+#include <o3tl/typed_flags_set.hxx>
#include <i18nlangtag/lang.h>
#include "TextFrameIndex.hxx"
@@ -42,7 +43,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:
}
TextFrameIndex NextHiddenChg(TextFrameIndex nPos) const;
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 2030fff25cc5..16f433e3b0b2 100644
--- a/sw/source/core/inc/txttypes.hxx
+++ b/sw/source/core/inc/txttypes.hxx
@@ -33,6 +33,7 @@ enum class PortionType
Multi = 0x0085,
HiddenText = 0x0086,
ControlChar = 0x0087,
+ Bookmark = 0x0088,
Text = 0x8000,
Lay = 0x8001,
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index 83e8bde03ad3..8538d6ebabd4 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -1375,6 +1375,14 @@ void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
bDraw = true;
}
break;
+ case PortionType::Bookmark:
+ if (!GetOpt().IsPagePreview()
+ && !GetOpt().IsReadonly()
+ && GetOpt().IsViewMetaChars())
+ {
+ bDraw = true;
+ }
+ break;
case PortionType::InputField:
// input field shading also in read-only mode
if ( !GetOpt().IsPagePreview()
@@ -1582,6 +1590,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()));
@@ -2007,4 +2016,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 30888843626d..63d030e896e9 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -477,6 +477,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
@@ -636,6 +637,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 3285f7f5ede9..6edf7e055184 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -691,6 +691,10 @@ void SwTextFormatter::BuildPortions( SwTextFormatInfo &rInf )
CalcAscent( rInf, pPor );
InsertPortion( rInf, pPor );
+ if (pPor->IsMultiPortion() && (!m_pMulti || m_pMulti->IsBidi()))
+ {
+ (void) rInf.CheckCurrentPosBookmark(); // bookmark was already created inside MultiPortion!
+ }
pPor = NewPortion( rInf );
}
@@ -753,6 +757,19 @@ void SwTextFormatter::CalcAscent( SwTextFormatInfo &rInf, SwLinePortion *pPor )
pPor->Height( pLast->Height() );
pPor->SetAscent( pLast->GetAscent() );
}
+ else if (pPor->GetWhichPor() == PortionType::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();
@@ -1012,6 +1029,7 @@ SwTextPortion *SwTextFormatter::NewTextPortion( SwTextFormatInfo &rInf )
return pPor;
}
+// first portions have no length
SwLinePortion *SwTextFormatter::WhichFirstPortion(SwTextFormatInfo &rInf)
{
SwLinePortion *pPor = nullptr;
@@ -1144,6 +1162,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 aa0bbf6860c3..9fa74a0d4833 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -1686,6 +1686,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 b5adccb07fba..3d5cb26aa4be 100644
--- a/sw/source/core/text/porlin.cxx
+++ b/sw/source/core/text/porlin.cxx
@@ -103,7 +103,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 3fe08cbacba4..ca7bc1a34fe1 100644
--- a/sw/source/core/text/porlin.hxx
+++ b/sw/source/core/text/porlin.hxx
@@ -133,7 +133,7 @@ public:
bool IsArrowPortion() const { return nWhichPor == PortionType::Arrow; }
bool IsMultiPortion() const { return nWhichPor == PortionType::Multi; }
bool IsNumberPortion() const { return nWhichPor == PortionType::Number; } // #i23726#
- bool IsControlCharPortion() const { return nWhichPor == PortionType::ControlChar; }
+ bool IsControlCharPortion() const { return nWhichPor == PortionType::ControlChar || nWhichPor == PortionType::Bookmark; }
// Positioning
SwLinePortion *FindPrevPortion( const SwLinePortion *pRoot );
diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 1ef0c04efd86..5e991cc4bed3 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -38,6 +38,7 @@
#include "itrform2.hxx"
#include "porfld.hxx"
#include "porglue.hxx"
+#include "porrst.hxx"
#include <pagefrm.hxx>
#include <rowfrm.hxx>
#include <tgrditem.hxx>
@@ -2029,6 +2030,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() == PortionType::Bookmark)
+ {
+ auto const pBookmark(static_cast<SwBookmarkPortion*>(rInf.GetLast()));
+ rInf.SetLast(pBookmark->Unchain());
+ assert(m_pCurr->GetNextPortion() == nullptr);
+ m_pCurr->SetNextPortion(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 686959609cd8..44d2288eaf9c 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -306,6 +306,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() &&
@@ -488,35 +499,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 = OUStringChar(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, PortionType::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;
@@ -527,12 +595,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);
@@ -565,4 +636,13 @@ sal_uInt16 SwControlCharPortion::GetViewWidth( const SwTextSizeInfo& rInf ) cons
return mnViewWidth;
}
+SwLinePortion * SwBookmarkPortion::Unchain()
+{
+ assert(!m_pPrevious || m_pPrevious->GetNextPortion() == this);
+ m_pPrevious->SetNextPortion(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 85e85d1570dd..dcb2cfcae7e9 100644
--- a/sw/source/core/text/porrst.hxx
+++ b/sw/source/core/text/porrst.hxx
@@ -31,6 +31,7 @@
class SwPortionHandler;
class SwTextPaintInfo;
class SwTextSizeInfo;
+class SwFont;
#define LINE_BREAK_WIDTH 150
#define SPECIAL_FONT_HEIGHT 200
@@ -133,6 +134,7 @@ 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
+protected:
sal_Unicode const mcChar;
public:
@@ -143,11 +145,35 @@ public:
SetWhichPor( PortionType::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(PortionType::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 510615b08a1f..3db640cb4774 100644
--- a/sw/source/core/text/xmldump.cxx
+++ b/sw/source/core/text/xmldump.cxx
@@ -52,6 +52,7 @@ class XmlPortionDumper:public SwPortionHandler
case PortionType::Multi: return "PortionType::Multi";
case PortionType::HiddenText: return "PortionType::HiddenText";
case PortionType::ControlChar: return "PortionType::ControlChar";
+ case PortionType::Bookmark: return "PortionType::Bookmark";
case PortionType::Text: return "PortionType::Text";
case PortionType::Lay: return "PortionType::Lay";