summaryrefslogtreecommitdiff
path: root/editeng/source
diff options
context:
space:
mode:
authorJonathan Clark <jonathan@libreoffice.org>2024-11-07 02:23:02 -0700
committerJonathan Clark <jonathan@libreoffice.org>2024-11-13 09:35:20 +0100
commitd3a59f7a915f9cc0864f2c76ccf90b6cd6fea339 (patch)
tree79d370eb7e4e66e6e625c24e2e465c6c624b9ddb /editeng/source
parent510f0837882284d20b49da8ee1f4f909ed54f0b7 (diff)
tdf#36709 sw: Writer layout for font-relative first-line indent
This change implements layout for font-relative paragraph first-line indentation in Writer. Change-Id: Ie8f386bcc13a43ab92d5c15654c24bfdfc62bd69 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176216 Tested-by: Jenkins Reviewed-by: Jonathan Clark <jonathan@libreoffice.org>
Diffstat (limited to 'editeng/source')
-rw-r--r--editeng/source/items/frmitems.cxx175
1 files changed, 135 insertions, 40 deletions
diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx
index 073ad972e9ac..3f11d48057ac 100644
--- a/editeng/source/items/frmitems.cxx
+++ b/editeng/source/items/frmitems.cxx
@@ -75,6 +75,7 @@
#include <o3tl/enumrange.hxx>
#include <o3tl/safeint.hxx>
#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
#include <vcl/GraphicLoader.hxx>
#include <unotools/securityoptions.hxx>
#include <docmodel/uno/UnoComplexColor.hxx>
@@ -496,15 +497,6 @@ void SvxLRSpaceItem::SetRight(const tools::Long nR, const sal_uInt16 nProp)
nPropRightMargin = nProp;
}
-void SvxFirstLineIndentItem::SetTextFirstLineOffset(
- const short nF, const sal_uInt16 nProp)
-{
- ASSERT_CHANGE_REFCOUNTED_ITEM;
- m_nFirstLineOffset = short((tools::Long(nF) * nProp ) / 100);
- m_nUnit = css::util::MeasureUnit::TWIP;
- m_nPropFirstLineOffset = nProp;
-}
-
void SvxLRSpaceItem::SetTextFirstLineOffset(const short nF, const sal_uInt16 nProp)
{
// note: left margin contains any negative first line offset - preserve it!
@@ -561,12 +553,17 @@ tools::Long SvxTextLeftMarginItem::GetTextLeft() const
return m_nTextLeftMargin;
}
-tools::Long SvxTextLeftMarginItem::GetLeft(SvxFirstLineIndentItem const& rFirstLine) const
+tools::Long SvxTextLeftMarginItem::GetLeft(const SvxFirstLineIndentItem& rFirstLine,
+ const SvxFontUnitMetrics& rMetrics) const
{
// add any negative first line offset to text left margin to get left
- return (rFirstLine.GetTextFirstLineOffset() < 0)
- ? m_nTextLeftMargin + rFirstLine.GetTextFirstLineOffset()
- : m_nTextLeftMargin;
+ if (rFirstLine.GetTextFirstLineOffsetValue() < 0.0)
+ {
+ auto nFirstLineOffset = rFirstLine.ResolveTextFirstLineOffset(rMetrics);
+ return m_nTextLeftMargin + nFirstLineOffset;
+ }
+
+ return m_nTextLeftMargin;
}
tools::Long SvxLRSpaceItem::GetTextLeft() const
@@ -938,10 +935,76 @@ SvxFirstLineIndentItem::SvxFirstLineIndentItem(const sal_uInt16 nId)
{
}
-SvxFirstLineIndentItem::SvxFirstLineIndentItem(const short nFirst, const sal_uInt16 nId)
- : SfxPoolItem(nId, SfxItemType::SvxFirstLineIndentItemType)
- , m_nFirstLineOffset(nFirst)
+SvxFirstLineIndentItem::SvxFirstLineIndentItem(double dValue, sal_uInt16 nUnit,
+ const sal_uInt16 nId)
+ : SvxFirstLineIndentItem(nId)
+{
+ SetTextFirstLineOffset(dValue, nUnit);
+}
+
+bool SvxFirstLineIndentItem::IsAutoFirst() const { return m_bAutoFirst; }
+
+void SvxFirstLineIndentItem::SetAutoFirst(bool bNew)
+{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ m_bAutoFirst = bNew;
+}
+
+void SvxFirstLineIndentItem::SetPropTextFirstLineOffset(sal_uInt16 nProp)
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ m_nPropFirstLineOffset = nProp;
+}
+
+sal_uInt16 SvxFirstLineIndentItem::GetPropTextFirstLineOffset() const
+{
+ return m_nPropFirstLineOffset;
+}
+
+void SvxFirstLineIndentItem::SetTextFirstLineOffset(double dValue, sal_Int16 nUnit,
+ sal_uInt16 nProp)
+{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ m_dFirstLineOffset = dValue;
+ m_nUnit = nUnit;
+ m_nPropFirstLineOffset = nProp;
+
+ if (nProp != 100)
+ {
+ m_dFirstLineOffset = (dValue * static_cast<double>(nProp)) / 100.0;
+ }
+}
+
+double SvxFirstLineIndentItem::GetTextFirstLineOffsetValue() const { return m_dFirstLineOffset; }
+
+sal_Int16 SvxFirstLineIndentItem::GetTextFirstLineOffsetUnit() const { return m_nUnit; }
+
+double
+SvxFirstLineIndentItem::ResolveTextFirstLineOffsetDouble(const SvxFontUnitMetrics& rMetrics) const
+{
+ if(m_nUnit == css::util::MeasureUnit::TWIP)
+ return m_dFirstLineOffset;
+
+ SAL_WARN_IF(!rMetrics.m_bInitialized, "editeng", "font-relative indentation lost");
+
+ switch (m_nUnit)
+ {
+ case css::util::MeasureUnit::FONT_EM:
+ return m_dFirstLineOffset * rMetrics.m_dEmTwips;
+
+ case css::util::MeasureUnit::FONT_CJK_ADVANCE:
+ return m_dFirstLineOffset * rMetrics.m_dIcTwips;
+
+ default:
+ SAL_WARN("editeng", "unhandled type conversion");
+ return 0.0;
+ }
+}
+
+sal_Int32
+SvxFirstLineIndentItem::ResolveTextFirstLineOffset(const SvxFontUnitMetrics& rMetrics) const
+{
+ return static_cast<sal_Int32>(std::llround(ResolveTextFirstLineOffsetDouble(rMetrics)));
}
bool SvxFirstLineIndentItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) const
@@ -956,8 +1019,9 @@ bool SvxFirstLineIndentItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) con
// In practice, these are always stored here in twips.
if (m_nUnit == css::util::MeasureUnit::TWIP)
{
- rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(m_nFirstLineOffset)
- : m_nFirstLineOffset);
+ auto nConvOffset
+ = (bConvert ? convertTwipToMm100(m_dFirstLineOffset) : m_dFirstLineOffset);
+ rVal <<= static_cast<sal_Int32>(std::llround(nConvOffset));
bRet = true;
}
break;
@@ -973,9 +1037,7 @@ bool SvxFirstLineIndentItem::QueryValue(uno::Any& rVal, sal_uInt8 nMemberId) con
// units (e.g. em, ic), and all other units will be pre-converted to twips.
if (m_nUnit != css::util::MeasureUnit::TWIP)
{
- rVal <<= css::beans::Pair<double, sal_Int16>{
- static_cast<double>(m_nFirstLineOffset), m_nUnit
- };
+ rVal <<= css::beans::Pair<double, sal_Int16>{ m_dFirstLineOffset, m_nUnit };
bRet = true;
}
break;
@@ -1009,7 +1071,8 @@ bool SvxFirstLineIndentItem::PutValue(const uno::Any& rVal, sal_uInt8 nMemberId)
{
return false;
}
- m_nFirstLineOffset = bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal;
+
+ m_dFirstLineOffset = bConvert ? o3tl::toTwips(nVal, o3tl::Length::mm100) : nVal;
m_nUnit = css::util::MeasureUnit::TWIP;
m_nPropFirstLineOffset = 100;
break;
@@ -1035,7 +1098,7 @@ bool SvxFirstLineIndentItem::PutValue(const uno::Any& rVal, sal_uInt8 nMemberId)
return false;
}
- m_nFirstLineOffset = stVal.First;
+ m_dFirstLineOffset = stVal.First;
m_nUnit = stVal.Second;
m_nPropFirstLineOffset = 100;
break;
@@ -1057,16 +1120,15 @@ bool SvxFirstLineIndentItem::operator==(const SfxPoolItem& rAttr) const
const SvxFirstLineIndentItem& rOther = static_cast<const SvxFirstLineIndentItem&>(rAttr);
- return (m_nFirstLineOffset == rOther.GetTextFirstLineOffset()
- && m_nUnit == rOther.GetTextFirstLineOffsetUnit()
- && m_nPropFirstLineOffset == rOther.GetPropTextFirstLineOffset()
- && m_bAutoFirst == rOther.IsAutoFirst());
+ return std::tie(m_dFirstLineOffset, m_nUnit, m_nPropFirstLineOffset, m_bAutoFirst)
+ == std::tie(rOther.m_dFirstLineOffset, rOther.m_nUnit, rOther.m_nPropFirstLineOffset,
+ rOther.m_bAutoFirst);
}
size_t SvxFirstLineIndentItem::hashCode() const
{
std::size_t seed(0);
- o3tl::hash_combine(seed, m_nFirstLineOffset);
+ o3tl::hash_combine(seed, m_dFirstLineOffset);
o3tl::hash_combine(seed, m_nUnit);
o3tl::hash_combine(seed, m_nPropFirstLineOffset);
o3tl::hash_combine(seed, m_bAutoFirst);
@@ -1095,10 +1157,15 @@ bool SvxFirstLineIndentItem::GetPresentation
rText += unicode::formatPercent(m_nPropFirstLineOffset,
Application::GetSettings().GetUILanguageTag());
}
+ else if (m_nUnit != css::util::MeasureUnit::TWIP)
+ {
+ OUStringBuffer stBuf;
+ sax::Converter::convertMeasureUnit(stBuf, m_dFirstLineOffset, m_nUnit);
+ rText += stBuf.makeStringAndClear();
+ }
else
{
- rText += GetMetricText(static_cast<tools::Long>(m_nFirstLineOffset),
- eCoreUnit, ePresUnit, &rIntl);
+ rText += GetMetricText(m_dFirstLineOffset, eCoreUnit, ePresUnit, &rIntl);
}
return true;
}
@@ -1110,11 +1177,16 @@ bool SvxFirstLineIndentItem::GetPresentation
rText += unicode::formatPercent(m_nPropFirstLineOffset,
Application::GetSettings().GetUILanguageTag());
}
+ else if (m_nUnit != css::util::MeasureUnit::TWIP)
+ {
+ OUStringBuffer stBuf;
+ sax::Converter::convertMeasureUnit(stBuf, m_dFirstLineOffset, m_nUnit);
+ rText += stBuf.makeStringAndClear();
+ }
else
{
- rText += GetMetricText(static_cast<tools::Long>(m_nFirstLineOffset),
- eCoreUnit, ePresUnit, &rIntl)
- + " " + EditResId(GetMetricId(ePresUnit));
+ rText += GetMetricText(m_dFirstLineOffset, eCoreUnit, ePresUnit, &rIntl) + " "
+ + EditResId(GetMetricId(ePresUnit));
}
return true;
}
@@ -1126,7 +1198,8 @@ bool SvxFirstLineIndentItem::GetPresentation
void SvxFirstLineIndentItem::ScaleMetrics(tools::Long const nMult, tools::Long const nDiv)
{
ASSERT_CHANGE_REFCOUNTED_ITEM;
- m_nFirstLineOffset = static_cast<short>(BigInt::Scale(m_nFirstLineOffset, nMult, nDiv));
+ m_dFirstLineOffset
+ = (m_dFirstLineOffset * static_cast<double>(nMult)) / static_cast<double>(nDiv);
}
bool SvxFirstLineIndentItem::HasMetrics() const
@@ -1138,7 +1211,8 @@ void SvxFirstLineIndentItem::dumpAsXml(xmlTextWriterPtr pWriter) const
{
(void)xmlTextWriterStartElement(pWriter, BAD_CAST("SvxFirstLineIndentItem"));
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
- (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nFirstLineOffset"), BAD_CAST(OString::number(m_nFirstLineOffset).getStr()));
+ (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_dFirstLineOffset"),
+ BAD_CAST(OString::number(m_dFirstLineOffset).getStr()));
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nUnit"), BAD_CAST(OString::number(m_nUnit).getStr()));
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nPropFirstLineOffset"), BAD_CAST(OString::number(m_nPropFirstLineOffset).getStr()));
(void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_bAutoFirst"), BAD_CAST(OString::number(int(m_bAutoFirst)).getStr()));
@@ -1151,13 +1225,34 @@ boost::property_tree::ptree SvxFirstLineIndentItem::dumpAsJSON() const
boost::property_tree::ptree aState;
- MapUnit eTargetUnit = MapUnit::MapInch;
+ switch (m_nUnit)
+ {
+ case css::util::MeasureUnit::TWIP:
+ {
+ MapUnit eTargetUnit = MapUnit::MapInch;
- OUString sFirstline = GetMetricText(GetTextFirstLineOffset(),
- MapUnit::MapTwip, eTargetUnit, nullptr);
+ OUString sFirstline
+ = GetMetricText(m_dFirstLineOffset, MapUnit::MapTwip, eTargetUnit, nullptr);
- aState.put("firstline", sFirstline);
- aState.put("unit", "inch");
+ aState.put("firstline", sFirstline);
+ aState.put("unit", "inch");
+ }
+ break;
+
+ case css::util::MeasureUnit::FONT_EM:
+ aState.put("firstline", m_dFirstLineOffset);
+ aState.put("unit", "em");
+ break;
+
+ case css::util::MeasureUnit::FONT_CJK_ADVANCE:
+ aState.put("firstline", m_dFirstLineOffset);
+ aState.put("unit", "ic");
+ break;
+
+ default:
+ SAL_WARN("editeng", "unhandled type conversion");
+ break;
+ }
aTree.push_back(std::make_pair("state", aState));