Search in sources :

Example 1 with SVGRectElement

use of org.w3c.dom.svg.SVGRectElement in project megameklab by MegaMek.

the class PrintEntity method writeTextFields.

protected void writeTextFields() {
    setTextField("title", getRecordSheetTitle().toUpperCase());
    setTextField("type", getEntity().getShortNameRaw());
    setTextField("mpWalk", formatWalk());
    setTextField("mpRun", formatRun());
    setTextField("mpJump", formatJump());
    setTextField("tonnage", Integer.toString((int) getEntity().getWeight()));
    setTextField("techBase", formatTechBase());
    setTextField("rulesLevel", formatRulesLevel());
    setTextField("era", formatEra(getEntity().getYear()));
    setTextField("cost", formatCost());
    setTextField("bv", Integer.toString(getEntity().calculateBattleValue()));
    UnitRole role = UnitRoleHandler.getRoleFor(getEntity());
    if (role == UnitRole.UNDETERMINED) {
        hideElement("lblRole", true);
        hideElement("role", true);
    } else {
        setTextField("role", role.toString());
    }
    // This will require building the graphics tree so we measure the elements.
    if (getEntity().getCrew().getCrewType() != CrewType.SINGLE) {
        build();
    }
    for (int i = 0; i < getEntity().getCrew().getSlotCount(); i++) {
        // If we have multiple named crew for the unit, change the "Name:" label to
        // the label of the slot. This will usually require adjusting the position of the
        // name or the length of the blank.
        double nameOffset = 0;
        if (getEntity().getCrew().getSlotCount() > 1) {
            Element element = getSVGDocument().getElementById("crewName" + i);
            if (null != element) {
                float oldWidth = ((SVGTextContentElement) element).getComputedTextLength();
                element.setTextContent(getEntity().getCrew().getCrewType().getRoleName(i) + ":");
                nameOffset = SVGLocatableSupport.getBBox(element).getWidth() - oldWidth;
            }
        }
        if (!getEntity().getCrew().getName().equalsIgnoreCase("unnamed")) {
            Element element = getSVGDocument().getElementById("blanksCrew" + i);
            if (null != element) {
                hideElement(element);
            }
            if (nameOffset != 0) {
                element = getSVGDocument().getElementById("pilotName" + i);
                if (null != element) {
                    double offset = nameOffset;
                    String prev = element.getAttribute(SVGConstants.SVG_X_ATTRIBUTE);
                    if (null != prev) {
                        offset += Double.parseDouble(prev);
                    } else {
                        offset += ((SVGTextContentElement) element).getStartPositionOfChar(0).getX();
                    }
                    element.setAttributeNS(null, SVGConstants.SVG_X_ATTRIBUTE, Double.toString(offset));
                }
            }
            setTextField("pilotName" + i, getEntity().getCrew().getName(i), true);
            setTextField("gunnerySkill" + i, Integer.toString(getEntity().getCrew().getGunnery(i)), true);
            setTextField("pilotingSkill" + i, Integer.toString(getEntity().getCrew().getPiloting(i)), true);
            StringJoiner spaList = new StringJoiner(", ");
            PilotOptions spas = getEntity().getCrew().getOptions();
            for (Enumeration<IOptionGroup> optionGroups = spas.getGroups(); optionGroups.hasMoreElements(); ) {
                IOptionGroup optiongroup = optionGroups.nextElement();
                if (spas.count(optiongroup.getKey()) > 0) {
                    for (Enumeration<IOption> options = optiongroup.getOptions(); options.hasMoreElements(); ) {
                        IOption option = options.nextElement();
                        if (option != null && option.booleanValue()) {
                            spaList.add(option.getDisplayableNameWithValue().replaceAll(" \\(.*?\\)", ""));
                        }
                    }
                }
            }
            if (spaList.length() > 0) {
                Element rect = getSVGDocument().getElementById("spas" + getEntity().getCrew().getSlotCount());
                if ((null != rect) && (rect instanceof SVGRectElement)) {
                    Rectangle2D bbox = getRectBBox((SVGRectElement) rect);
                    Element canvas = (Element) ((Node) rect).getParentNode();
                    String spaText = "Abilities: " + spaList.toString();
                    float fontSize = FONT_SIZE_MEDIUM;
                    if (getTextLength(spaText, fontSize) > bbox.getWidth()) {
                        fontSize = (float) bbox.getHeight() / 2.4f;
                    }
                    double lineHeight = fontSize * 1.2;
                    addMultilineTextElement(canvas, bbox.getX(), bbox.getY() + lineHeight, bbox.getWidth(), lineHeight, spaText, fontSize, "start", "normal", "black", ' ');
                }
            }
        } else {
            setTextField("pilotName" + i, null);
            setTextField("gunnerySkill" + i, null);
            setTextField("pilotingSkill" + i, null);
            if (nameOffset != 0) {
                Element element = getSVGDocument().getElementById("blankCrewName" + i);
                if (null != element) {
                    float w = ((SVGGraphicsElement) element).getBBox().getWidth();
                    element.setAttributeNS(null, SVGConstants.SVG_D_ATTRIBUTE, String.format("M %f,0 %f,0", nameOffset, w - nameOffset));
                }
            }
        }
    }
}
Also used : IOptionGroup(megamek.common.options.IOptionGroup) PilotOptions(megamek.common.options.PilotOptions) SVGGraphicsElement(org.apache.batik.anim.dom.SVGGraphicsElement) SVGRectElement(org.w3c.dom.svg.SVGRectElement) Element(org.w3c.dom.Element) SVGTextContentElement(org.w3c.dom.svg.SVGTextContentElement) SVGTextContentElement(org.w3c.dom.svg.SVGTextContentElement) IOption(megamek.common.options.IOption) Rectangle2D(java.awt.geom.Rectangle2D) SVGRectElement(org.w3c.dom.svg.SVGRectElement) UnitRole(megamek.common.UnitRole) StringJoiner(java.util.StringJoiner)

