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.

PSPainterTestCase.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.fop.render.ps;
  18. import java.awt.Color;
  19. import java.awt.Dimension;
  20. import java.awt.Rectangle;
  21. import java.io.ByteArrayOutputStream;
  22. import java.io.File;
  23. import java.io.IOException;
  24. import java.util.Collections;
  25. import java.util.HashMap;
  26. import java.util.Map;
  27. import javax.xml.transform.stream.StreamResult;
  28. import org.junit.Assert;
  29. import org.junit.Before;
  30. import org.junit.Test;
  31. import org.mockito.verification.VerificationMode;
  32. import static org.junit.Assert.fail;
  33. import static org.mockito.Matchers.any;
  34. import static org.mockito.Matchers.anyFloat;
  35. import static org.mockito.Matchers.anyInt;
  36. import static org.mockito.Mockito.mock;
  37. import static org.mockito.Mockito.never;
  38. import static org.mockito.Mockito.times;
  39. import static org.mockito.Mockito.verify;
  40. import static org.mockito.Mockito.when;
  41. import org.apache.xmlgraphics.ps.PSGenerator;
  42. import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
  43. import org.apache.fop.apps.FOUserAgent;
  44. import org.apache.fop.apps.FopFactory;
  45. import org.apache.fop.fo.Constants;
  46. import org.apache.fop.fonts.EmbeddingMode;
  47. import org.apache.fop.fonts.Font;
  48. import org.apache.fop.fonts.FontInfo;
  49. import org.apache.fop.fonts.FontTriplet;
  50. import org.apache.fop.fonts.MultiByteFont;
  51. import org.apache.fop.fonts.Typeface;
  52. import org.apache.fop.fonts.truetype.SVGGlyphData;
  53. import org.apache.fop.render.intermediate.IFContext;
  54. import org.apache.fop.render.intermediate.IFException;
  55. import org.apache.fop.render.intermediate.IFState;
  56. import org.apache.fop.traits.BorderProps;
  57. import org.apache.fop.util.CharUtilities;
  58. public class PSPainterTestCase {
  59. private PSDocumentHandler docHandler;
  60. private PSPainter psPainter;
  61. private PSGenerator gen;
  62. private IFState state;
  63. @Before
  64. public void setup() {
  65. state = IFState.create();
  66. FOUserAgent userAgent = mock(FOUserAgent.class);
  67. when(userAgent.getRendererOptions()).thenReturn(Collections.EMPTY_MAP);
  68. IFContext context = mock(IFContext.class);
  69. when(context.getUserAgent()).thenReturn(userAgent);
  70. docHandler = new PSDocumentHandler(context);
  71. gen = mock(PSGenerator.class);
  72. docHandler.gen = gen;
  73. state = IFState.create();
  74. psPainter = new PSPainter(docHandler, state);
  75. }
  76. @Test
  77. public void testNonZeroFontSize() throws IOException {
  78. testFontSize(6, times(1));
  79. }
  80. @Test
  81. public void testZeroFontSize() throws IOException {
  82. testFontSize(0, never());
  83. }
  84. private void testFontSize(int fontSize, VerificationMode test) throws IOException {
  85. state.setFontSize(fontSize);
  86. try {
  87. psPainter.drawText(10, 10, 2, 2, null, "Test");
  88. } catch (Exception ex) {
  89. //Expected
  90. }
  91. verify(gen, test).useColor(state.getTextColor());
  92. }
  93. @Test
  94. public void testDrawBorderRect() {
  95. // the goal of this test is to check that the drawing of rounded corners in PS calls
  96. // PSGraphicsPaiter.cubicBezierTo(); the check is done by verifying that a curveto command is written
  97. // to the PSGenerator
  98. PSGenerator psGenerator = mock(PSGenerator.class);
  99. when(psGenerator.formatDouble(anyFloat())).thenReturn("20.0"); // simplify!
  100. PSRenderingUtil psRenderingUtil = mock(PSRenderingUtil.class);
  101. PSDocumentHandler psDocumentHandler = mock(PSDocumentHandler.class);
  102. when(psDocumentHandler.getGenerator()).thenReturn(psGenerator);
  103. when(psDocumentHandler.getPSUtil()).thenReturn(psRenderingUtil);
  104. PSPainter psPainter = new PSPainter(psDocumentHandler);
  105. // build rectangle 200 x 50 (points, which are converted to milipoints)
  106. Rectangle rectangle = new Rectangle(0, 0, 200000, 50000);
  107. // build border properties: width 4pt, radius 30pt
  108. BorderProps border = new BorderProps(Constants.EN_SOLID, 4000, 30000, 30000, Color.BLACK,
  109. BorderProps.Mode.SEPARATE);
  110. try {
  111. psPainter.drawBorderRect(rectangle, border, border, border, border, Color.WHITE);
  112. verify(psGenerator, times(16)).writeln("20.0 20.0 20.0 20.0 20.0 20.0 curveto ");
  113. } catch (Exception e) {
  114. fail("something broke...");
  115. }
  116. }
  117. @Test
  118. public void testDrawText() throws IOException {
  119. int fontSize = 12000;
  120. String fontName = "MockFont";
  121. PSGenerator psGenerator = mock(PSGenerator.class);
  122. PSRenderingUtil psRenderingUtil = mock(PSRenderingUtil.class);
  123. PSDocumentHandler psDocumentHandler = mock(PSDocumentHandler.class);
  124. FontInfo fontInfo = mock(FontInfo.class);
  125. PSFontResource psFontResource = mock(PSFontResource.class);
  126. MultiByteFont multiByteFont = mock(MultiByteFont.class);
  127. Font font = mock(Font.class);
  128. when(psDocumentHandler.getGenerator()).thenReturn(psGenerator);
  129. when(psDocumentHandler.getPSUtil()).thenReturn(psRenderingUtil);
  130. when(psDocumentHandler.getFontInfo()).thenReturn(fontInfo);
  131. when(psDocumentHandler.getPSResourceForFontKey(fontName)).thenReturn(psFontResource);
  132. when(fontInfo.getInternalFontKey(any(FontTriplet.class))).thenReturn(fontName);
  133. when(fontInfo.getFontInstance(any(FontTriplet.class), anyInt())).thenReturn(font);
  134. Map<String, Typeface> fonts = new HashMap<String, Typeface>();
  135. fonts.put(fontName, multiByteFont);
  136. when(fontInfo.getFonts()).thenReturn(fonts);
  137. IFState ifState = IFState.create();
  138. ifState.setFontSize(fontSize);
  139. PSPainter psPainter = new PSPainter(psDocumentHandler, ifState);
  140. int x = 100000;
  141. int y = 100000;
  142. int letterSpacing = 0;
  143. int wordSpacing = 0;
  144. int[][] dp = {{100, 100, 0, 0}, null, null, {200, 200, -100, -100}};
  145. double xAsDouble = (x + dp[0][0]) / 1000.0;
  146. double yAsDouble = (y - dp[0][1]) / 1000.0;
  147. when(psGenerator.formatDouble(xAsDouble)).thenReturn("100.100");
  148. when(psGenerator.formatDouble(yAsDouble)).thenReturn("99.900");
  149. //0x48 0x65 0x6C 0x6C 0x6F 0x20 0x4D 0x6F 0x63 0x6B 0x21 0x1F4A9
  150. String text = "Hello Mock!\uD83D\uDCA9";
  151. for (int cp : CharUtilities.codepointsIter(text)) {
  152. when(font.mapCodePoint(cp)).thenReturn(cp);
  153. }
  154. try {
  155. psPainter.drawText(x, y, letterSpacing, wordSpacing, dp, text);
  156. verify(psGenerator).writeln("1 0 0 -1 100.100 99.900 Tm");
  157. verify(psGenerator).writeln("[<0048> [-100 100] <0065006C> [200 -200] <006C> [-300 300] "
  158. + "<006F0020004D006F0063006B002101F4A9>] TJ");
  159. } catch (Exception e) {
  160. fail("something broke...");
  161. }
  162. }
  163. @Test
  164. public void testOTF() throws IFException, IOException {
  165. FOUserAgent ua = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent();
  166. final IFState state = IFState.create();
  167. PSDocumentHandler dh = new PSDocumentHandler(new IFContext(ua)) {
  168. protected PSFontResource getPSResourceForFontKey(String key) {
  169. return new PSFontResource() {
  170. String getName() {
  171. return state.getFontFamily();
  172. }
  173. void notifyResourceUsageOnPage(ResourceTracker resourceTracker) {
  174. }
  175. };
  176. }
  177. };
  178. FontInfo fi = new FontInfo();
  179. addFont(fi, "OTFFont", true);
  180. addFont(fi, "TTFFont", false);
  181. dh.setFontInfo(fi);
  182. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  183. dh.setResult(new StreamResult(bos));
  184. dh.startDocument();
  185. state.setFontSize(10);
  186. state.setTextColor(Color.BLACK);
  187. state.setFontStyle("");
  188. PSPainter p = new PSPainter(dh, state) {
  189. protected String getFontKey(FontTriplet triplet) throws IFException {
  190. return state.getFontFamily();
  191. }
  192. };
  193. state.setFontFamily("TTFFont");
  194. p.drawText(0, 0, 0, 0, null, "test1");
  195. state.setFontFamily("OTFFont");
  196. p.drawText(0, 0, 0, 0, null, "test2");
  197. p.drawText(0, 0, 0, 0, null, "test3");
  198. state.setFontFamily("TTFFont");
  199. p.drawText(0, 0, 0, 0, null, "test4");
  200. Assert.assertTrue(bos.toString(), bos.toString().endsWith("BT\n"
  201. + "/TTFFont 0.01 F\n"
  202. + "1 0 0 -1 0 0 Tm\n"
  203. + "<00000000000000000000> t\n"
  204. + "/OTFFont.0 0.01 F\n"
  205. + "1 0 0 -1 0 0 Tm\n"
  206. + "<0000000000> t\n"
  207. + "1 0 0 -1 0 0 Tm\n"
  208. + "<0000000000> t\n"
  209. + "/TTFFont 0.01 F\n"
  210. + "1 0 0 -1 0 0 Tm\n"
  211. + "<00000000000000000000> t\n"));
  212. }
  213. private void addFont(FontInfo fi, String name, boolean otf) {
  214. fi.addFontProperties(name, name, "", 0);
  215. MultiByteFont mbf = new MultiByteFont(null, EmbeddingMode.AUTO);
  216. mbf.setWidthArray(new int[100]);
  217. mbf.setIsOTFFile(otf);
  218. fi.addMetrics(name, mbf);
  219. }
  220. @Test
  221. public void testSVGFont() throws IFException {
  222. FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
  223. FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
  224. PSDocumentHandler psDocumentHandler = new PSDocumentHandler(new IFContext(foUserAgent));
  225. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  226. psDocumentHandler.setResult(new StreamResult(bos));
  227. psDocumentHandler.startDocument();
  228. psDocumentHandler.startPage(0, "", "", new Dimension());
  229. FontInfo fi = new FontInfo();
  230. fi.addFontProperties("f1", new FontTriplet("a", "normal", 400));
  231. MultiByteFont font = new MultiByteFont(null, null);
  232. font.setWidthArray(new int[1]);
  233. Map<Integer, SVGGlyphData> svgs = new HashMap<>();
  234. SVGGlyphData svgGlyph = new SVGGlyphData();
  235. svgGlyph.setSVG("<svg xmlns=\"http://www.w3.org/2000/svg\">\n"
  236. + "<circle cx=\"50\" cy=\"50\" r=\"40\" stroke=\"black\" stroke-width=\"3\" fill=\"red\" />\n"
  237. + "</svg>");
  238. svgs.put(0, svgGlyph);
  239. font.setSVG(svgs);
  240. font.setBBoxArray(new Rectangle[] {new Rectangle()});
  241. fi.addMetrics("f1", font);
  242. psDocumentHandler.setFontInfo(fi);
  243. PSPainter psPainter = new PSPainter(psDocumentHandler);
  244. psPainter.setFont("a", "normal", 400, null, 12, Color.black);
  245. psPainter.drawText(0, 0, 0, 0, null, "test");
  246. Assert.assertTrue(bos.toString().contains("%FOPBeginSVG"));
  247. Assert.assertTrue(bos.toString().contains("[0.00012 0 0 0.00012 0 0] CT"));
  248. Assert.assertTrue(bos.toString().contains("1 0 0 RC"));
  249. }
  250. }