/*
* This file is part of LaTeXDraw.
* Copyright (c) 2005-2017 Arnaud BLOUIN
* LaTeXDraw is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
* LaTeXDraw is distributed without any warranty; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package net.sf.latexdraw.view.pst;
import java.util.HashMap;
import java.util.Map;
import net.sf.latexdraw.models.MathUtils;
import net.sf.latexdraw.models.interfaces.shape.IPoint;
import net.sf.latexdraw.util.LSystem;
import net.sf.latexdraw.view.latex.DviPsColors;
import net.sf.latexdraw.view.latex.LaTeXGenerator;
import net.sf.latexdraw.view.latex.VerticalPosition;
import org.eclipse.jdt.annotation.NonNull;
/**
* Defines a PSTricks generator; it manages the PSTricks views and the latex additional code.
* @author Arnaud Blouin
*/
public class PSTCodeGenerator extends LaTeXGenerator {
static final @NonNull String PACKAGE_PSTRICKS = "% \\usepackage[usenames,dvipsnames]{pstricks}" + LSystem.EOL +//$NON-NLS-1$
"% \\usepackage{epsfig}" + LSystem.EOL + "% \\usepackage{pst-grad} % For gradients" +//$NON-NLS-1$//$NON-NLS-2$
LSystem.EOL + "% \\usepackage{pst-plot} % For axes" + LSystem.EOL; //$NON-NLS-1$
public static final @NonNull String PACKAGE_FOR_SPACE_PICTURE = "\\usepackage[space]{grffile} % For spaces in paths" + LSystem.EOL +
"\\usepackage{etoolbox} % For spaces in paths" + LSystem.EOL + "\\makeatletter % For spaces in paths" + LSystem.EOL +
"\\patchcmd\\Gread@eps{\\@inputcheck#1 }{\\@inputcheck\"#1\"\\relax}{}{}" + LSystem.EOL + "\\makeatother" + LSystem.EOL;
/**
* Creates and initialises the generator.
*/
public PSTCodeGenerator() {
super();
}
@Override
public String getDocumentCode() {
final StringBuilder doc = new StringBuilder();
final IPoint bl = handler.getBottomLeftDrawingPoint();
final IPoint tr = handler.getTopRightDrawingPoint();
final float ppc = handler.getPPCDrawing();
if(tr.getY() < 0) {
bl.setY(bl.getY() - tr.getY());
tr.setY(0.0);
}
doc.append("\\documentclass{article}").append(LSystem.EOL).append("\\pagestyle{empty}").append(LSystem.EOL).append(getPackages()).append(LSystem.EOL).append( //$NON-NLS-1$ //$NON-NLS-2$
"\\usepackage[left=0cm,top=0.1cm,right=0cm,bottom=0cm,nohead,nofoot,paperwidth=").append( //$NON-NLS-1$
tr.getX() / ppc * scale).append("cm,paperheight=").append( //$NON-NLS-1$
bl.getY() / ppc * scale + 0.2).append("cm]{geometry}").append( //$NON-NLS-1$
LSystem.EOL).append("\\usepackage[usenames,dvipsnames]{pstricks}").append(//$NON-NLS-1$
LSystem.EOL).append("\\usepackage{epsfig}").append(//$NON-NLS-1$
LSystem.EOL).append("\\usepackage{pst-grad}").append(LSystem.EOL).append("\\usepackage{pst-plot}").append(LSystem.EOL).append(//$NON-NLS-1$//$NON-NLS-2$
PSTCodeGenerator.PACKAGE_FOR_SPACE_PICTURE).append("\\begin{document}").append(LSystem.EOL).append( //$NON-NLS-1$
"\\addtolength{\\oddsidemargin}{-0.2in}").append(LSystem.EOL).append("\\addtolength{\\evensidemargin}{-0.2in}").append( //$NON-NLS-1$ //$NON-NLS-2$
LSystem.EOL).append(getDrawingCode()).append(LSystem.EOL).append("\\end{document}");//$NON-NLS-1$
return doc.toString();
}
@Override
public String getDrawingCode() {
if(drawing.isEmpty()) return "";
final StringBuilder cache = new StringBuilder();
String pkg = LaTeXGenerator.getPackages();
final IPoint origin = handler.getOriginDrawingPoint();
final IPoint tl = handler.getTopRightDrawingPoint();
final IPoint br = handler.getBottomLeftDrawingPoint();
final int ppc = handler.getPPCDrawing();
final Map<String, String> addedColours = new HashMap<>();
final StringBuilder shapeCode = new StringBuilder();
final boolean hasBeginFigure;
if(withComments && comment != null && !comment.isEmpty()) cache.append(comment);
cache.append(PACKAGE_PSTRICKS).append("% ").append(PACKAGE_FOR_SPACE_PICTURE.replaceAll(LSystem.EOL, LSystem.EOL + "% "));
if(!pkg.isEmpty()) {
pkg = "% User Packages:" + LSystem.EOL + "% " + pkg.replace(LSystem.EOL, LSystem.EOL + "% "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
cache.append(pkg).append(LSystem.EOL);
}
cache.append(LSystem.EOL);
if(withLatexParams && (positionVertToken != VerticalPosition.NONE || !caption.isEmpty() || !label.isEmpty())) {
cache.append("\\begin{figure}"); //$NON-NLS-1$
if(positionVertToken == VerticalPosition.NONE) cache.append(LSystem.EOL);
else cache.append('[').append(positionVertToken.getToken()).append(']').append(LSystem.EOL);
hasBeginFigure = true;
}else hasBeginFigure = false;
if(withLatexParams && positionHoriCentre) cache.append("\\begin{center}").append(LSystem.EOL);//$NON-NLS-1$
final float scaleF = MathUtils.INST.getCutNumberFloat(getScale());
cache.append("\\psscalebox{").append(scaleF).append(' ').append(scaleF).append("} % Change this value to rescale the drawing.");//$NON-NLS-1$ //$NON-NLS-2$
cache.append(LSystem.EOL).append('{').append(LSystem.EOL);
cache.append("\\begin{pspicture}("); //$NON-NLS-1$
cache.append(0).append(',').append(MathUtils.INST.getCutNumberFloat((origin.getY() - br.getY()) / ppc)).append(')').append('(');
cache.append(MathUtils.INST.getCutNumberFloat((tl.getX() - origin.getX()) / ppc)).append(',').append(MathUtils.INST.getCutNumberFloat((origin.getY() - tl.getY()) / ppc));
cache.append(')').append(LSystem.EOL);
drawing.getShapes().forEach(shape -> PSTViewsFactory.INSTANCE.createView(shape).ifPresent(pstView -> {
shapeCode.append(pstView.getCode(origin, ppc)).append(LSystem.EOL);
cache.append(generateColourCode(pstView, addedColours));
}));
cache.append(shapeCode).append("\\end{pspicture}").append(LSystem.EOL).append('}').append(LSystem.EOL); //$NON-NLS-1$
if(withLatexParams) {
if(positionHoriCentre) cache.append("\\end{center}").append(LSystem.EOL);//$NON-NLS-1$
if(!label.isEmpty()) cache.append("\\label{").append(label).append('}').append(LSystem.EOL);//$NON-NLS-1$
if(!caption.isEmpty()) cache.append("\\caption{").append(caption).append('}').append(LSystem.EOL);//$NON-NLS-1$
if(hasBeginFigure) cache.append("\\end{figure}").append(LSystem.EOL);//$NON-NLS-1$
}
return cache.toString();
}
/**
* Adds the PST colour code to the cache.
* @param pstView The shape which colour code will be generated.
* @param addedColours The PST colours already generated.
* @since 3.0
*/
private @NonNull String generateColourCode(final @NonNull PSTShapeView<?> pstView, final @NonNull Map<String, String> addedColours) {
if(pstView.coloursName != null) {
for(final String nameColour : pstView.coloursName) {
if(addedColours.get(nameColour) == null && !DviPsColors.INSTANCE.getPredefinedColour(nameColour).isPresent()) {
addedColours.put(nameColour, nameColour);
return DviPsColors.INSTANCE.getUsercolourCode(nameColour) + LSystem.EOL;
}
}
}
return ""; //$NON-NLS-1$
}
}