package com.xenoage.zong.webserver.model; import static com.xenoage.utils.jse.xml.XMLReader.attribute; import static com.xenoage.zong.webserver.util.Parser.getInt; import static com.xenoage.zong.webserver.util.Parser.getIntAttr; import java.util.Map; import javax.servlet.ServletException; import org.w3c.dom.Element; import com.xenoage.utils.math.geom.Size2f; /** * A scaling factor. There are 4 different types of scalings: * * <ul> * <li>{@code <scaling dpi="72"/>} renders this scaling with 72 dpi (was scaling=10000 before)</li> * <li>{@code <scaling widthpx="500"/>} finds a scaling so that the first page has a width of 500 px</li> * <li>{@code <scaling heightpx="800"/>} finds a scaling so that the first page has a height of 800 px</li> * <li>{@code <scaling widthpx="500" heightpx="800"/>} finds a scaling so that the first page fits * into 500 px width AND 800 px height (the smaller scaling factor is chosen to guarantee that the whole page fits into the given area)</li> * </ul> * * @author Andreas Wenger */ public class Scaling { private final Integer dpi, widthpx, heightpx; private static final int maxScaling10000 = 100000; //1000% zoom is maximum public Scaling(Integer dpi, Integer widthpx, Integer heightpx) throws ServletException { this.dpi = dpi; this.widthpx = widthpx; this.heightpx = heightpx; //check combinations if (!((dpi != null && widthpx == null && heightpx == null) || (dpi == null && (widthpx != null || heightpx != null)))) throw new ServletException("Invalid combination of scaling types"); } public static Scaling fromXML(Element e) throws ServletException { Integer dpi = (attribute(e, "dpi") != null ? getIntAttr(e, "dpi") : null); Integer widthpx = (attribute(e, "widthpx") != null ? getIntAttr(e, "widthpx") : null); Integer heightpx = (attribute(e, "heightpx") != null ? getIntAttr(e, "heightpx") : null); return new Scaling(dpi, widthpx, heightpx); } public static Scaling fromParams(Map<String, String[]> params) throws ServletException { Integer dpi = (params.get("scaling_dpi") != null ? getInt(params, "scaling_dpi") : null); Integer widthpx = (params.get("scaling_widthpx") != null ? getInt(params, "scaling_widthpx") : null); Integer heightpx = (params.get("scaling_heightpx") != null ? getInt(params, "scaling_heightpx") : null); return new Scaling(dpi, widthpx, heightpx); } /** * Converts this scaling into return*72dpi/10000 space * (e.g. return=5000 means 36dpi). */ public int convertTo10000(Size2f firstPageSize) { //easy case: dpi if (dpi != null) return dpi * 10000 / 72; //width and height int widthScaling = maxScaling10000; int heightScaling = maxScaling10000; if (widthpx != null) widthScaling = (int) (10000 * widthpx / firstPageSize.width * (25.4f / 72)); if (heightpx != null) heightScaling = (int) (10000 * widthpx / firstPageSize.width * (25.4f / 72)); return Math.min(widthScaling, heightScaling); } }