Example 2 with SVGRectElement

use of org.w3c.dom.svg.SVGRectElement in project megameklab by MegaMek.

the class PrintMech method writeEquipment.

@Override
protected void writeEquipment(SVGRectElement svgRect) {
    Map<Integer, Map<RecordSheetEquipmentLine, Integer>> eqMap = new TreeMap<>();
    Map<String, Integer> ammo = new TreeMap<>();
    for (Mounted m : mech.getEquipment()) {
        if ((m.getType() instanceof AmmoType) && (((AmmoType) m.getType()).getAmmoType() != AmmoType.T_COOLANT_POD)) {
            if (m.getLocation() != Entity.LOC_NONE) {
                String shortName = m.getType().getShortName().replace("Ammo", "");
                shortName = shortName.replace("(Clan)", "");
                String munition = ((AmmoType) m.getType()).getSubMunitionName().replace("(Clan) ", "");
                shortName = shortName.replace(munition, "");
                ammo.merge(shortName.trim(), m.getBaseShotsLeft(), Integer::sum);
            }
            continue;
        }
        if ((m.getType() instanceof AmmoType) || (m.getLocation() == Entity.LOC_NONE) || !UnitUtil.isPrintableEquipment(m.getType(), true)) {
            continue;
        }
        if (mech.hasETypeFlag(Entity.ETYPE_QUADVEE) && (m.getType() instanceof MiscType) && m.getType().hasFlag(MiscType.F_TRACKS)) {
            continue;
        }
        eqMap.putIfAbsent(m.getLocation(), new HashMap<>());
        RecordSheetEquipmentLine line = new RecordSheetEquipmentLine(m);
        eqMap.get(m.getLocation()).merge(line, 1, Integer::sum);
    }
    Rectangle2D bbox = getRectBBox(svgRect);
    Element canvas = (Element) ((Node) svgRect).getParentNode();
    int viewWidth = (int) bbox.getWidth();
    int viewHeight = (int) bbox.getHeight();
    int viewX = (int) bbox.getX();
    int viewY = (int) bbox.getY();
    int qtyX = (int) Math.round(viewX + viewWidth * 0.037);
    int nameX = (int) Math.round(viewX + viewWidth * 0.08);
    int locX = (int) Math.round(viewX + viewWidth * 0.41);
    int heatX = (int) Math.round(viewX + viewWidth * 0.48);
    int dmgX = (int) Math.round(viewX + viewWidth * 0.53);
    int minX = (int) Math.round(viewX + viewWidth * 0.75);
    int shortX = (int) Math.round(viewX + viewWidth * 0.82);
    int medX = (int) Math.round(viewX + viewWidth * 0.89);
    int longX = (int) Math.round(viewX + viewWidth * 0.96);
    int indent = (int) Math.round(viewWidth * 0.02);
    int currY = viewY + 10;
    float fontSize = FONT_SIZE_MEDIUM;
    float lineHeight = getFontHeight(fontSize) * 0.8f;
    addTextElement(canvas, qtyX, currY, "Qty", fontSize, "middle", "bold");
    addTextElement(canvas, nameX + indent, currY, "Type", fontSize, "start", "bold");
    addTextElement(canvas, locX, currY, "Loc", fontSize, "middle", "bold");
    addTextElement(canvas, heatX, currY, "Ht", fontSize, "middle", "bold");
    addTextElement(canvas, dmgX, currY, "Dmg", fontSize, "start", "bold");
    addTextElement(canvas, minX, currY, "Min", fontSize, "middle", "bold");
    addTextElement(canvas, shortX, currY, "Sht", fontSize, "middle", "bold");
    addTextElement(canvas, medX, currY, "Med", fontSize, "middle", "bold");
    addTextElement(canvas, longX, currY, "Lng", fontSize, "middle", "bold");
    currY += lineHeight * 1.2;
    int lines = 0;
    for (Integer loc : eqMap.keySet()) {
        for (RecordSheetEquipmentLine line : eqMap.get(loc).keySet()) {
            int rows = line.nRows();
            if ((rows == 1) && (getTextLength(line.getNameField(0, mech.isMixedTech()), fontSize) > locX - nameX)) {
                rows++;
            }
            lines += rows;
        }
    }
    if (lines > 12) {
        lineHeight = getFontHeight(fontSize) * 0.8f;
    }
    if (lines > 16) {
        fontSize = FONT_SIZE_SMALL;
    }
    if (lines > 20) {
        fontSize = FONT_SIZE_VSMALL;
    }
    for (Integer loc : eqMap.keySet()) {
        for (RecordSheetEquipmentLine line : eqMap.get(loc).keySet()) {
            for (int row = 0; row < line.nRows(); row++) {
                if (row == 0) {
                    addTextElement(canvas, qtyX, currY, Integer.toString(eqMap.get(loc).get(line)), fontSize, "middle", "normal");
                    lines = addMultilineTextElement(canvas, nameX, currY, locX - nameX - indent, lineHeight, line.getNameField(row, mech.isMixedTech()), fontSize, "start", "normal");
                } else {
                    lines = addMultilineTextElement(canvas, nameX + indent, currY, locX - nameX - indent, lineHeight, line.getNameField(row, mech.isMixedTech()), fontSize, "start", "normal");
                }
                addTextElement(canvas, locX, currY, line.getLocationField(row), fontSize, "middle", "normal");
                addTextElement(canvas, heatX, currY, line.getHeatField(row), fontSize, "middle", "normal");
                lines = Math.max(lines, addMultilineTextElement(canvas, dmgX, currY, minX - dmgX, lineHeight, line.getDamageField(row), fontSize, "start", "normal"));
                addTextElement(canvas, minX, currY, line.getMinField(row), fontSize, "middle", "normal");
                addTextElement(canvas, shortX, currY, line.getShortField(row), fontSize, "middle", "normal");
                addTextElement(canvas, medX, currY, line.getMediumField(row), fontSize, "middle", "normal");
                addTextElement(canvas, longX, currY, line.getLongField(row), fontSize, "middle", "normal");
                currY += lineHeight * lines;
            }
        }
    }
    StringJoiner quirksList = new StringJoiner(", ");
    Quirks quirks = mech.getQuirks();
    for (Enumeration<IOptionGroup> optionGroups = quirks.getGroups(); optionGroups.hasMoreElements(); ) {
        IOptionGroup optiongroup = optionGroups.nextElement();
        if (quirks.count(optiongroup.getKey()) > 0) {
            for (Enumeration<IOption> options = optiongroup.getOptions(); options.hasMoreElements(); ) {
                IOption option = options.nextElement();
                if (option != null && option.booleanValue()) {
                    quirksList.add(option.getDisplayableNameWithValue());
                }
            }
        }
    }
    if ((ammo.size() > 0) || (quirksList.length() > 0)) {
        Element svgGroup = getSVGDocument().createElementNS(svgNS, SVGConstants.SVG_G_TAG);
        canvas.appendChild(svgGroup);
        lines = 0;
        if (ammo.size() > 0) {
            lines = addMultilineTextElement(svgGroup, viewX + viewWidth * 0.025, 0, viewWidth * 0.95, lineHeight, "Ammo: " + ammo.entrySet().stream().map(e -> String.format("(%s) %d", e.getKey(), e.getValue())).collect(Collectors.joining(", ")), fontSize, "start", "normal");
        }
        if (quirksList.length() > 0) {
            lines += addMultilineTextElement(svgGroup, viewX + viewWidth * 0.025, lines * lineHeight, viewWidth * 0.95, lineHeight, "Quirks: " + quirksList.toString(), fontSize, "start", "normal");
        }
        svgGroup.setAttributeNS(null, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, String.format("translate(0,%f)", viewY + viewHeight - lines * lineHeight));
    }
}
Also used : IOptionGroup(megamek.common.options.IOptionGroup) MiscType(megamek.common.MiscType) SVGRectElement(org.w3c.dom.svg.SVGRectElement) Element(org.w3c.dom.Element) Rectangle2D(java.awt.geom.Rectangle2D) IOption(megamek.common.options.IOption) TreeMap(java.util.TreeMap) Quirks(megamek.common.options.Quirks) AmmoType(megamek.common.AmmoType) RecordSheetEquipmentLine(megameklab.com.util.RecordSheetEquipmentLine) Mounted(megamek.common.Mounted) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) StringJoiner(java.util.StringJoiner)

