private void mergeBordersOfType()

in fop-core/src/main/java/org/apache/fop/layoutmgr/table/OverPaintBorders.java [87:187]


    private void mergeBordersOfType(List<Block> newBlocks, List<?> childAreas, int[] borderTraits) {
        Map<Integer, Map<Point, Block>> mergeMap = new HashMap<Integer, Map<Point, Block>>();
        for (int traitType : borderTraits) {
            mergeMap.put(traitType, null);
        }
        for (Object child : childAreas) {
            Block childBlock = (Block) child;
            BorderProps startBps = (BorderProps) childBlock.getTrait(Trait.BORDER_START);
            BorderProps endBps = (BorderProps) childBlock.getTrait(Trait.BORDER_END);
            BorderProps beforeBps = (BorderProps) childBlock.getTrait(Trait.BORDER_BEFORE);
            BorderProps afterBps = (BorderProps) childBlock.getTrait(Trait.BORDER_AFTER);
            for (int traitType : borderTraits) {
                Block currBlock = childBlock;
                BorderProps borderProps = (BorderProps) currBlock.getTrait(traitType);
                if (borderProps == null) {
                    continue;
                }
                Map<Point, Block> currTraitMap = mergeMap.get(traitType);
                Point endPoint = getEndMiddlePoint(currBlock, traitType, startBps, endBps, beforeBps, afterBps);
                BorderProps bpsCurr = (BorderProps) currBlock.getTrait(traitType);
                Block prevBlock = null;
                if (currTraitMap == null) {
                    currTraitMap = new HashMap<Point, Block>();
                    mergeMap.put(traitType, currTraitMap);
                } else {
                    Point startPoint = getStartMiddlePoint(currBlock, traitType, startBps, endBps, beforeBps, afterBps);
                    for (Map.Entry<Point, Block> entry : currTraitMap.entrySet()) {
                        Point prevEndPoint = entry.getKey();
                        boolean isVertical = traitType == Trait.BORDER_START || traitType == Trait.BORDER_END;
                        boolean isHorizontal = traitType == Trait.BORDER_BEFORE || traitType == Trait.BORDER_AFTER;
                        if ((isHorizontal && prevEndPoint.y == startPoint.y && prevEndPoint.x >= startPoint.x)
                                || (isVertical && prevEndPoint.x == startPoint.x && prevEndPoint.y >= startPoint.y)) {
                            Block prevBlockCurr = entry.getValue();
                            currTraitMap.remove(prevEndPoint);
                            BorderProps bpsPrev = (BorderProps) prevBlockCurr.getTrait(traitType);
                            if (canMergeBorders(bpsPrev, bpsCurr)) {
                                prevBlock = prevBlockCurr;
                            }
                            break;
                        }
                    }
                }
                Block borderBlock;
                if (prevBlock != null && newBlocks.contains(prevBlock)) {
                    borderBlock = prevBlock;
                } else {
                    borderBlock = new Block();
                    borderBlock.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
                    borderBlock.setPositioning(Block.ABSOLUTE);
                    borderBlock.setBidiLevel(currBlock.getBidiLevel());
                    newBlocks.add(borderBlock);
                    BorderProps prevBeforeBps = (BorderProps) currBlock.getTrait(Trait.BORDER_BEFORE);
                    int prevBefore = prevBeforeBps != null ? prevBeforeBps.width : 0;
                    Integer prevPaddingStart = (Integer) currBlock.getTrait(Trait.PADDING_START);
                    Integer prevPaddingEnd = (Integer) currBlock.getTrait(Trait.PADDING_END);
                    Integer prevPaddingBefore = (Integer) currBlock.getTrait(Trait.PADDING_BEFORE);
                    Integer prevPaddingAfter = (Integer) currBlock.getTrait(Trait.PADDING_AFTER);
                    if (traitType == Trait.BORDER_START) {
                        borderBlock.setYOffset(currBlock.getYOffset() + prevBefore);
                        borderBlock.setXOffset(currBlock.getXOffset()
                                - (prevPaddingStart != null ? prevPaddingStart : 0));
                    } else if (traitType == Trait.BORDER_END) {
                        borderBlock.setYOffset(currBlock.getYOffset() + prevBefore);
                        borderBlock.setXOffset(currBlock.getXOffset()
                                - (prevPaddingStart != null ? prevPaddingStart : 0));
                        borderBlock.setIPD(currBlock.getIPD()
                                + (prevPaddingStart != null ? prevPaddingStart : 0)
                                + (prevPaddingEnd != null ? prevPaddingEnd : 0));
                    } else if (traitType == Trait.BORDER_BEFORE) {
                        borderBlock.setYOffset(currBlock.getYOffset());
                        borderBlock.setXOffset(currBlock.getXOffset()
                                - (prevPaddingStart != null ? prevPaddingStart : 0));
                    } else if (traitType == Trait.BORDER_AFTER) {
                        borderBlock.setYOffset(currBlock.getYOffset() + prevBefore);
                        borderBlock.setXOffset(currBlock.getXOffset()
                                - (prevPaddingStart != null ? prevPaddingStart : 0));
                        borderBlock.setBPD(currBlock.getBPD()
                                + (prevPaddingBefore != null ? prevPaddingBefore : 0)
                                + (prevPaddingAfter != null ? prevPaddingAfter : 0));
                    }
                }
                Integer paddingEnd = (Integer) currBlock.getTrait(Trait.PADDING_END);
                Integer paddingAfter = (Integer) currBlock.getTrait(Trait.PADDING_AFTER);
                if (traitType == Trait.BORDER_BEFORE || traitType == Trait.BORDER_AFTER) {
                    int newEndPoint = currBlock.getXOffset() + currBlock.getIPD()
                            + (paddingEnd != null ? paddingEnd : 0);
                    borderBlock.setIPD(newEndPoint - borderBlock.getXOffset());
                } else if (traitType == Trait.BORDER_START || traitType == Trait.BORDER_END) {
                    int newEndPoint = currBlock.getYOffset() + currBlock.getBPD()
                            + currBlock.getBorderAndPaddingWidthBefore()
                            + (paddingAfter != null ? paddingAfter : 0);
                    borderBlock.setBPD(newEndPoint - borderBlock.getYOffset());
                }
                BorderProps newBps = new BorderProps(bpsCurr.style, bpsCurr.width, 0, 0,
                        bpsCurr.color, bpsCurr.getMode());
                borderBlock.addTrait(traitType, newBps);
                currBlock = borderBlock;
                currTraitMap.put(endPoint, currBlock);
            }
        }
    }