From 303de7dab65105eff48307a94410c3d6e72e2a61 Mon Sep 17 00:00:00 2001 From: Sergey Vladimirov Date: Mon, 5 Nov 2012 15:51:41 +0000 Subject: [PATCH] fix bug 53182 - Reading combined character styling and direct formatting of a character run git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1405850 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 1 + .../src/org/apache/poi/hwpf/model/CHPX.java | 5 +- .../hwpf/sprm/CharacterSprmUncompressor.java | 120 ++++++++++++------ .../hwpf/usermodel/CharacterProperties.java | 34 +++-- .../poi/hwpf/usermodel/CharacterRun.java | 24 ++-- .../converter/TestWordToHtmlConverter.java | 8 +- test-data/document/Bug53182.doc | Bin 0 -> 19968 bytes 7 files changed, 125 insertions(+), 67 deletions(-) create mode 100644 test-data/document/Bug53182.doc diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index bfbabdf77b..4a76471aee 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 53182 - Reading combined character styling and direct formatting of a character run 52311 - Conversion to html : Problem in titles number 53914 - TableRow#getTopBorder() return bottom's border 53282 - Avoid exception when parsing OPC relationships with non-breaking spaces diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/CHPX.java b/src/scratchpad/src/org/apache/poi/hwpf/model/CHPX.java index add8ec9b1d..c7d4a30fd5 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/CHPX.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/CHPX.java @@ -72,11 +72,8 @@ public final class CHPX extends BytePropertyNode } CharacterProperties baseStyle = ss.getCharacterStyle( istd ); - if (baseStyle == null) - baseStyle = new CharacterProperties(); - CharacterProperties props = CharacterSprmUncompressor.uncompressCHP( - baseStyle, getGrpprl(), 0 ); + ss, baseStyle, getGrpprl(), 0 ); return props; } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/sprm/CharacterSprmUncompressor.java b/src/scratchpad/src/org/apache/poi/hwpf/sprm/CharacterSprmUncompressor.java index 423b569308..c1b718709f 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/sprm/CharacterSprmUncompressor.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/sprm/CharacterSprmUncompressor.java @@ -21,6 +21,7 @@ import org.apache.poi.hwpf.usermodel.ShadingDescriptor80; import org.apache.poi.hwpf.model.Colorref; import org.apache.poi.hwpf.model.Hyphenation; +import org.apache.poi.hwpf.model.StyleSheet; import org.apache.poi.hwpf.usermodel.BorderCode; import org.apache.poi.hwpf.usermodel.CharacterProperties; import org.apache.poi.hwpf.usermodel.DateAndTime; @@ -40,35 +41,89 @@ public final class CharacterSprmUncompressor extends SprmUncompressor { } - public static CharacterProperties uncompressCHP(CharacterProperties parent, - byte[] grpprl, - int offset) - { - CharacterProperties newProperties = null; - try + @Deprecated + public static CharacterProperties uncompressCHP( + CharacterProperties parent, byte[] grpprl, int offset ) { - newProperties = (CharacterProperties) parent.clone(); + CharacterProperties newProperties = parent.clone(); + applySprms( parent, grpprl, offset, true, newProperties ); + return newProperties; } - catch (CloneNotSupportedException cnse) + + public static CharacterProperties uncompressCHP( StyleSheet styleSheet, + CharacterProperties parStyle, byte[] grpprl, int offset ) { - throw new RuntimeException("There is no way this exception should happen!!"); + CharacterProperties newProperties; + if ( parStyle == null ) + { + parStyle = new CharacterProperties(); + newProperties = new CharacterProperties(); + } + else + { + newProperties = parStyle.clone(); + } + + /* + * not fully conform to specification, but the fastest way to make it + * work. Shall be rewritten if any errors would be found -- vlsergey + */ + Integer style = getIstd( grpprl, offset ); + if ( style != null ) + { + applySprms( parStyle, styleSheet.getCHPX( style ), 0, false, + newProperties ); + } + + CharacterProperties styleProperties = newProperties; + newProperties = styleProperties.clone(); + + applySprms( styleProperties, grpprl, offset, true, newProperties ); + return newProperties; } - SprmIterator sprmIt = new SprmIterator(grpprl, offset); - while (sprmIt.hasNext()) + private static void applySprms( CharacterProperties parentProperties, + byte[] grpprl, int offset, boolean warnAboutNonChpSprms, + CharacterProperties targetProperties ) { - SprmOperation sprm = sprmIt.next(); + SprmIterator sprmIt = new SprmIterator( grpprl, offset ); + + while ( sprmIt.hasNext() ) + { + SprmOperation sprm = sprmIt.next(); - if (sprm.getType() != 2) { - logger.log( POILogger.WARN, "Non-CHP SPRM returned by SprmIterator: " + sprm ); - continue; - } + if ( sprm.getType() != 2 ) + { + if ( warnAboutNonChpSprms ) + { + logger.log( POILogger.WARN, + "Non-CHP SPRM returned by SprmIterator: " + sprm ); + } + continue; + } - unCompressCHPOperation(parent, newProperties, sprm); + unCompressCHPOperation( parentProperties, targetProperties, sprm ); + } } - return newProperties; - } + private static Integer getIstd( byte[] grpprl, int offset ) + { + Integer style = null; + { + SprmIterator sprmIt = new SprmIterator( grpprl, offset ); + while ( sprmIt.hasNext() ) + { + SprmOperation sprm = sprmIt.next(); + + if ( sprm.getType() == 2 && sprm.getOperation() == 0x30 ) + { + // sprmCIstd (0x4A30) + style = Integer.valueOf( sprm.getOperand() ); + } + } + } + return style; + } /** * Used in decompression of a chpx. This performs an operation defined by @@ -238,9 +293,10 @@ public final class CharacterSprmUncompressor extends SprmUncompressor break; case 0x2f: break; - case 0x30: - newCHP.setIstd (sprm.getOperand()); - break; + case 0x30: + newCHP.setIstd( sprm.getOperand() ); + // 0x30 is supported by uncompressCHP(...) + break; case 0x31: //permutation vector for fast saves, who cares! @@ -257,20 +313,12 @@ public final class CharacterSprmUncompressor extends SprmUncompressor newCHP.setKul ((byte) 0); newCHP.setIco ((byte) 0); break; - case 0x33: - try - { - // preserve the fSpec setting from the original CHP - boolean fSpec = newCHP.isFSpec (); - newCHP = (CharacterProperties) oldCHP.clone (); - newCHP.setFSpec (fSpec); - - } - catch (CloneNotSupportedException e) - { - //do nothing - } - return; + case 0x33: + // preserve the fSpec setting from the original CHP + boolean fSpec = newCHP.isFSpec(); + newCHP = oldCHP.clone(); + newCHP.setFSpec( fSpec ); + return; case 0x34: // sprmCKcd break; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterProperties.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterProperties.java index 9d1582aec8..fd6d631c72 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterProperties.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterProperties.java @@ -370,19 +370,27 @@ public final class CharacterProperties setCv( new Colorref( colour24 & 0xFFFFFF ) ); } - public Object clone() throws CloneNotSupportedException + public CharacterProperties clone() { - CharacterProperties cp = (CharacterProperties) super.clone(); - - cp.setCv( getCv().clone() ); - cp.setDttmRMark( (DateAndTime) getDttmRMark().clone() ); - cp.setDttmRMarkDel( (DateAndTime) getDttmRMarkDel().clone() ); - cp.setDttmPropRMark( (DateAndTime) getDttmPropRMark().clone() ); - cp.setDttmDispFldRMark( (DateAndTime) getDttmDispFldRMark().clone() ); - cp.setXstDispFldRMark( getXstDispFldRMark().clone() ); - cp.setShd( (ShadingDescriptor) getShd().clone() ); - cp.setBrc( (BorderCode) getBrc().clone() ); - - return cp; + try + { + CharacterProperties cp = (CharacterProperties) super.clone(); + + cp.setCv( getCv().clone() ); + cp.setDttmRMark( (DateAndTime) getDttmRMark().clone() ); + cp.setDttmRMarkDel( (DateAndTime) getDttmRMarkDel().clone() ); + cp.setDttmPropRMark( (DateAndTime) getDttmPropRMark().clone() ); + cp.setDttmDispFldRMark( (DateAndTime) getDttmDispFldRMark().clone() ); + cp.setXstDispFldRMark( getXstDispFldRMark().clone() ); + cp.setShd( (ShadingDescriptor) getShd().clone() ); + cp.setBrc( (BorderCode) getBrc().clone() ); + + return cp; + } + catch ( CloneNotSupportedException exc ) + { + throw new UnsupportedOperationException( + "Impossible CloneNotSupportedException occured", exc ); + } } } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterRun.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterRun.java index d049969f75..77ec0ecd33 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterRun.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterRun.java @@ -535,20 +535,18 @@ public final class CharacterRun _props.setIco24(colour24); } - /** - * clone the CharacterProperties object associated with this - * characterRun so that you can apply it to another CharacterRun - * - * @deprecated This method shall not be public and should not be called from high-level code - */ - @Deprecated - public CharacterProperties cloneProperties() { - try { - return (CharacterProperties)_props.clone(); - } catch(java.lang.CloneNotSupportedException e) { - throw new RuntimeException(e); + /** + * clone the CharacterProperties object associated with this characterRun so + * that you can apply it to another CharacterRun + * + * @deprecated This method shall not be public and should not be called from + * high-level code + */ + @Deprecated + public CharacterProperties cloneProperties() + { + return _props.clone(); } - } /** * Used to create a deep copy of this object. diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java index a7a8212398..74be67b28d 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java @@ -141,6 +141,12 @@ public class TestWordToHtmlConverter extends TestCase getHtmlText( "Bug48075.doc" ); } + public void testBug53182() throws Exception + { + String result = getHtmlText( "Bug53182.doc" ); + assertFalse( result.contains( "italic" ) ); + } + public void testDocumentProperties() throws Exception { String result = getHtmlText( "documentProperties.doc" ); @@ -183,7 +189,7 @@ public class TestWordToHtmlConverter extends TestCase assertContains( result, "Before text; Hyperlink text" ); + "Hyperlink text" ); assertContains( result, "; after text" ); } diff --git a/test-data/document/Bug53182.doc b/test-data/document/Bug53182.doc new file mode 100644 index 0000000000000000000000000000000000000000..c627d02633660a7e9c2c6d1e7d0d0b90e7afae28 GIT binary patch literal 19968 zcmeHPZ;Vt|6+iFIpPgAo7PhdgTWlXtlt!E^0h_8xGZbuBDp2VvXrgxhJeZ-gJL~K~ zi&0s+)ndbk(HiB$mO>K~qo&zfQr*}@YDhoP*bi-^i77O}#t)5I5RoQ!$KUVHyR&bH z8JuY;mh|4udFS49?m6e)^X_~1p8M|X%YRyU=GZfRZ%AFbLjp2WiAvZbG61qBT}K{x>*p^>G!YGoOn3i*H&Fz476~_gM?_@4q;{uvKlbKhZz}4X zOElOcan%0%AxpuIIo!(&l}cBQ*etIr98{SMhZhpDKd))^co7L+ddQPKaRnSh-BaKb z>-wMV5P1&ev!2|$#Z&O04L!g29-&q+pQvfr-v+@uJ4L$DhSQK=40?Ui{?P5K=WBX1 zOuhc3^=Yi-bRAv30J$CzyVwf<)MsJ9Qcp9tYz zL!oYm#;w?BRObn={o4MYVT0r7MAxS}dT)Kn>n+M&?jOMPOAc~AkRmW<#oW?ew8~re)Txk{cDD`oW|OYE^9g3Sqh@=r^fnz>9WRJz8Ti_ z>aiY=8tZ-#^SPMtu+|&FeWgGB^~hsACR;2oS1p^X@qqC_y$1%fxlw1-9WJ@UY1hdn zN1ddTD&#XxI-4ve(e|1lOKyuCK=|g}|97sI z8KdWV@c>sxwfjGFy|mi2^Qw8kwk&J4tSM)$nd497Z59-^di2i)&QgE|L%cBh$*}A8kmqS?D*-F5J{Y?*pg5YZIv39EmDx83`tV* zAaOAC%7#t7^34G&m;@dgh(<;MB|ufif88kS6Xz?(WTV7taaj*auIz-yJvCsh9kVxq4YTNMc5lvw)Noemt^88Ifq!C(LSeCk*Exy4VzKhkqwY2 zp(WfxyDegUJ)(4SZ!GHVt#Nx0Mfn=wFf$DMnZ`U|-b+pEC=ZX-_UW*>QOjdWujReX z1ZAt5r^ae-J8~=qy>gY)Dc?c+Rrb<`+pC#V~&p!Rr*XuczE=#@#-o;;@|7#=O ze(;{2_~X5ecw^v|Pxt2=@eY7D@tjOG;yn!BqBmxqZ^Ro1@6^8^`dlO4LGYZjva%8H zhv2=HzT;RUUUhKPh6p_8rCyP)M_vgneB|)V;uk|=y%Gw41LgZs=BSB#!>XC&RInyF z6@=teuvN(;ftuuz03?qDT9q8PYm(zOB**Q!l1p^oe0bg!`nh$JC0_y*R-v=Mon}{? zt7zQewp29kd0Q$PyP$yz-)mvk8_E}1tLDY51utf;R=wC*vd%cSw>ThYtzuiSuFQwP z&*uZ zVU5i`P^bQ5g=R~$Rc-E=GVK7A`TkAt8x^Z|$d@szJOC)jgSe9FpSG&CSex@iwbTAQ zXUn^L%1~w7;Xo)DvID_Kzby{PV_J_g1i~QZgdxlcqhN0Veh_#Y>~bz02LIF0V@oJx z*;Yr`4(XS+ZaiwJxk2ueeUM2(k~8qyk1Ol*!a@V&*#nV|qoLz+Tn-#4 za#P=zI6D*GOVVo==vX_xkoQTC%*I*=6#3R^&gOjZ&fAg zIT-0KMmE<$!;;3;0Vk=(e-ioX2+kmvR&=iT(yDe5G_JSyd8@gS;&WxF7E@ABH*g>mk})?P*B>Wy|r@JDJMtKuv3 zJvDO>ZzR`X)z?}K&r}RgRSfIv7`z&j5FiZb07L*$fJw#!#skI!*V+R!SlwXRahX{Q zlr!Id^8DLdvkQLpqlkR+6VLvoAGA|oECePW>nXKbI1J3y&?Nw8jUbqeN0$QgJ-7;( zOPY1SoPP#@5ev)xz??hszIYC%{~590i^a{A*yI961immB#bHHvpdmX3IHC z-2}`v-uv@CtE!)UW1=m#;~qD^H#h8T$R#myR`_ zokhT#bLnDXw6L?}Y%dfu&YJ#sza&7HLqE8iD8WnctIsUKsRNZSpT5LA?+IL_?hXCP zGFNrPCK(SH4;T*^4;T*^4;T*^4;T*^4;T*^4}7>haHaU)e)XkSC*n6Qc>HIG|5v~L zG~@q`2q+oLGOo-57?+O#81Ih(81EkhaF3u2;73625AZwtQ2^uSUjP`tPXhQ$g5Loc zpPm3v_lml>o_hv^$&w4CVpkp0YRp}7#AZIt(yO-fH6Je{$2q2eZV&Y_$%^{ z0T>wH3~&JCzXMp|X=;iF4%h>bzbNr{~&9Jvcq0TgovMj&d|r_i}*l zQU&i)e*8}LpAlA~Jm%5X_SSOBze6eDtl%DX zN>~5Zq!nF#u+L{m`=AvW*5Ut6VG7|)FRk(#T?qj6T;2XD%hvT`RumZ zf9}oc{)aB>d3)`--SdAt{r{-XzJ(K)JO@1@TX8CMH#u#kZoIv;?N<9w1MORC-mG_H zzqz*dIq$_j$F6zb`aSsJ%3HYm0Zj1hb^W`W^LO3ZvyFxHo+13V2z6d>^L;#z29kQ2 YFdx_a`0aAxGr##(`(xQiTw4$P7fT5I8UO$Q literal 0 HcmV?d00001 -- 2.39.5