Example 3 with SVGRectElement

use of org.w3c.dom.svg.SVGRectElement in project megameklab by MegaMek.

the class PrintMech method writeLocationCriticals.

private void writeLocationCriticals(int loc, SVGRectElement svgRect) {
    Rectangle2D bbox = getRectBBox(svgRect);
    Element canvas = (Element) ((Node) svgRect).getParentNode();
    int viewWidth = (int) bbox.getWidth();
    int viewHeight = (int) bbox.getHeight();
    int viewX = (int) bbox.getX();
    int viewY = (int) bbox.getY();
    double rollX = viewX;
    double critX = viewX + viewWidth * 0.11;
    double gap = 0;
    if (mech.getNumberOfCriticals(loc) > 6) {
        gap = viewHeight * 0.05;
    }
    double lineHeight = (viewHeight - gap) / mech.getNumberOfCriticals(loc);
    double currY = viewY;
    float fontSize = (float) lineHeight * 0.85f;
    Mounted startingMount = null;
    double startingMountY = 0;
    double endingMountY = 0;
    double connWidth = viewWidth * 0.02;
    double x = viewX + viewWidth * 0.075;
    x += addTextElement(canvas, x, viewY - 1, mech.getLocationName(loc), fontSize * 1.25f, "start", "bold");
    if (mech.isClan() && UnitUtil.hasAmmo(mech, loc) && !mech.hasCASEII(loc)) {
        addTextElement(canvas, x + fontSize / 2, viewY - 1, "(CASE)", fontSize, "start", "normal");
    }
    for (int slot = 0; slot < mech.getNumberOfCriticals(loc); slot++) {
        currY += lineHeight;
        if (slot == 6) {
            currY += gap;
        }
        addTextElement(canvas, rollX, currY, ((slot % 6) + 1) + ".", fontSize, "start", "bold");
        CriticalSlot crit = mech.getCritical(loc, slot);
        String style = "bold";
        String fill = "#000000";
        if ((null == crit) || ((crit.getType() == CriticalSlot.TYPE_EQUIPMENT) && (!crit.getMount().getType().isHittable()))) {
            style = "standard";
            fill = "#3f3f3f";
            addTextElement(canvas, critX, currY, formatCritName(crit), fontSize, "start", style, fill);
        } else if (crit.isArmored()) {
            Element pip = createPip(critX, currY - fontSize * 0.8, fontSize * 0.4, 0.7);
            canvas.appendChild(pip);
            addTextElement(canvas, critX + fontSize, currY, formatCritName(crit), fontSize, "start", style, fill);
        } else if ((crit.getType() == CriticalSlot.TYPE_EQUIPMENT) && (crit.getMount().getType() instanceof MiscType) && (crit.getMount().getType().hasFlag(MiscType.F_MODULAR_ARMOR))) {
            String critName = formatCritName(crit);
            addTextElement(canvas, critX, currY, critName, fontSize, "start", style, fill);
            x = critX + getTextLength(critName, fontSize);
            double remainingW = viewX + viewWidth - x;
            double spacing = remainingW / 6.0;
            double radius = spacing * 0.25;
            double y = currY - lineHeight + spacing;
            double y2 = currY - spacing;
            x += spacing;
            for (int i = 0; i < 10; i++) {
                if (i == 5) {
                    x -= spacing * 5.5;
                    y = y2;
                }
                Element pip = createPip(x, y, radius, 0.5);
                canvas.appendChild(pip);
                x += spacing;
            }
        } else {
            addTextElement(canvas, critX, currY, formatCritName(crit), fontSize, "start", style, fill);
        }
        Mounted m = null;
        if ((null != crit) && (crit.getType() == CriticalSlot.TYPE_EQUIPMENT) && (crit.getMount().getType().isHittable()) && (crit.getMount().getType().getCriticals(mech) > (mech.isSuperHeavy() ? 2 : 1))) {
            m = crit.getMount();
        }
        if ((startingMount != null) && (startingMount != m)) {
            connectSlots(canvas, critX - 1, startingMountY, connWidth, endingMountY - startingMountY);
        }
        if (m != startingMount) {
            startingMount = m;
            if (null != m) {
                startingMountY = currY - lineHeight * 0.6;
            }
        } else {
            endingMountY = currY;
        }
    }
    if ((null != startingMount) && (mech.getNumberOfCriticals(startingMount.getType(), loc) > 1)) {
        connectSlots(canvas, critX - 1, startingMountY, connWidth, endingMountY - startingMountY);
    }
}
Also used : Mounted(megamek.common.Mounted) CriticalSlot(megamek.common.CriticalSlot) SVGRectElement(org.w3c.dom.svg.SVGRectElement) Element(org.w3c.dom.Element) MiscType(megamek.common.MiscType) Rectangle2D(java.awt.geom.Rectangle2D)

