From e2be23d1718b363650bf1853d629df89347d906e Mon Sep 17 00:00:00 2001 From: Mark Hung Date: Thu, 16 Jul 2015 02:55:32 +0800 Subject: Improving Asian phonetic guide for docx and rtf files. RTF import, export, and ooxml export for ruby text are implemented. tdf#49073 - FILEOPEN: Furigana (ruby text) and characters with them are missing in opened .docx files. tdf#50786 - [TASK, METABUG] FILEOPEN, FILESAVE, FORMATTING : Japanese ruby-character handling is broken Change-Id: I4a5c30bad180241e3344e9da7efe7da4369fb325 Reviewed-on: https://gerrit.libreoffice.org/17241 Tested-by: Jenkins Reviewed-by: Michael Stahl --- writerfilter/source/dmapper/ConversionHelper.cxx | 26 ++++++++ writerfilter/source/dmapper/ConversionHelper.hxx | 1 + writerfilter/source/dmapper/DomainMapper.cxx | 70 ++++++++++++++++++++- writerfilter/source/dmapper/DomainMapper_Impl.cxx | 77 +++++++++++++++++++++++ writerfilter/source/dmapper/DomainMapper_Impl.hxx | 28 +++++++++ writerfilter/source/dmapper/PropertyIds.cxx | 3 + writerfilter/source/dmapper/PropertyIds.hxx | 3 + writerfilter/source/ooxml/model.xml | 44 ++++++++++++- 8 files changed, 249 insertions(+), 3 deletions(-) (limited to 'writerfilter') diff --git a/writerfilter/source/dmapper/ConversionHelper.cxx b/writerfilter/source/dmapper/ConversionHelper.cxx index 77f935c80829..e64c091e30ae 100644 --- a/writerfilter/source/dmapper/ConversionHelper.cxx +++ b/writerfilter/source/dmapper/ConversionHelper.cxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -423,6 +424,31 @@ sal_uInt32 convertTwipToMM100Unsigned(sal_Int32 _t) return convertTwipToMM100( _t ); } +sal_Int16 convertRubyAlign( sal_Int32 nIntValue ) +{ + sal_Int16 rubyAdjust = text::RubyAdjust_LEFT; + switch( nIntValue ) + { + case NS_ooxml::LN_Value_ST_RubyAlign_center: + case NS_ooxml::LN_Value_ST_RubyAlign_rightVertical: + rubyAdjust = text::RubyAdjust_CENTER; + break; + case NS_ooxml::LN_Value_ST_RubyAlign_distributeLetter: + rubyAdjust = text::RubyAdjust_BLOCK; + break; + case NS_ooxml::LN_Value_ST_RubyAlign_distributeSpace: + rubyAdjust = text::RubyAdjust_INDENT_BLOCK; + break; + case NS_ooxml::LN_Value_ST_RubyAlign_left: + rubyAdjust = text::RubyAdjust_LEFT; + break; + case NS_ooxml::LN_Value_ST_RubyAlign_right: + rubyAdjust = text::RubyAdjust_RIGHT; + break; + } + return rubyAdjust; +} + sal_Int16 convertTableJustification( sal_Int32 nIntValue ) { sal_Int16 nOrient = text::HoriOrientation::LEFT_AND_WIDTH; diff --git a/writerfilter/source/dmapper/ConversionHelper.hxx b/writerfilter/source/dmapper/ConversionHelper.hxx index b9067759410d..faf5c27d234a 100644 --- a/writerfilter/source/dmapper/ConversionHelper.hxx +++ b/writerfilter/source/dmapper/ConversionHelper.hxx @@ -47,6 +47,7 @@ namespace ConversionHelper{ SAL_DLLPUBLIC_EXPORT sal_Int32 convertTwipToMM100(sal_Int32 _t); SAL_DLLPUBLIC_EXPORT sal_uInt32 convertTwipToMM100Unsigned(sal_Int32 _t); sal_Int16 convertTableJustification( sal_Int32 nIntValue ); + sal_Int16 convertRubyAlign( sal_Int32 nIntValue ); sal_Int16 ConvertNumberingType(sal_Int32 nFmt); css::util::DateTime ConvertDateStringToDateTime(const OUString& rDateTime); diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 267dc54a874a..a27bf85f5deb 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1560,7 +1560,18 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, PropertyMapPtr rContext ) else { bool bIgnore = false; - if (m_pImpl->m_bInTableStyleRunProps) + const RubyInfo &aInfo = m_pImpl->GetRubyInfo(); + if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rt && aInfo.nHps > 0 ) + { + fVal = double(aInfo.nHps) / 2.; + aVal = uno::makeAny( fVal ); + } + else if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rubyBase && aInfo.nHpsBaseText > 0 ) + { + fVal = double(aInfo.nHpsBaseText) / 2.; + aVal = uno::makeAny( fVal ); + } + else if (m_pImpl->m_bInTableStyleRunProps) { // If the default para style contains PROP_CHAR_HEIGHT, that should have priority over the table style. StyleSheetEntryPtr pTable = m_pImpl->GetStyleSheetTable()->FindDefaultParaStyle(); @@ -2544,6 +2555,54 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, PropertyMapPtr rContext ) } } break; + case NS_ooxml::LN_EG_RunInnerContent_ruby: + { + RubyInfo aInfo ; + m_pImpl->SetRubyInfo(aInfo); + } + case NS_ooxml::LN_CT_RubyPr: + case NS_ooxml::LN_CT_Ruby_rt: + case NS_ooxml::LN_CT_Ruby_rubyBase: + { + m_pImpl->SetRubySprmId(nSprmId); + if (nSprmId == NS_ooxml::LN_CT_RubyPr) + { + resolveSprmProps(*this, rSprm); + } + } + break; + case NS_ooxml::LN_EG_RubyContent_r: + { + const RubyInfo & aInfo = m_pImpl->GetRubyInfo(); + if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rubyBase) + { + rContext->Insert(PROP_RUBY_TEXT, uno::makeAny(aInfo.sRubyText)); + rContext->Insert(PROP_RUBY_STYLE, uno::makeAny(aInfo.sRubyStyle)); + rContext->Insert(PROP_RUBY_ADJUST, uno::makeAny(ConversionHelper::convertRubyAlign(aInfo.nRubyAlign))); + m_pImpl->SetRubySprmId(0); + } + } + break; + case NS_ooxml::LN_CT_RubyPr_rubyAlign: + case NS_ooxml::LN_CT_RubyPr_hps: + case NS_ooxml::LN_CT_RubyPr_hpsBaseText: + { + RubyInfo aInfo = m_pImpl->GetRubyInfo(); + switch(nSprmId) + { + case NS_ooxml::LN_CT_RubyPr_rubyAlign: + aInfo.nRubyAlign = nIntValue; + break; + case NS_ooxml::LN_CT_RubyPr_hps: + aInfo.nHps= nIntValue; + break; + case NS_ooxml::LN_CT_RubyPr_hpsBaseText: + aInfo.nHpsBaseText = nIntValue; + break; + } + m_pImpl->SetRubyInfo(aInfo); + } + break; default: { #ifdef DEBUG_WRITERFILTER @@ -2954,6 +3013,15 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len) OUStringBuffer aBuffer = OUStringBuffer(sal::static_int_cast(len)); aBuffer.append( reinterpret_cast(data_), len); sText = aBuffer.makeStringAndClear(); + const RubyInfo & aInfo = m_pImpl->GetRubyInfo(); + if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rt) + { + PropertyMapPtr pContext = m_pImpl->GetTopContext(); + PropertyValueVector_t aProps = comphelper::sequenceToContainer< PropertyValueVector_t >(pContext->GetPropertyValues()); + OUString sStyle = getOrCreateCharStyle(aProps); + m_pImpl->SetRubyText(sText,sStyle); + return; + } if (m_pImpl->isSdtEndDeferred()) { diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 3f0e6a3472f0..c47584e77173 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -2929,6 +2929,79 @@ void DomainMapper_Impl::handleFieldAsk } } + +void DomainMapper_Impl::handleRubyEQField( FieldContextPtr pContext) +{ + const OUString & rCommand(pContext->GetCommand()); + sal_Int32 nIndex = 0, nEnd = 0; + OUString aToken ,sFont; + RubyInfo aInfo ; + nIndex = rCommand.indexOf("\\* jc" ); + if (nIndex != -1) + { + nIndex += 5; + sal_uInt32 nJc = rCommand.getToken(0, ' ',nIndex).toInt32(); + const sal_Int32 aRubyAlignValues[] = + { + NS_ooxml::LN_Value_ST_RubyAlign_center, + NS_ooxml::LN_Value_ST_RubyAlign_distributeLetter, + NS_ooxml::LN_Value_ST_RubyAlign_distributeSpace, + NS_ooxml::LN_Value_ST_RubyAlign_left, + NS_ooxml::LN_Value_ST_RubyAlign_right, + NS_ooxml::LN_Value_ST_RubyAlign_rightVertical, + }; + aInfo.nRubyAlign = aRubyAlignValues[(nJc nIndex) + { + OUString sRubyParts = rCommand.copy(nIndex+1,nEnd-nIndex-1); + nIndex = 0; + OUString sPart1 = sRubyParts.getToken(0, ',', nIndex); + OUString sPart2 = sRubyParts.getToken(0, ',', nIndex); + if ((nIndex = sPart1.indexOf('(', 0)) != -1 && (nEnd = sPart1.lastIndexOf(')'))!=-1 ) + { + aInfo.sRubyText = sPart1.copy(nIndex+1,nEnd-nIndex-1); + } + + PropertyMapPtr pRubyContext(new PropertyMap()); + pRubyContext->InsertProps(GetTopContext()); + if (aInfo.nHps > 0) + { + double fVal = double(aInfo.nHps) / 2.; + uno::Any aVal = uno::makeAny( fVal ); + + pRubyContext->Insert(PROP_CHAR_HEIGHT, aVal); + pRubyContext->Insert(PROP_CHAR_HEIGHT_ASIAN, aVal); + } + PropertyValueVector_t aProps = comphelper::sequenceToContainer< PropertyValueVector_t >(pRubyContext->GetPropertyValues()); + aInfo.sRubyStyle = m_rDMapper.getOrCreateCharStyle(aProps); + PropertyMapPtr pCharContext(new PropertyMap()); + if (m_pLastCharacterContext.get()) + pCharContext->InsertProps(m_pLastCharacterContext); + pCharContext->InsertProps(pContext->getProperties()); + pCharContext->Insert(PROP_RUBY_TEXT, uno::makeAny( aInfo.sRubyText ) ); + pCharContext->Insert(PROP_RUBY_ADJUST, uno::makeAny(ConversionHelper::convertRubyAlign(aInfo.nRubyAlign))); + pCharContext->Insert(PROP_RUBY_STYLE, uno::makeAny(aInfo.sRubyStyle)); + appendTextPortion(sPart2, pCharContext); + } +} + void DomainMapper_Impl::handleAutoNum (FieldContextPtr pContext, uno::Reference< uno::XInterface > & xFieldInterface, @@ -3677,6 +3750,10 @@ void DomainMapper_Impl::CloseFieldCommand() } } } + else if (aCommand.startsWith("\\* jc")) + { + handleRubyEQField(pContext); + } } } break; diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 8dc1856f6ceb..55d059da7af3 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -267,6 +267,24 @@ struct AnnotationPosition css::uno::Reference m_xEnd; }; +struct RubyInfo +{ + OUString sRubyText; + OUString sRubyStyle; + sal_uInt32 nSprmId; + sal_uInt32 nRubyAlign; + sal_uInt32 nHps; + sal_uInt32 nHpsBaseText; + + RubyInfo(): + nSprmId(0), + nRubyAlign(0), + nHps(0), + nHpsBaseText(0) + { + } +}; + struct LineNumberSettings { bool bIsOn; @@ -399,6 +417,7 @@ private: bool m_bIsInFootnoteProperties; bool m_bIsCustomFtnMark; + RubyInfo m_aRubyInfo; //registered frame properties std::vector m_aFrameProperties; css::uno::Reference m_xFrameStartRange; @@ -488,6 +507,14 @@ public: void RemoveLastParagraph( ); void SetIsLastParagraphInSection( bool bIsLast ); bool GetIsLastParagraphInSection() { return m_bIsLastParaInSection;} + void SetRubySprmId( sal_uInt32 nSprmId) { m_aRubyInfo.nSprmId = nSprmId ; } + void SetRubyText( OUString &sText,OUString &sStyle) { + m_aRubyInfo.sRubyText = sText; + m_aRubyInfo.sRubyStyle = sStyle; + } + const RubyInfo & GetRubyInfo() const { return m_aRubyInfo;} + void SetRubyInfo(const RubyInfo & rInfo) { m_aRubyInfo = rInfo;} + void SetIsLastSectionGroup( bool bIsLast ); bool GetIsLastSectionGroup() { return m_bIsLastSectionGroup;} void SetIsFirstParagraphInSection( bool bIsFirst ); @@ -620,6 +647,7 @@ public: void SetFieldLocked(); //collect the pieces of the command void AppendFieldCommand(OUString& rPartOfCommand); + void handleRubyEQField( FieldContextPtr pContext); void handleFieldAsk (FieldContextPtr pContext, css::uno::Reference< css::uno::XInterface > & xFieldInterface, diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx index 5bf3715ed799..e8b85d745432 100644 --- a/writerfilter/source/dmapper/PropertyIds.cxx +++ b/writerfilter/source/dmapper/PropertyIds.cxx @@ -379,6 +379,9 @@ OUString getPropertyName( PropertyIds eId ) case PROP_FILL_COLOR: sName = "FillColor"; break; case PROP_SNAP_TO_GRID: sName = "SnapToGrid"; break; case PROP_GRID_SNAP_TO_CHARS: sName = "GridSnapToChars"; break; + case PROP_RUBY_STYLE: sName = "RubyCharStyleName"; break; + case PROP_RUBY_TEXT: sName = "RubyText"; break; + case PROP_RUBY_ADJUST: sName = "RubyAdjust"; break; } assert(sName.getLength()>0); return sName; diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx index 89feb8c03a48..75a2a9b70ca0 100644 --- a/writerfilter/source/dmapper/PropertyIds.hxx +++ b/writerfilter/source/dmapper/PropertyIds.hxx @@ -377,6 +377,9 @@ enum PropertyIds ,PROP_FILL_COLOR ,PROP_SNAP_TO_GRID ,PROP_GRID_SNAP_TO_CHARS + ,PROP_RUBY_STYLE + ,PROP_RUBY_TEXT + ,PROP_RUBY_ADJUST }; //Returns the UNO string equivalent to eId. diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 860655eaa320..260aa3dfac2c 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -13706,9 +13706,19 @@ + + + center + distributeLetter + distributeSpace + left + right + rightVertical + + - + @@ -17900,6 +17910,7 @@ + default @@ -17997,9 +18008,38 @@ + + center + distributeLetter + distributeSpace + left + right + rightVertical + - + + + + + + + + + + + + + + + + + + + + + + -- cgit