/** * Parses mathml from the input into a DOM document. Split out so that subclass can call. * * @param params Parameters including MathML * @param result Blank result object * @param start Request start time (milliseconds since epoch) * @return Document or null if failed (in which case should return result) */ protected Document parseMathml(MathsImageParams params, MathsImageReturn result, long start) throws Exception { try { Document mathml = parseMathml(params.getMathml()); if (SHOWPERFORMANCE) { System.err.println("Parse DOM: " + (System.currentTimeMillis() - start)); } return mathml; } catch (SAXParseException e) { int line = e.getLineNumber(), col = e.getColumnNumber(); result.setError("MathML parse error at " + line + ":" + col + " - " + e.getMessage()); return null; } }
/** * Does real work; separated out so it can be efficiently called from subclass. * * @param params Request parameters * @param doc MathML as DOM document * @param result Initialised result object with blank fields * @param start Start time of request (milliseconds since epoch) * @return Return result * @throws IOException Any error creating image file */ protected MathsImageReturn getImage( MathsImageParams params, Document doc, MathsImageReturn result, long start) throws IOException { initContext(); Color fg; try { fg = convertRgb(params.getRgb()); } catch (IllegalArgumentException e) { result.setError(e.getMessage()); return result; } if (SHOWPERFORMANCE) { System.err.println("Setup: " + (System.currentTimeMillis() - start)); } // Parse XML to JEuclid document DocumentElement document; preprocessForJEuclid(doc); document = DOMBuilder.getInstance().createJeuclidDom(doc); if (SHOWPERFORMANCE) { System.err.println("Parse: " + (System.currentTimeMillis() - start)); } // Set layout options LayoutContextImpl layout = new LayoutContextImpl(LayoutContextImpl.getDefaultLayoutContext()); layout.setParameter(Parameter.ANTIALIAS, Boolean.TRUE); // This size is hardcoded to go well with our default text size // and be one of the sizes that doesn't look too horrible. layout.setParameter(Parameter.MATHSIZE, params.getSize() * 15f); layout.setParameter(Parameter.SCRIPTSIZEMULTIPLIER, 0.86667f); layout.setParameter(Parameter.MATHCOLOR, fg); // These fonts are included with the JEuclid build so ought to work layout.setParameter( Parameter.FONTS_SERIF, Arrays.asList(new String[] {"DejaVu Serif", "Quivira"})); layout.setParameter(Parameter.FONTS_SCRIPT, Arrays.asList(new String[] {"Allura"})); layout.setParameter(Parameter.FONTS_SANSSERIF, "DejaVu Sans"); layout.setParameter(Parameter.FONTS_MONOSPACED, "DejaVu Sans Mono"); if (SHOWPERFORMANCE) { System.err.println("Layout: " + (System.currentTimeMillis() - start)); } // Layout equation JEuclidView view = new JEuclidView(document, layout, context); float ascent = view.getAscentHeight(); float descent = view.getDescentHeight(); float width = view.getWidth(); if (SHOWPERFORMANCE) { System.err.println("View: " + (System.currentTimeMillis() - start)); } // Create new image to hold it int pixelWidth = Math.max(1, (int) Math.ceil(width)), pixelHeight = Math.max(1, (int) Math.ceil(ascent + descent)); BufferedImage image = new BufferedImage(pixelWidth, pixelHeight, BufferedImage.TYPE_INT_ARGB); if (SHOWPERFORMANCE) { System.err.println("Image: " + (System.currentTimeMillis() - start)); } view.draw(image.createGraphics(), 0, ascent); if (SHOWPERFORMANCE) { System.err.println("Draw: " + (System.currentTimeMillis() - start)); } ByteArrayOutputStream output = new ByteArrayOutputStream(); ImageIO.write(image, "png", output); if (SHOWPERFORMANCE) { System.err.println("PNG: " + (System.currentTimeMillis() - start)); } // Save results result.setImage(output.toByteArray()); result.setBaseline(BigInteger.valueOf(image.getHeight() - (int) Math.round(ascent))); result.setOk(true); if (SHOWPERFORMANCE) { System.err.println("End: " + (System.currentTimeMillis() - start)); } return result; }