Example 4 with SVGRectElement

use of org.w3c.dom.svg.SVGRectElement in project megameklab by MegaMek.

the class PrintRecordSheet method addPips.

/**
 * Adds pips to the SVG diagram. The rows are defined in the SVG diagram with a series of <rect>
 * elements, each of which determines the bounds of a row of pips. The spacing between pips is
 * determined by the height of the first row. If rows overlap the pips are offset by half in the next
 * row.
 *
 * @param group           A <g> element that has <rect> children that describe pip rows
 * @param pipCount        The number of pips to place in the region
 * @param symmetric       If true, the left and right sides will be mirror images (assuming the row
 *                        bounds are symmetric). Used for regions on a unit's center line.
 * @param size            The ratio of pip radius to the spacing between pips.
 * @param strokeWidth     The value to use for the stroke-width attribute when drawing the pips.
 */
protected void addPips(Element group, int pipCount, boolean symmetric, PipType pipType, double size, double strokeWidth) {
    if (pipCount == 0) {
        return;
    }
    final String METHOD_NAME = "addArmorPips(SVGElement,int)";
    double spacing = 6.15152;
    double left = Double.MAX_VALUE;
    double top = Double.MAX_VALUE;
    double right = 0;
    double bottom = 0;
    List<Rectangle2D> regions = new ArrayList<>();
    for (int i = 0; i < group.getChildNodes().getLength(); i++) {
        final Node r = group.getChildNodes().item(i);
        if (r instanceof SVGRectElement) {
            Rectangle2D bbox = getRectBBox((SVGRectElement) r);
            if (bbox.getX() < left) {
                left = bbox.getX();
            }
            if (bbox.getY() < top) {
                top = bbox.getY();
            }
            if (bbox.getX() + bbox.getWidth() > right) {
                right = bbox.getX() + bbox.getWidth();
            }
            if (bbox.getY() + bbox.getHeight() > bottom) {
                bottom = bbox.getY() + bbox.getHeight();
            }
            regions.add(bbox);
        }
    }
    if (regions.isEmpty()) {
        MegaMekLab.getLogger().log(getClass(), METHOD_NAME, LogLevel.WARNING, "No pip rows defined for region " + group.getAttribute("id"));
        return;
    }
    Rectangle2D bounds = new Rectangle2D.Double(left, top, right - left, bottom - top);
    double aspect = bounds.getWidth() / bounds.getHeight();
    double centerLine = regions.get(0).getX() + regions.get(0).getWidth() / 2.0;
    int maxWidth = 0;
    Collections.sort(regions, (r1, r2) -> (int) r1.getY() - (int) r2.getY());
    // Maximum number of pips that can be displayed on each row
    int[] rowLength = null;
    int[][] halfPipCount = null;
    int totalPips = 0;
    double scale = 1.0;
    List<Rectangle2D> rows = null;
    while (totalPips < pipCount) {
        totalPips = 0;
        rows = rescaleRows(regions, scale);
        rowLength = new int[rows.size()];
        halfPipCount = new int[rows.size()][];
        double prevRowBottom = 0;
        int centerPip = 0;
        spacing = rows.stream().mapToDouble(Rectangle2D::getHeight).min().orElse(spacing);
        for (int i = 0; i < rows.size(); i++) {
            final Rectangle2D rect = rows.get(i);
            int halfPipsLeft = (int) ((centerLine - rect.getX()) / (spacing / 2));
            int halfPipsRight = (int) ((rect.getX() + rect.getWidth() - centerLine) / (spacing / 2));
            if ((i > 0) && (rect.getY() < prevRowBottom)) {
                centerPip = (1 - centerPip);
                if (halfPipsLeft % 2 != centerPip) {
                    halfPipsLeft--;
                }
                if (halfPipsRight % 2 != centerPip) {
                    halfPipsRight--;
                }
                rowLength[i] = (halfPipsLeft + halfPipsRight) / 2;
            } else {
                rowLength[i] = (halfPipsLeft + halfPipsRight) / 2;
                centerPip = rowLength[i] % 2;
            }
            if (rowLength[i] > maxWidth) {
                maxWidth = rowLength[i];
            }
            halfPipCount[i] = new int[] { halfPipsLeft, halfPipsRight };
            totalPips += rowLength[i];
            prevRowBottom = rect.getY() + spacing;
        }
        scale *= 0.9;
    }
    ;
    int nRows = adjustedRows(pipCount, rows.size(), maxWidth, aspect);
    // Now we need to select the rows to use. If the total pips available in those rows is
    // insufficient, add a row and try again.
    int available = 0;
    int minWidth = maxWidth;
    List<Integer> useRows = new ArrayList<>();
    while (available < pipCount) {
        int start = rows.size() / (nRows * 2);
        for (int i = 0; i < nRows; i++) {
            int r = start + i * rows.size() / nRows;
            if (rowLength[r] > 0) {
                useRows.add(r);
                available += rowLength[r];
                if (rowLength[r] < minWidth) {
                    minWidth = rowLength[r];
                }
            }
        }
        if (available < pipCount) {
            nRows++;
            available = 0;
            useRows.clear();
            minWidth = maxWidth;
        }
    }
    // Sort the rows into the order pips should be added: longest rows first, then for rows of
    // equal length the one closest to the middle first
    final int rowCount = rows.size();
    final int[] rowSize = Arrays.copyOf(rowLength, rowLength.length);
    Collections.sort(useRows, (r1, r2) -> {
        if (rowSize[r1] == rowSize[r2]) {
            return Math.abs(r1 - rowCount / 2) - Math.abs(r2 - rowCount / 2);
        } else {
            return rowSize[r2] - rowSize[r1];
        }
    });
    // Now we iterate through the rows and assign pips as many times as it takes to get all assigned.
    int[] pipsByRow = new int[rows.size()];
    int remaining = pipCount;
    while (remaining > 0) {
        for (int r : useRows) {
            if (rowLength[r] > pipsByRow[r]) {
                int toAdd = Math.min(remaining, Math.min(rowLength[r] / minWidth, rowLength[r] - pipsByRow[r]));
                pipsByRow[r] += toAdd;
                remaining -= toAdd;
            }
        }
    }
    // an odd number of pips.
    if (symmetric) {
        // First we remove all the odd pips in even rows
        remaining = 0;
        for (int r = 0; r < rows.size(); r++) {
            if ((rowLength[r] % 2 == 0) && (pipsByRow[r] % 2 == 1)) {
                pipsByRow[r]--;
                remaining++;
            }
        }
        // Now we go through all the selected rows and assign them; this time even rows can
        // only be assigned pips in pairs.
        int toAdd = 0;
        boolean added = false;
        do {
            for (int r : useRows) {
                toAdd = 2 - rowLength[r] % 2;
                if ((remaining >= toAdd) && (pipsByRow[r] + toAdd <= rowLength[r])) {
                    pipsByRow[r] += toAdd;
                    remaining -= toAdd;
                }
            }
        } while ((remaining > 0) && added);
        // We may still have one or more left. At this point all rows are considered available.
        int centerRow = rows.size() / 2;
        while (remaining > 0) {
            for (int i = 0; i <= centerRow; i++) {
                int r = centerRow - i;
                toAdd = 2 - rowLength[r] % 2;
                if (remaining < toAdd) {
                    continue;
                }
                if (rowLength[r] >= pipsByRow[r] + toAdd) {
                    pipsByRow[r] += toAdd;
                    remaining -= toAdd;
                }
                if (i > 0) {
                    r = centerRow + i;
                    if (r >= rows.size()) {
                        continue;
                    }
                    toAdd = 2 - rowLength[r] % 2;
                    if (remaining < toAdd) {
                        continue;
                    }
                    if (rowLength[r] >= pipsByRow[r] + toAdd) {
                        pipsByRow[r] += toAdd;
                        remaining -= toAdd;
                    }
                }
            }
            // with the remaining pip to one of the even rows.
            if (remaining == 1) {
                boolean noSingle = true;
                int fromRow = -1;
                for (int r = 0; r < rows.size(); r++) {
                    if (rowLength[r] % 2 == 1) {
                        if (pipsByRow[r] < rowLength[r]) {
                            noSingle = false;
                            break;
                        } else {
                            fromRow = r;
                        }
                    }
                }
                if (noSingle) {
                    pipsByRow[fromRow]--;
                    remaining++;
                }
            }
        }
    }
    // It's likely that there's extra spacing between rows, so we're going to check whether
    // we can increase horizontal spacing between pips to keep the approximate aspect ratio.
    int firstRow = 0;
    int lastRow = rows.size() - 1;
    int r = 0;
    while (r < rows.size()) {
        if (pipsByRow[r] > 0) {
            firstRow = r;
            break;
        }
        r++;
    }
    r = rows.size() - 1;
    while (r >= 0) {
        if (pipsByRow[r] > 0) {
            lastRow = r;
            break;
        }
        r--;
    }
    double targetWidth = aspect * (rows.get(lastRow).getY() + rows.get(lastRow).getHeight() - rows.get(firstRow).getY());
    double hSpacing = targetWidth / pipsByRow[firstRow] - spacing;
    for (r = firstRow + 1; r <= lastRow; r++) {
        if (pipsByRow[r] > 0) {
            hSpacing = Math.min(hSpacing, (Math.min(targetWidth, rows.get(r).getWidth()) - spacing) / pipsByRow[r]);
        }
    }
    if (hSpacing < spacing) {
        hSpacing = spacing;
    }
    for (r = 0; r < pipsByRow.length; r++) {
        if (pipsByRow[r] > 0) {
            double radius = rows.get(r).getHeight() * size;
            Element pip = null;
            // Symmetric and this row is centered
            if (symmetric && (halfPipCount[r][0] == halfPipCount[r][1])) {
                double leftX = centerLine - hSpacing;
                double rightX = centerLine;
                if (rowLength[r] % 2 == 1) {
                    leftX -= radius;
                    rightX += hSpacing - radius;
                    if (pipsByRow[r] % 2 == 1) {
                        pip = createPip(leftX + hSpacing, rows.get(r).getY(), radius, strokeWidth, pipType);
                        group.appendChild(pip);
                        pipsByRow[r]--;
                    }
                } else {
                    leftX += hSpacing / 2 - radius;
                    rightX += hSpacing / 2 - radius;
                }
                while (pipsByRow[r] > 0) {
                    pip = createPip(leftX, rows.get(r).getY(), radius, strokeWidth, pipType);
                    group.appendChild(pip);
                    pip = createPip(rightX, rows.get(r).getY(), radius, strokeWidth, pipType);
                    group.appendChild(pip);
                    leftX -= hSpacing;
                    rightX += hSpacing;
                    pipsByRow[r] -= 2;
                }
            } else {
                // If the location is symmetric but the middle of the current row is to the left
                // of the centerline, right justify. If non-symmetric, balance the extra space at the
                // ends of the rows with any odd space going on the right margin.
                double x = centerLine - halfPipCount[r][0] * spacing / 2.0;
                if (symmetric && halfPipCount[r][0] > halfPipCount[r][1]) {
                    x += (rowLength[r] - pipsByRow[r]) * hSpacing;
                } else if (!symmetric) {
                    x += ((rowLength[r] - pipsByRow[r]) / 2) * hSpacing;
                }
                while (pipsByRow[r] > 0) {
                    pip = createPip(x, rows.get(r).getY(), radius, strokeWidth, pipType);
                    group.appendChild(pip);
                    pipsByRow[r]--;
                    x += hSpacing;
                }
            }
        }
    }
}
Also used : Node(org.w3c.dom.Node) GraphicsNode(org.apache.batik.gvt.GraphicsNode) SVGRectElement(org.w3c.dom.svg.SVGRectElement) SVGElement(org.w3c.dom.svg.SVGElement) Element(org.w3c.dom.Element) Rectangle2D(java.awt.geom.Rectangle2D) ArrayList(java.util.ArrayList) SVGRectElement(org.w3c.dom.svg.SVGRectElement)

