diff options
Diffstat (limited to 'sw/source/core/text/pormulti.hxx')
-rw-r--r-- | sw/source/core/text/pormulti.hxx | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/sw/source/core/text/pormulti.hxx b/sw/source/core/text/pormulti.hxx new file mode 100644 index 0000000000..e5a3da2b32 --- /dev/null +++ b/sw/source/core/text/pormulti.hxx @@ -0,0 +1,256 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <memory> +#include "porlay.hxx" +#include <com/sun/star/text/RubyAdjust.hpp> + +class IDocumentSettingAccess; +class SwTextFormatInfo; +class SwTextCursor; +class SwTextPaintInfo; +class SwTextAttr; +class SfxPoolItem; +class SwFont; + +// SwMultiCreator is a small structure to create a multiportion. +// It contains the kind of multiportion and a textattribute +// or a poolitem. +// The GetMultiCreator-function fills this structure and +// the Ctor of the SwMultiPortion uses it. +enum class SwMultiCreatorId +{ + Double, Ruby, Rotate, Bidi +}; + +enum class RubyPosition : sal_uInt16 +{ + ABOVE = 0, + BELOW = 1, + RIGHT = 2 +}; + +struct SwMultiCreator +{ + TextFrameIndex nStartOfAttr; + const SwTextAttr* pAttr; + const SfxPoolItem* pItem; + SwMultiCreatorId nId; + sal_uInt8 nLevel; +}; + +// A two-line-portion (SwMultiPortion) could have surrounding brackets, +// in this case the structure SwBracket will be used. +struct SwBracket +{ + TextFrameIndex nStart; // Start of text attribute determines the font + sal_uInt16 nAscent; // Ascent of the brackets + sal_uInt16 nHeight; // Height of them + sal_uInt16 nPreWidth; // Width of the opening bracket + sal_uInt16 nPostWidth; // Width of the closing bracket + sal_Unicode cPre; // Initial character, e.g. '(' + sal_Unicode cPost; // Final character, e.g. ')' + SwFontScript nPreScript; // Script of the initial character + SwFontScript nPostScript; // Script of the final character +}; + +// The SwMultiPortion is line portion inside a line portion, +// it's a group of portions, +// e.g. a double line portion in a line +// or phonetics (ruby) +// or combined characters +// or a rotated portion. +class SAL_DLLPUBLIC_RTTI SwMultiPortion : public SwLinePortion +{ + SwLineLayout m_aRoot; // One or more lines + bool m_bTab1 :1; // First line tabulator + bool m_bTab2 :1; // Second line includes tabulator + bool m_bDouble :1; // Double line + bool m_bRuby :1; // Phonetics + bool m_bBidi :1; + bool m_bFormatted :1; // Already formatted + bool m_bFollowField :1; // Field follow inside + bool m_bFlyInContent:1; // Fly as character inside + RubyPosition m_eRubyPosition; // Phonetic position + sal_uInt8 m_nDirection:2; // Direction (0/90/180/270 degrees) +protected: + explicit SwMultiPortion(TextFrameIndex const nEnd) + : m_bTab1(false) + , m_bTab2(false) + , m_bDouble(false) + , m_bRuby(false) + , m_bBidi(false) + , m_bFormatted(false) + , m_bFollowField(false) + , m_bFlyInContent(false) + , m_eRubyPosition( RubyPosition::ABOVE ) + , m_nDirection(0) + { + SetWhichPor(PortionType::Multi); + SetLen(nEnd); + } + void SetDouble() { m_bDouble = true; } + void SetRuby() { m_bRuby = true; } + void SetBidi() { m_bBidi = true; } + void SetRubyPosition( RubyPosition eNew ) { m_eRubyPosition = eNew; } + void SetTab1( bool bNew ) { m_bTab1 = bNew; } + void SetTab2( bool bNew ) { m_bTab2 = bNew; } + void SetDirection( sal_uInt8 nNew ) { m_nDirection = nNew; } + bool GetTab1() const { return m_bTab1; } + bool GetTab2() const { return m_bTab2; } +public: + virtual ~SwMultiPortion() override; + const SwLineLayout& GetRoot() const { return m_aRoot; } + SwLineLayout& GetRoot() { return m_aRoot; } + + bool HasTabulator() const { return m_bTab1 || m_bTab2; } + bool IsFormatted() const { return m_bFormatted; } + void SetFormatted() { m_bFormatted = true; } + bool IsFollowField() const { return m_bFollowField; } + void SetFollowField() { m_bFollowField = true; } + bool HasFlyInContent() const { return m_bFlyInContent; } + void SetFlyInContent( bool bNew ) { m_bFlyInContent = bNew; } + bool IsDouble() const { return m_bDouble; } + bool IsRuby() const { return m_bRuby; } + bool IsBidi() const { return m_bBidi; } + bool OnTop() const { return m_eRubyPosition == RubyPosition::ABOVE; } + bool OnRight() const { return m_eRubyPosition == RubyPosition::RIGHT; } + RubyPosition GetRubyPosition() const { return m_eRubyPosition; } + void ActualizeTabulator(); + + virtual void Paint( const SwTextPaintInfo &rInf ) const override; + virtual SwTwips CalcSpacing( tools::Long nSpaceAdd, const SwTextSizeInfo &rInf ) const override; + virtual bool ChgSpaceAdd( SwLineLayout* pCurr, tools::Long nSpaceAdd ) const; + + // Summarize the internal lines to calculate the (external) size + void CalcSize( SwTextFormatter& rLine, SwTextFormatInfo &rInf ); + + inline bool HasBrackets() const; + bool HasRotation() const { return 0 != (1 & m_nDirection); } + bool IsRevers() const { return 0 != (2 & m_nDirection); } + sal_uInt8 GetDirection() const { return m_nDirection; } + + // Accessibility: pass information about this portion to the PortionHandler + virtual void HandlePortion( SwPortionHandler& rPH ) const override; + + void dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, + TextFrameIndex& nOffset) const override; +}; + +class SwDoubleLinePortion : public SwMultiPortion +{ + std::unique_ptr<SwBracket> m_pBracket; // Surrounding brackets + SwTwips m_nLineDiff; // Difference of the width of the both lines + TextFrameIndex m_nBlank1; ///< Number of blanks in the first line + TextFrameIndex m_nBlank2; ///< Number of blanks in the second line +public: + SwDoubleLinePortion(SwDoubleLinePortion& rDouble, TextFrameIndex nEnd); + SwDoubleLinePortion(const SwMultiCreator& rCreate, TextFrameIndex nEnd); + virtual ~SwDoubleLinePortion() override; + + SwBracket* GetBrackets() const { return m_pBracket.get(); } + void SetBrackets( const SwDoubleLinePortion& rDouble ); + void PaintBracket( SwTextPaintInfo& rInf, tools::Long nSpaceAdd, bool bOpen ) const; + void FormatBrackets( SwTextFormatInfo &rInf, SwTwips& nMaxWidth ); + sal_uInt16 PreWidth() const { return m_pBracket->nPreWidth; }; + sal_uInt16 PostWidth() const { return m_pBracket->nPostWidth; } + void ClearBrackets() + { m_pBracket->nPreWidth = m_pBracket->nPostWidth=0; Width( 0 ); } + sal_uInt16 BracketWidth(){ return PreWidth() + PostWidth(); } + + void CalcBlanks( SwTextFormatInfo &rInf ); + static void ResetSpaceAdd( SwLineLayout* pCurr ); + SwTwips GetLineDiff() const { return m_nLineDiff; } + TextFrameIndex GetSpaceCnt() const + { return ( m_nLineDiff < 0 ) ? m_nBlank2 : m_nBlank1; } + TextFrameIndex GetSmallerSpaceCnt() const + { return ( m_nLineDiff < 0 ) ? m_nBlank1 : m_nBlank2; } + + virtual SwTwips CalcSpacing( tools::Long nSpaceAdd, const SwTextSizeInfo &rInf ) const override; + virtual bool ChgSpaceAdd( SwLineLayout* pCurr, tools::Long nSpaceAdd ) const override; +}; + +class SwRubyPortion : public SwMultiPortion +{ + TextFrameIndex m_nRubyOffset; + css::text::RubyAdjust m_nAdjustment; + void Adjust_( SwTextFormatInfo &rInf); +public: + SwRubyPortion(const SwRubyPortion& rRuby, TextFrameIndex nEnd); + + SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt, + const IDocumentSettingAccess& rIDocumentSettingAccess, + TextFrameIndex nEnd, TextFrameIndex nOffs, + const SwTextSizeInfo &rInf ); + + void CalcRubyOffset(); + void Adjust( SwTextFormatInfo &rInf ) + { if(m_nAdjustment != css::text::RubyAdjust_LEFT && GetRoot().GetNext()) Adjust_(rInf); } + css::text::RubyAdjust GetAdjustment() const { return m_nAdjustment; } + TextFrameIndex GetRubyOffset() const { return m_nRubyOffset; } +}; + +class SwRotatedPortion : public SwMultiPortion +{ +public: + SwRotatedPortion(TextFrameIndex const nEnd, sal_uInt8 nDir) + : SwMultiPortion( nEnd ) { SetDirection( nDir ); } + SwRotatedPortion( const SwMultiCreator& rCreate, TextFrameIndex nEnd, + bool bRTL ); +}; + +class SwBidiPortion : public SwMultiPortion +{ + sal_uInt8 m_nLevel; + +public: + SwBidiPortion(TextFrameIndex nEnd, sal_uInt8 nLv); + + sal_uInt8 GetLevel() const { return m_nLevel; } + // Get number of blanks for justified alignment + TextFrameIndex GetSpaceCnt(const SwTextSizeInfo &rInf) const; + // Calculates extra spacing based on number of blanks + virtual SwTwips CalcSpacing( tools::Long nSpaceAdd, const SwTextSizeInfo &rInf ) const override; + // Manipulate the spacing array at pCurr + virtual bool ChgSpaceAdd( SwLineLayout* pCurr, tools::Long nSpaceAdd ) const override; +}; + +// For cursor travelling in multiportions + +class SwTextCursorSave +{ + SwTextCursor* pTextCursor; + SwLineLayout* pCurr; + TextFrameIndex nStart; + sal_uInt16 nWidth; + sal_uInt8 nOldProp; + bool bSpaceChg; +public: + SwTextCursorSave( SwTextCursor* pTextCursor, SwMultiPortion* pMulti, + SwTwips nY, SwTwips& nX, TextFrameIndex nCurrStart, tools::Long nSpaceAdd); + ~SwTextCursorSave(); +}; + +inline bool SwMultiPortion::HasBrackets() const +{ + return IsDouble() && nullptr != static_cast<const SwDoubleLinePortion*>(this)->GetBrackets(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |