summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2015-07-16 02:55:32 +0800
committerMichael Stahl <mstahl@redhat.com>2015-08-27 17:02:29 +0000
commite2be23d1718b363650bf1853d629df89347d906e (patch)
treef0f0e4a1b7857f6630f4bad5ec3dd4cc8f88a3a6 /writerfilter
parent30c2ae28eecb3f1a4454784974c0c2bffc60334e (diff)
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 <ci@libreoffice.org> Reviewed-by: Michael Stahl <mstahl@redhat.com>
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/dmapper/ConversionHelper.cxx26
-rw-r--r--writerfilter/source/dmapper/ConversionHelper.hxx1
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx70
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx77
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx28
-rw-r--r--writerfilter/source/dmapper/PropertyIds.cxx3
-rw-r--r--writerfilter/source/dmapper/PropertyIds.hxx3
-rw-r--r--writerfilter/source/ooxml/model.xml44
8 files changed, 249 insertions, 3 deletions
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 <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/text/HoriOrientation.hpp>
#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/text/RubyAdjust.hpp>
#include <editeng/borderline.hxx>
#include <ooxml/resourceids.hxx>
#include <rtl/ustrbuf.hxx>
@@ -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<int>(len));
aBuffer.append( reinterpret_cast<const sal_Unicode *>(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<SAL_N_ELEMENTS(aRubyAlignValues))?nJc:0];
+ }
+
+ nIndex = rCommand.indexOf("\\* \"Font:" );
+ if (nIndex != -1)
+ {
+ nIndex += 9;
+ aToken = rCommand.getToken(0, '"',nIndex);
+ sFont = aToken;
+ }
+ nIndex = rCommand.indexOf("\\* hps" );
+ if (nIndex != -1)
+ {
+ nIndex += 6;
+ aInfo.nHps = rCommand.getToken(0, ' ',nIndex).toInt32();
+ }
+
+ nIndex = rCommand.indexOf("\\o");
+ if (nIndex != -1 && (nIndex = rCommand.indexOf('(', nIndex)) != -1 && (nEnd = rCommand.lastIndexOf(')'))!=-1 && nEnd > 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<css::text::XTextRange> 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<css::beans::PropertyValue> m_aFrameProperties;
css::uno::Reference<css::text::XTextRange> 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 @@
<ref name="CT_OnOff"/>
</element>
</define>
+ <define name="ST_RubyAlign">
+ <choice>
+ <value>center</value>
+ <value>distributeLetter</value>
+ <value>distributeSpace</value>
+ <value>left</value>
+ <value>right</value>
+ <value>rightVertical</value>
+ </choice>
+ </define>
<define name="CT_RubyAlign">
<attribute name="val">
- <data type="string"/>
+ <ref name="ST_RubyAlign"/>
</attribute>
</define>
<define name="CT_RubyPr">
@@ -17900,6 +17910,7 @@
</resource>
<resource name="CT_R" resource="Stream">
<action name="start" action="startCharacterGroup"/>
+ <action name="start" action="sendPropertiesWithId" tokenid="ooxml:EG_RubyContent_r" sendtokenid="ooxml:EG_RubyContent_r"/>
</resource>
<resource name="ST_Hint" resource="List">
<value tokenid="ooxml:Value_ST_Hint_default">default</value>
@@ -17997,9 +18008,38 @@
<action name="start" action="sendPropertiesWithId" sendtokenid="ooxml:paratrackchange"/>
<action name="start" action="clearProps"/>
</resource>
+ <resource name="ST_RubyAlign" resource="List">
+ <value tokenid="ooxml:Value_ST_RubyAlign_center">center</value>
+ <value tokenid="ooxml:Value_ST_RubyAlign_distributeLetter">distributeLetter</value>
+ <value tokenid="ooxml:Value_ST_RubyAlign_distributeSpace">distributeSpace</value>
+ <value tokenid="ooxml:Value_ST_RubyAlign_left">left</value>
+ <value tokenid="ooxml:Value_ST_RubyAlign_right">right</value>
+ <value tokenid="ooxml:Value_ST_RubyAlign_rightVertical">rightVertical</value>
+ </resource>
<resource name="CT_RubyAlign" resource="Value">
<attribute name="val" tokenid="ooxml:CT_RubyAlign_val" action="setValue"/>
- <action name="start" action="setDefaultStringValue"/>
+ </resource>
+ <resource name="CT_RubyPr" resource="Properties">
+ <element name="rubyAlign" tokenid="ooxml:CT_RubyPr_rubyAlign"/>
+ <element name="hps" tokenid="ooxml:CT_RubyPr_hps"/>
+ <element name="hpsRaise" tokenid="ooxml:CT_RubyPr_hpsRaise"/>
+ <element name="hpsBaseText" tokenid="ooxml:CT_RubyPr_hpsBaseText"/>
+ <element name="lid" tokenid="ooxml:CT_RubyPr_lid"/>
+ <element name="dirty" tokenid="ooxml:CT_RubyPr_dirty"/>
+ <action name="start" action="sendPropertiesWithId" tokenid="ooxml:CT_RubyPr" sendtokenid="ooxml:CT_RubyPr"/>
+ </resource>
+ <resource name="CT_Ruby" resource="Stream">
+ <element name="rubyPr" tokenid="ooxml:CT_RubyPr"/>
+ <element name="rt" tokenid="ooxml:CT_Ruby_rt"/>
+ <element name="rubyBase" tokenid="ooxml:CT_Ruby_rubyBase"/>
+ <action name="start" action="sendPropertiesWithId" tokenid="ooxml:EG_RunInnerContent_ruby" sendtokenid="ooxml:EG_RunInnerContent_ruby"/>
+ </resource>
+ <resource name="CT_RubyContent" resource="Stream">
+ <action name="start" action="sendPropertiesWithId" tokenid="ooxml:CT_Ruby_rt" sendtokenid="ooxml:CT_Ruby_rt"/>
+ <action name="start" action="sendPropertiesWithId" tokenid="ooxml:CT_Ruby_rubyBase" sendtokenid="ooxml:CT_Ruby_rubyBase"/>
+ </resource>
+ <resource name="EG_RubyContent" resource="Stream">
+ <element name="r" tokenid="ooxml:EG_RubyContent_r"/>
</resource>
<resource name="CT_Lock" resource="Value">
<attribute name="val" tokenid="ooxml:CT_Lock_val" action="setValue"/>