Example 5 with SVGRectElement

use of org.w3c.dom.svg.SVGRectElement in project megameklab by MegaMek.

the class PrintEntity method printImage.

@Override
protected void printImage(Graphics2D g2d, PageFormat pageFormat, int pageNum) {
    Element element = null;
    element = getSVGDocument().getElementById("tspanCopyright");
    if (null != element) {
        element.setTextContent(String.format(element.getTextContent(), Calendar.getInstance().get(Calendar.YEAR)));
    }
    writeTextFields();
    drawArmor();
    drawStructure();
    Element eqRect = getSVGDocument().getElementById("inventory");
    if ((null != eqRect) && (eqRect instanceof SVGRectElement)) {
        writeEquipment((SVGRectElement) eqRect);
    }
    drawFluffImage();
}
Also used : SVGRectElement(org.w3c.dom.svg.SVGRectElement) SVGGraphicsElement(org.apache.batik.anim.dom.SVGGraphicsElement) SVGRectElement(org.w3c.dom.svg.SVGRectElement) Element(org.w3c.dom.Element) SVGTextContentElement(org.w3c.dom.svg.SVGTextContentElement)

Aggregations

Element (org.w3c.dom.Element)7 SVGRectElement (org.w3c.dom.svg.SVGRectElement)7 Rectangle2D (java.awt.geom.Rectangle2D)5 StringJoiner (java.util.StringJoiner)2 MiscType (megamek.common.MiscType)2 Mounted (megamek.common.Mounted)2 IOption (megamek.common.options.IOption)2 IOptionGroup (megamek.common.options.IOptionGroup)2 SVGGraphicsElement (org.apache.batik.anim.dom.SVGGraphicsElement)2 SVGTextContentElement (org.w3c.dom.svg.SVGTextContentElement)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 TreeMap (java.util.TreeMap)1 AmmoType (megamek.common.AmmoType)1 CriticalSlot (megamek.common.CriticalSlot)1 UnitRole (megamek.common.UnitRole)1 PilotOptions (megamek.common.options.PilotOptions)1 Quirks (megamek.common.options.Quirks)1 RecordSheetEquipmentLine (megameklab.com.util.RecordSheetEquipmentLine)1