You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TestStyleTextPropAtom.java 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hslf.record;
  16. import static org.junit.Assert.*;
  17. import java.io.ByteArrayOutputStream;
  18. import java.io.IOException;
  19. import java.util.List;
  20. import org.apache.poi.hslf.exceptions.HSLFException;
  21. import org.apache.poi.hslf.model.textproperties.*;
  22. import org.apache.poi.util.HexDump;
  23. import org.junit.Test;
  24. /**
  25. * Tests that StyleTextPropAtom works properly
  26. *
  27. * @author Nick Burch (nick at torchbox dot com)
  28. */
  29. public final class TestStyleTextPropAtom {
  30. /** From a real file: a paragraph with 4 different styles */
  31. private static final byte[] data_a = new byte[] {
  32. 0, 0, 0xA1-256, 0x0F, 0x2A, 0, 0, 0,
  33. 0x36, 00, 00, 00, // paragraph is 54 long
  34. 00, 00, // (paragraph reserved field)
  35. 00, 00, 00, 00, // it doesn't have any styles
  36. 0x15, 00, 00, 00, // first char run is 21 long
  37. 00, 00, 00, 00, // it doesn't have any styles
  38. 0x11, 00, 00, 00, // second char run is 17 long
  39. 00, 00, 0x04, 00, // font.color only
  40. 00, 00, 00, 0x05, // blue
  41. 0x10, 00, 00, 00, // third char run is 16 long
  42. 00, 00, 0x04, 00, // font.color only
  43. 0xFF-256, 0x33, 00, 0xFE-256 // red
  44. };
  45. private static final int data_a_text_len = 0x36-1;
  46. /**
  47. * From a real file: 4 paragraphs with text in 4 different styles:
  48. * left aligned+bold (30)
  49. * centre aligned+italic+blue (28)
  50. * right aligned+red (25)
  51. * left aligned+underlined+larger font size (96)
  52. * left aligned+underlined+larger font size+red (1)
  53. */
  54. private static final byte[] data_b = new byte[] {
  55. 0, 0, 0xA1-256, 0x0F, 0x80-256, 0, 0, 0,
  56. 0x1E, 00, 00, 00, // paragraph is 30 long
  57. 00, 00, // paragraph reserved field
  58. 00, 0x18, 00, 00, // mask is 0x1800
  59. 00, 00, // left aligned
  60. 0x50, 00, // line spacing 80
  61. 0x1C, 00, 00, 00, // paragprah is 28 long
  62. 00, 00, // paragraph reserved field
  63. 00, 0x10, 00, 00, // mask is 0x1000
  64. 0x50, 00, // line spacing 80
  65. 0x19, 00, 00, 00, // paragraph is 25 long
  66. 00, 00, // paragraph reserved field
  67. 00, 0x18, 00, 00, // mask is 0x1800
  68. 02, 00, // right aligned
  69. 0x50, 00, // line spacing 80
  70. 0x61, 00, 00, 00, // paragraph is 97 long
  71. 00, 00, // paragraph reserved field
  72. 00, 0x18, 00, 00, // mask is 0x1800
  73. 00, 00, // left aligned
  74. 0x50, 00, // line spacing 80
  75. 0x1E, 00, 00, 00, // character run is 30 long
  76. 01, 00, 02, 00, // mask is 0x020001
  77. 01, 00, // char flags 0x0001 = bold
  78. 0x14, 00, // font size 20
  79. 0x1C, 00, 00, 00, // character run is 28 long
  80. 02, 00, 06, 00, // mask is 0x060002
  81. 02, 00, // char flags 0x0002 = italic
  82. 0x14, 00, // font size 20
  83. 00, 00, 00, 05, // colour blue
  84. 0x19, 00, 00, 00, // character run is 25 long
  85. 00, 00, 06, 00, // char flags 0x060000
  86. 0x14, 00, // font size 20
  87. 0xFF-256, 0x33, 00, 0xFE-256, // colour red
  88. 0x60, 00, 00, 00, // character run is 96 long
  89. 04, 00, 03, 00, // mask is 0x030004
  90. 04, 00, // char flags 0x0004 = underlined
  91. 01, 00, // font index is 1
  92. 0x18, 00, // font size 24
  93. 01, 00, 00, 00, // character run is 1 long
  94. 04, 00, 07, 00, // mask is 0x070004
  95. 04, 00, // char flags 0x0004 = underlined
  96. 01, 00, // font index is 1
  97. 0x18, 00, // font size 24
  98. 0xFF-256, 0x33, 00, 0xFE-256 // colour red
  99. };
  100. private static final int data_b_text_len = 0xB3;
  101. /**
  102. * From a real file. Has a mask with more bits
  103. * set than it actually has data for. Shouldn't do,
  104. * but some real files do :(
  105. */
  106. private static final byte[] data_c = new byte[] {
  107. 0, 0, -95, 15, 62, 0, 0, 0,
  108. 123, 0, 0, 0, 0, 0, 48, 8,
  109. 10, 0, 1, 0, 0, 0, 0, 0,
  110. 1, 0, 2, 0, 1, 0, 0, 0,
  111. 0, 0, 48, 0, 10, 0, 1, 0,
  112. 0, 0, 0, 0, 2, 0, 123, 0,
  113. 0, 0, 0, 0, 3, 0, 1, 0,
  114. 28, 0, 1, 0, 0, 0, 0, 0,
  115. 3, 0, 1, 0, 24, 0
  116. };
  117. private int data_c_text_len = 123-1;
  118. /**
  119. * From a real file supplied for Bug 40143 by tales@great.ufc.br
  120. */
  121. private static final byte[] data_d = {
  122. 0x00, 0x00, 0xA1-256, 0x0F, 0x1E, 0x00, 0x00, 0x00, //header
  123. (byte)0xA0, 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x08 , 0x00 , 0x00 ,
  124. 0x01 , 0x00, (byte)0xA0 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x63 , 0x00 ,
  125. 0x01 , 0x00, 0x01 , 0x00 , 0x00, 0x00 , 0x01 , 0x00 , 0x14 , 0x00
  126. };
  127. private static final int data_d_text_len = 0xA0-1;
  128. @Test
  129. public void testRecordType() {
  130. StyleTextPropAtom stpa = new StyleTextPropAtom(data_a,0,data_a.length);
  131. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  132. StyleTextPropAtom stpc = new StyleTextPropAtom(data_c,0,data_c.length);
  133. assertEquals(4001l, stpa.getRecordType());
  134. assertEquals(4001l, stpb.getRecordType());
  135. assertEquals(4001l, stpc.getRecordType());
  136. }
  137. @Test
  138. public void testCharacterStyleCounts() {
  139. StyleTextPropAtom stpa = new StyleTextPropAtom(data_a,0,data_a.length);
  140. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  141. // Set for the appropriate text sizes
  142. stpa.setParentTextSize(data_a_text_len);
  143. stpb.setParentTextSize(data_b_text_len);
  144. // In case A, there is a single styling of the characters
  145. assertEquals(3, stpa.getCharacterStyles().size());
  146. // In case B, there are 5 different stylings
  147. assertEquals(5, stpb.getCharacterStyles().size());
  148. }
  149. @Test
  150. public void testParagraphStyleCounts() {
  151. StyleTextPropAtom stpa = new StyleTextPropAtom(data_a,0,data_a.length);
  152. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  153. // Set for the appropriate text sizes
  154. stpa.setParentTextSize(data_a_text_len);
  155. stpb.setParentTextSize(data_b_text_len);
  156. // In case A, all has the same spacing and alignment
  157. assertEquals(1, stpa.getParagraphStyles().size());
  158. // In case B, all 4 sets have different alignments
  159. assertEquals(4, stpb.getParagraphStyles().size());
  160. }
  161. @Test
  162. public void testCharacterStyleLengths() {
  163. StyleTextPropAtom stpa = new StyleTextPropAtom(data_a,0,data_a.length);
  164. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  165. // Set for the appropriate text sizes
  166. stpa.setParentTextSize(data_a_text_len);
  167. stpb.setParentTextSize(data_b_text_len);
  168. // 54 chars, 21 + 17 + 16
  169. List<TextPropCollection> a_ch_l = stpa.getCharacterStyles();
  170. TextPropCollection a_ch_1 = a_ch_l.get(0);
  171. TextPropCollection a_ch_2 = a_ch_l.get(1);
  172. TextPropCollection a_ch_3 = a_ch_l.get(2);
  173. assertEquals(21, a_ch_1.getCharactersCovered());
  174. assertEquals(17, a_ch_2.getCharactersCovered());
  175. assertEquals(16, a_ch_3.getCharactersCovered());
  176. // 179 chars, 30 + 28 + 25
  177. List<TextPropCollection> b_ch_l = stpb.getCharacterStyles();
  178. TextPropCollection b_ch_1 = b_ch_l.get(0);
  179. TextPropCollection b_ch_2 = b_ch_l.get(1);
  180. TextPropCollection b_ch_3 = b_ch_l.get(2);
  181. TextPropCollection b_ch_4 = b_ch_l.get(3);
  182. assertEquals(30, b_ch_1.getCharactersCovered());
  183. assertEquals(28, b_ch_2.getCharactersCovered());
  184. assertEquals(25, b_ch_3.getCharactersCovered());
  185. assertEquals(96, b_ch_4.getCharactersCovered());
  186. }
  187. @Test
  188. public void testCharacterPropOrdering() {
  189. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  190. stpb.setParentTextSize(data_b_text_len);
  191. List<TextPropCollection> b_ch_l = stpb.getCharacterStyles();
  192. TextPropCollection b_ch_1 = b_ch_l.get(0);
  193. TextPropCollection b_ch_2 = b_ch_l.get(1);
  194. TextPropCollection b_ch_3 = b_ch_l.get(2);
  195. TextPropCollection b_ch_4 = b_ch_l.get(3);
  196. // In first set, we get a CharFlagsTextProp and a font.size
  197. assertEquals(2,b_ch_1.getTextPropList().size());
  198. TextProp tp_1_1 = b_ch_1.getTextPropList().get(0);
  199. TextProp tp_1_2 = b_ch_1.getTextPropList().get(1);
  200. assertEquals(true, tp_1_1 instanceof CharFlagsTextProp);
  201. assertEquals("font.size", tp_1_2.getName());
  202. assertEquals(20, tp_1_2.getValue());
  203. // In second set, we get a CharFlagsTextProp and a font.size and a font.color
  204. assertEquals(3,b_ch_2.getTextPropList().size());
  205. TextProp tp_2_1 = b_ch_2.getTextPropList().get(0);
  206. TextProp tp_2_2 = b_ch_2.getTextPropList().get(1);
  207. TextProp tp_2_3 = b_ch_2.getTextPropList().get(2);
  208. assertEquals(true, tp_2_1 instanceof CharFlagsTextProp);
  209. assertEquals("font.size", tp_2_2.getName());
  210. assertEquals("font.color", tp_2_3.getName());
  211. assertEquals(20, tp_2_2.getValue());
  212. // In third set, it's just a font.size and a font.color
  213. assertEquals(2,b_ch_3.getTextPropList().size());
  214. TextProp tp_3_1 = b_ch_3.getTextPropList().get(0);
  215. TextProp tp_3_2 = b_ch_3.getTextPropList().get(1);
  216. assertEquals("font.size", tp_3_1.getName());
  217. assertEquals("font.color", tp_3_2.getName());
  218. assertEquals(20, tp_3_1.getValue());
  219. // In fourth set, we get a CharFlagsTextProp and a font.index and a font.size
  220. assertEquals(3,b_ch_4.getTextPropList().size());
  221. TextProp tp_4_1 = b_ch_4.getTextPropList().get(0);
  222. TextProp tp_4_2 = b_ch_4.getTextPropList().get(1);
  223. TextProp tp_4_3 = b_ch_4.getTextPropList().get(2);
  224. assertEquals(true, tp_4_1 instanceof CharFlagsTextProp);
  225. assertEquals("font.index", tp_4_2.getName());
  226. assertEquals("font.size", tp_4_3.getName());
  227. assertEquals(24, tp_4_3.getValue());
  228. }
  229. @Test
  230. public void testParagraphProps() {
  231. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  232. stpb.setParentTextSize(data_b_text_len);
  233. List<TextPropCollection> b_p_l = stpb.getParagraphStyles();
  234. TextPropCollection b_p_1 = b_p_l.get(0);
  235. TextPropCollection b_p_2 = b_p_l.get(1);
  236. TextPropCollection b_p_3 = b_p_l.get(2);
  237. TextPropCollection b_p_4 = b_p_l.get(3);
  238. // 1st is left aligned + normal line spacing
  239. assertEquals(2,b_p_1.getTextPropList().size());
  240. TextProp tp_1_1 = b_p_1.getTextPropList().get(0);
  241. TextProp tp_1_2 = b_p_1.getTextPropList().get(1);
  242. assertEquals("alignment", tp_1_1.getName());
  243. assertEquals("linespacing", tp_1_2.getName());
  244. assertEquals(0, tp_1_1.getValue());
  245. assertEquals(80, tp_1_2.getValue());
  246. // 2nd is centre aligned (default) + normal line spacing
  247. assertEquals(1,b_p_2.getTextPropList().size());
  248. TextProp tp_2_1 = b_p_2.getTextPropList().get(0);
  249. assertEquals("linespacing", tp_2_1.getName());
  250. assertEquals(80, tp_2_1.getValue());
  251. // 3rd is right aligned + normal line spacing
  252. assertEquals(2,b_p_3.getTextPropList().size());
  253. TextProp tp_3_1 = b_p_3.getTextPropList().get(0);
  254. TextProp tp_3_2 = b_p_3.getTextPropList().get(1);
  255. assertEquals("alignment", tp_3_1.getName());
  256. assertEquals("linespacing", tp_3_2.getName());
  257. assertEquals(2, tp_3_1.getValue());
  258. assertEquals(80, tp_3_2.getValue());
  259. // 4st is left aligned + normal line spacing (despite differing font)
  260. assertEquals(2,b_p_4.getTextPropList().size());
  261. TextProp tp_4_1 = b_p_4.getTextPropList().get(0);
  262. TextProp tp_4_2 = b_p_4.getTextPropList().get(1);
  263. assertEquals("alignment", tp_4_1.getName());
  264. assertEquals("linespacing", tp_4_2.getName());
  265. assertEquals(0, tp_4_1.getValue());
  266. assertEquals(80, tp_4_2.getValue());
  267. }
  268. @Test
  269. public void testCharacterProps() {
  270. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  271. stpb.setParentTextSize(data_b_text_len);
  272. List<TextPropCollection> b_ch_l = stpb.getCharacterStyles();
  273. TextPropCollection b_ch_1 = b_ch_l.get(0);
  274. TextPropCollection b_ch_2 = b_ch_l.get(1);
  275. TextPropCollection b_ch_3 = b_ch_l.get(2);
  276. TextPropCollection b_ch_4 = b_ch_l.get(3);
  277. // 1st is bold
  278. CharFlagsTextProp cf_1_1 = (CharFlagsTextProp)b_ch_1.getTextPropList().get(0);
  279. assertEquals(true,cf_1_1.getSubValue(CharFlagsTextProp.BOLD_IDX));
  280. assertEquals(false,cf_1_1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
  281. assertEquals(false,cf_1_1.getSubValue(CharFlagsTextProp.ENABLE_NUMBERING_1_IDX));
  282. assertEquals(false,cf_1_1.getSubValue(CharFlagsTextProp.ENABLE_NUMBERING_2_IDX));
  283. assertEquals(false,cf_1_1.getSubValue(CharFlagsTextProp.RELIEF_IDX));
  284. assertEquals(false,cf_1_1.getSubValue(CharFlagsTextProp.RESET_NUMBERING_IDX));
  285. assertEquals(false,cf_1_1.getSubValue(CharFlagsTextProp.SHADOW_IDX));
  286. assertEquals(false,cf_1_1.getSubValue(CharFlagsTextProp.STRIKETHROUGH_IDX));
  287. assertEquals(false,cf_1_1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
  288. // 2nd is italic
  289. CharFlagsTextProp cf_2_1 = (CharFlagsTextProp)b_ch_2.getTextPropList().get(0);
  290. assertEquals(false,cf_2_1.getSubValue(CharFlagsTextProp.BOLD_IDX));
  291. assertEquals(true,cf_2_1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
  292. assertEquals(false,cf_2_1.getSubValue(CharFlagsTextProp.ENABLE_NUMBERING_1_IDX));
  293. assertEquals(false,cf_2_1.getSubValue(CharFlagsTextProp.ENABLE_NUMBERING_2_IDX));
  294. assertEquals(false,cf_2_1.getSubValue(CharFlagsTextProp.RELIEF_IDX));
  295. assertEquals(false,cf_2_1.getSubValue(CharFlagsTextProp.RESET_NUMBERING_IDX));
  296. assertEquals(false,cf_2_1.getSubValue(CharFlagsTextProp.SHADOW_IDX));
  297. assertEquals(false,cf_2_1.getSubValue(CharFlagsTextProp.STRIKETHROUGH_IDX));
  298. assertEquals(false,cf_2_1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
  299. // 3rd is normal, so lacks a CharFlagsTextProp
  300. assertFalse(b_ch_3.getTextPropList().get(0) instanceof CharFlagsTextProp);
  301. // 4th is underlined
  302. CharFlagsTextProp cf_4_1 = (CharFlagsTextProp)b_ch_4.getTextPropList().get(0);
  303. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.BOLD_IDX));
  304. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
  305. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.ENABLE_NUMBERING_1_IDX));
  306. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.ENABLE_NUMBERING_2_IDX));
  307. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.RELIEF_IDX));
  308. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.RESET_NUMBERING_IDX));
  309. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.SHADOW_IDX));
  310. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.STRIKETHROUGH_IDX));
  311. assertEquals(true,cf_4_1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
  312. // The value for this should be 4
  313. assertEquals(0x0004, cf_4_1.getValue());
  314. // Now make the 4th bold, italic and not underlined
  315. cf_4_1.setSubValue(true, CharFlagsTextProp.BOLD_IDX);
  316. cf_4_1.setSubValue(true, CharFlagsTextProp.ITALIC_IDX);
  317. cf_4_1.setSubValue(false, CharFlagsTextProp.UNDERLINE_IDX);
  318. assertEquals(true,cf_4_1.getSubValue(CharFlagsTextProp.BOLD_IDX));
  319. assertEquals(true,cf_4_1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
  320. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.ENABLE_NUMBERING_1_IDX));
  321. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.ENABLE_NUMBERING_2_IDX));
  322. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.RELIEF_IDX));
  323. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.RESET_NUMBERING_IDX));
  324. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.SHADOW_IDX));
  325. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.STRIKETHROUGH_IDX));
  326. assertEquals(false,cf_4_1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
  327. // The value should now be 3
  328. assertEquals(0x0003, cf_4_1.getValue());
  329. }
  330. @Test(expected=HSLFException.class)
  331. public void testFindAddTextProp() {
  332. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  333. stpb.setParentTextSize(data_b_text_len);
  334. List<TextPropCollection> b_p_l = stpb.getParagraphStyles();
  335. TextPropCollection b_p_1 = b_p_l.get(0);
  336. TextPropCollection b_p_2 = b_p_l.get(1);
  337. TextPropCollection b_p_3 = b_p_l.get(2);
  338. TextPropCollection b_p_4 = b_p_l.get(3);
  339. List<TextPropCollection> b_ch_l = stpb.getCharacterStyles();
  340. TextPropCollection b_ch_1 = b_ch_l.get(0);
  341. TextPropCollection b_ch_2 = b_ch_l.get(1);
  342. TextPropCollection b_ch_3 = b_ch_l.get(2);
  343. TextPropCollection b_ch_4 = b_ch_l.get(3);
  344. assertNotNull(b_p_1);
  345. assertNotNull(b_p_2);
  346. assertNotNull(b_p_3);
  347. assertNotNull(b_p_4);
  348. assertNotNull(b_ch_1);
  349. assertNotNull(b_ch_2);
  350. assertNotNull(b_ch_3);
  351. assertNotNull(b_ch_4);
  352. // CharFlagsTextProp: 3 doesn't have, 4 does
  353. assertNull(b_ch_3.findByName("char_flags"));
  354. assertNotNull(b_ch_4.findByName("char_flags"));
  355. // Now add in on 3, should go to front
  356. assertEquals(2, b_ch_3.getTextPropList().size());
  357. TextProp new_cftp = b_ch_3.addWithName("char_flags");
  358. assertEquals(3, b_ch_3.getTextPropList().size());
  359. assertEquals(new_cftp, b_ch_3.getTextPropList().get(0));
  360. // alignment: 1 does have, 2 doesn't
  361. assertNotNull(b_p_1.findByName("alignment"));
  362. assertNull(b_p_2.findByName("alignment"));
  363. // Now add in on 2, should go to the front
  364. assertEquals(1, b_p_2.getTextPropList().size());
  365. TextProp new_al = b_p_2.addWithName("alignment");
  366. assertEquals(2, b_p_2.getTextPropList().size());
  367. assertEquals(new_al, b_p_2.getTextPropList().get(0));
  368. // This should go at the end
  369. TextProp new_sa = b_p_2.addWithName("spaceafter");
  370. assertEquals(3, b_p_2.getTextPropList().size());
  371. assertEquals(new_sa, b_p_2.getTextPropList().get(2));
  372. // Check we get an error with a made up one
  373. b_p_2.addWithName("madeUpOne");
  374. }
  375. /**
  376. * Try to recreate an existing StyleTextPropAtom (a) from the empty
  377. * constructor, and setting the required properties
  378. */
  379. @Test
  380. public void testCreateAFromScatch() throws Exception {
  381. // Start with an empty one
  382. StyleTextPropAtom stpa = new StyleTextPropAtom(54);
  383. // Don't need to touch the paragraph styles
  384. // Add two more character styles
  385. List<TextPropCollection> cs = stpa.getCharacterStyles();
  386. // First char style is boring, and 21 long
  387. TextPropCollection tpca = cs.get(0);
  388. tpca.updateTextSize(21);
  389. // Second char style is coloured, 00 00 00 05, and 17 long
  390. TextPropCollection tpcb = stpa.addCharacterTextPropCollection(17);
  391. TextProp tpb = tpcb.addWithName("font.color");
  392. tpb.setValue(0x05000000);
  393. // Third char style is coloured, FF 33 00 FE, and 16 long
  394. TextPropCollection tpcc = stpa.addCharacterTextPropCollection(16);
  395. TextProp tpc = tpcc.addWithName("font.color");
  396. tpc.setValue(0xFE0033FF);
  397. // Should now be the same as data_a
  398. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  399. stpa.writeOut(baos);
  400. byte[] b = baos.toByteArray();
  401. assertEquals(data_a.length, b.length);
  402. for(int i=0; i<data_a.length; i++) {
  403. assertEquals(data_a[i],b[i]);
  404. }
  405. }
  406. /**
  407. * Try to recreate an existing StyleTextPropAtom (b) from the empty
  408. * constructor, and setting the required properties
  409. */
  410. @Test
  411. public void testCreateBFromScatch() throws Exception {
  412. // Start with an empty one
  413. StyleTextPropAtom stpa = new StyleTextPropAtom(data_b_text_len);
  414. // Need 4 paragraph styles
  415. List<TextPropCollection> ps = stpa.getParagraphStyles();
  416. // First is 30 long, left aligned, normal spacing
  417. TextPropCollection tppa = ps.get(0);
  418. tppa.updateTextSize(30);
  419. TextProp tp = tppa.addWithName("alignment");
  420. tp.setValue(0);
  421. tp = tppa.addWithName("linespacing");
  422. tp.setValue(80);
  423. // Second is 28 long, centre aligned and normal spacing
  424. TextPropCollection tppb = stpa.addParagraphTextPropCollection(28);
  425. tp = tppb.addWithName("linespacing");
  426. tp.setValue(80);
  427. // Third is 25 long, right aligned and normal spacing
  428. TextPropCollection tppc = stpa.addParagraphTextPropCollection(25);
  429. tp = tppc.addWithName("alignment");
  430. tp.setValue(2);
  431. tp = tppc.addWithName("linespacing");
  432. tp.setValue(80);
  433. // Forth is left aligned + normal line spacing (despite differing font)
  434. TextPropCollection tppd = stpa.addParagraphTextPropCollection(97);
  435. tp = tppd.addWithName("alignment");
  436. tp.setValue(0);
  437. tp = tppd.addWithName("linespacing");
  438. tp.setValue(80);
  439. // Now do 4 character styles
  440. List<TextPropCollection> cs = stpa.getCharacterStyles();
  441. // First is 30 long, bold and font size
  442. TextPropCollection tpca = cs.get(0);
  443. tpca.updateTextSize(30);
  444. tp = tpca.addWithName("font.size");
  445. tp.setValue(20);
  446. CharFlagsTextProp cftp = (CharFlagsTextProp)
  447. tpca.addWithName("char_flags");
  448. assertEquals(0, cftp.getValue());
  449. cftp.setSubValue(true, CharFlagsTextProp.BOLD_IDX);
  450. assertEquals(1, cftp.getValue());
  451. // Second is 28 long, blue and italic
  452. TextPropCollection tpcb = stpa.addCharacterTextPropCollection(28);
  453. tp = tpcb.addWithName("font.size");
  454. tp.setValue(20);
  455. tp = tpcb.addWithName("font.color");
  456. tp.setValue(0x05000000);
  457. cftp = (CharFlagsTextProp)tpcb.addWithName("char_flags");
  458. cftp.setSubValue(true, CharFlagsTextProp.ITALIC_IDX);
  459. assertEquals(2, cftp.getValue());
  460. // Third is 25 long and red
  461. TextPropCollection tpcc = stpa.addCharacterTextPropCollection(25);
  462. tp = tpcc.addWithName("font.size");
  463. tp.setValue(20);
  464. tp = tpcc.addWithName("font.color");
  465. tp.setValue(0xfe0033ff);
  466. // Fourth is 96 long, underlined and different+bigger font
  467. TextPropCollection tpcd = stpa.addCharacterTextPropCollection(96);
  468. tp = tpcd.addWithName("font.size");
  469. tp.setValue(24);
  470. tp = tpcd.addWithName("font.index");
  471. tp.setValue(1);
  472. cftp = (CharFlagsTextProp)tpcd.addWithName("char_flags");
  473. cftp.setSubValue(true, CharFlagsTextProp.UNDERLINE_IDX);
  474. assertEquals(4, cftp.getValue());
  475. // Fifth is 1 long, underlined and different+bigger font + red
  476. TextPropCollection tpce = stpa.addCharacterTextPropCollection(1);
  477. tp = tpce.addWithName("font.size");
  478. tp.setValue(24);
  479. tp = tpce.addWithName("font.index");
  480. tp.setValue(1);
  481. tp = tpce.addWithName("font.color");
  482. tp.setValue(0xfe0033ff);
  483. cftp = (CharFlagsTextProp)tpce.addWithName("char_flags");
  484. cftp.setSubValue(true, CharFlagsTextProp.UNDERLINE_IDX);
  485. assertEquals(4, cftp.getValue());
  486. // Check it's as expected
  487. assertEquals(4, stpa.getParagraphStyles().size());
  488. assertEquals(5, stpa.getCharacterStyles().size());
  489. // Compare in detail to b
  490. StyleTextPropAtom stpb = new StyleTextPropAtom(data_b,0,data_b.length);
  491. stpb.setParentTextSize(data_b_text_len);
  492. List<TextPropCollection> psb = stpb.getParagraphStyles();
  493. List<TextPropCollection> csb = stpb.getCharacterStyles();
  494. assertEquals(psb.size(), ps.size());
  495. assertEquals(csb.size(), cs.size());
  496. // Ensure Paragraph Character styles match
  497. for(int z=0; z<2; z++) {
  498. List<TextPropCollection> lla = cs;
  499. List<TextPropCollection> llb = csb;
  500. int upto = 5;
  501. if(z == 1) {
  502. lla = ps;
  503. llb = psb;
  504. upto = 4;
  505. }
  506. for(int i=0; i<upto; i++) {
  507. TextPropCollection ca = lla.get(i);
  508. TextPropCollection cb = llb.get(i);
  509. assertEquals(ca.getCharactersCovered(), cb.getCharactersCovered());
  510. assertEquals(ca.getTextPropList().size(), cb.getTextPropList().size());
  511. for(int j=0; j<ca.getTextPropList().size(); j++) {
  512. TextProp tpa = ca.getTextPropList().get(j);
  513. TextProp tpb = cb.getTextPropList().get(j);
  514. //System.out.println("TP " + i + " " + j + " " + tpa.getName() + "\t" + tpa.getValue() );
  515. assertEquals(tpa.getName(), tpb.getName());
  516. assertEquals(tpa.getMask(), tpb.getMask());
  517. assertEquals(tpa.getWriteMask(), tpb.getWriteMask());
  518. assertEquals(tpa.getValue(), tpb.getValue());
  519. }
  520. ByteArrayOutputStream ba = new ByteArrayOutputStream();
  521. ByteArrayOutputStream bb = new ByteArrayOutputStream();
  522. ca.writeOut(ba);
  523. cb.writeOut(bb);
  524. byte[] cab = ba.toByteArray();
  525. byte[] cbb = bb.toByteArray();
  526. assertEquals(cbb.length, cab.length);
  527. for(int j=0; j<cab.length; j++) {
  528. //System.out.println("On tp " + z + " " + i + " " + j + "\t" + cab[j] + "\t" + cbb[j]);
  529. assertEquals(cbb[j], cab[j]);
  530. }
  531. }
  532. }
  533. // Check byte level with b
  534. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  535. stpa.writeOut(baos);
  536. byte[] b = baos.toByteArray();
  537. assertEquals(data_b.length, b.length);
  538. for(int i=0; i<data_b.length; i++) {
  539. //System.out.println(i + "\t" + b[i] + "\t" + data_b[i] + "\t" + Integer.toHexString(b[i]) );
  540. assertEquals(data_b[i],b[i]);
  541. }
  542. }
  543. @Test
  544. public void testWriteA() {
  545. doReadWrite(data_a, -1);
  546. }
  547. @Test
  548. public void testLoadWriteA() {
  549. doReadWrite(data_b, data_b_text_len);
  550. }
  551. @Test
  552. public void testWriteB() {
  553. doReadWrite(data_b, -1);
  554. }
  555. @Test
  556. public void testLoadWriteB() {
  557. doReadWrite(data_b, data_b_text_len);
  558. }
  559. @Test
  560. public void testLoadWriteC() {
  561. // BitMaskTextProperties will sanitize the output
  562. byte expected[] = data_c.clone();
  563. expected[56] = 0;
  564. expected[68] = 0;
  565. doReadWrite(data_c, expected, data_c_text_len);
  566. }
  567. @Test
  568. public void testLoadWriteD() {
  569. doReadWrite(data_d, data_d_text_len);
  570. }
  571. protected void doReadWrite(byte[] data, int textlen) {
  572. doReadWrite(data, data, textlen);
  573. }
  574. protected void doReadWrite(byte[] data, byte[] expected, int textlen) {
  575. StyleTextPropAtom stpb = new StyleTextPropAtom(data, 0,data.length);
  576. if(textlen != -1) stpb.setParentTextSize(textlen);
  577. ByteArrayOutputStream out = new ByteArrayOutputStream();
  578. try {
  579. stpb.writeOut(out);
  580. } catch (IOException e) {
  581. throw new RuntimeException(e);
  582. }
  583. byte[] bytes = out.toByteArray();
  584. assertEquals(expected.length, bytes.length);
  585. try {
  586. assertArrayEquals(expected, bytes);
  587. } catch (Throwable e){
  588. //print hex dump if failed
  589. assertEquals(HexDump.toHex(expected), HexDump.toHex(bytes));
  590. }
  591. }
  592. @Test
  593. public void testNotEnoughDataProp() {
  594. // We don't have enough data in the record to cover
  595. // all the properties the mask says we have
  596. // Make sure we just do the best we can
  597. StyleTextPropAtom stpc = new StyleTextPropAtom(data_c,0,data_c.length);
  598. stpc.setParentTextSize(data_c_text_len);
  599. // If we get here, we didn't break
  600. }
  601. /**
  602. * Check the test data for Bug 40143.
  603. */
  604. @Test
  605. public void testBug40143() {
  606. StyleTextPropAtom atom = new StyleTextPropAtom(data_d, 0, data_d.length);
  607. atom.setParentTextSize(data_d_text_len);
  608. TextPropCollection prprops = atom.getParagraphStyles().get(0);
  609. assertEquals(data_d_text_len+1, prprops.getCharactersCovered());
  610. assertEquals(1, prprops.getTextPropList().size()); //1 property found
  611. assertEquals(1, prprops.findByName("alignment").getValue());
  612. TextPropCollection chprops = atom.getCharacterStyles().get(0);
  613. assertEquals(data_d_text_len+1, chprops.getCharactersCovered());
  614. assertEquals(5, chprops.getTextPropList().size()); //5 properties found
  615. assertEquals(1, chprops.findByName("char_flags").getValue());
  616. assertEquals(1, chprops.findByName("font.index").getValue());
  617. assertEquals(20, chprops.findByName("font.size").getValue());
  618. assertEquals(0, chprops.findByName("asian.font.index").getValue());
  619. assertEquals(1, chprops.findByName("ansi.font.index").getValue());
  620. }
  621. /**
  622. * Check the test data for Bug 42677.
  623. */
  624. @Test
  625. public void test42677() {
  626. int length = 18;
  627. byte[] data = {
  628. 0x00, 0x00, (byte)0xA1, 0x0F, 0x28, 0x00, 0x00, 0x00,
  629. 0x13, 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , (byte)0xF1 , 0x20 , 0x00, 0x00 , 0x00 , 0x00 ,
  630. 0x22 , 0x20 , 0x00 , 0x00 , 0x64 , 0x00 , 0x00 , 0x00 , 0x00 , (byte)0xFF ,
  631. 0x00 , 0x00 , 0x13 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x63 , 0x00 ,
  632. 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x0F , 0x00
  633. };
  634. doReadWrite(data, length);
  635. }
  636. /**
  637. * Bug 45815: bit mask values are not preserved on read-write
  638. *
  639. * From the test file attached to the bug:
  640. *
  641. * <StyleTextPropAtom info="0" type="4001" size="94" offset="114782" header="00 00 A1 0F 5E 00 00 00 ">
  642. * 14 00 00 00 00 00 41 00 0A 00 06 00 50 00 07 00 01 00 00 00 00 00 00 00 02
  643. * 00 00 00 01 04 00 00 01 04 01 00 00 00 01 08 00 00 01 08 0C 00 00 00 01 0C
  644. * 00 00 01 0C 01 00 00 00 01 10 00 00 01 10 01 00 00 00 01 14 00 00 01 14 01
  645. * 00 00 00 01 18 00 00 01 18 01 00 00 00 01 1C 00 00 01 1C
  646. * </StyleTextPropAtom>
  647. */
  648. @Test
  649. public void test45815() {
  650. int length = 19;
  651. byte[] data = {
  652. 0x00, 0x00, (byte)0xA1, 0x0F, 0x5E, 0x00, 0x00, 0x00, 0x14, 0x00,
  653. 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x0A, 0x00, 0x06, 0x00,
  654. 0x50, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  655. 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00,
  656. 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00,
  657. 0x01, 0x08, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, 0x00,
  658. 0x01, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00,
  659. 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00,
  660. 0x01, 0x14, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00,
  661. 0x01, 0x18, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1C, 0x00, 0x00,
  662. 0x01, 0x1C
  663. };
  664. // changed original data: ... 0x41 and 0x06 don't match
  665. // the bitmask text properties will sanitize the bytes and thus the bytes differ
  666. byte[] exptected = data.clone();
  667. exptected[18] = 0;
  668. doReadWrite(data, exptected, length);
  669. }
  670. }