/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.exporters.morphshape;
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
import com.jpexs.decompiler.flash.types.ColorTransform;
import com.jpexs.decompiler.flash.types.FILLSTYLE;
import com.jpexs.decompiler.flash.types.FOCALGRADIENT;
import com.jpexs.decompiler.flash.types.LINESTYLE;
import com.jpexs.decompiler.flash.types.LINESTYLE2;
import com.jpexs.decompiler.flash.types.RGB;
import com.jpexs.decompiler.flash.types.SHAPE;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author JPEXS, Claus Wahlers
*/
public abstract class MorphShapeExporterBase implements IMorphShapeExporter {
protected final SHAPE shape;
protected final SHAPE shapeEnd;
protected List<FILLSTYLE> _fillStyles;
protected List<LINESTYLE> _lineStyles;
protected List<FILLSTYLE> _fillStylesEnd;
protected List<LINESTYLE> _lineStylesEnd;
protected List<Map<Integer, List<IMorphEdge>>> _fillEdgeMaps;
protected List<Map<Integer, List<IMorphEdge>>> _lineEdgeMaps;
private boolean edgeMapsCreated;
protected ColorTransform colorTransform;
public MorphShapeExporterBase(SHAPE shape, SHAPE endShape, ColorTransform colorTransform) {
this.shape = shape;
this.shapeEnd = endShape;
this.colorTransform = colorTransform;
_fillStyles = new ArrayList<>();
_lineStyles = new ArrayList<>();
if (shape instanceof SHAPEWITHSTYLE) {
SHAPEWITHSTYLE shapeWithStyle = (SHAPEWITHSTYLE) shape;
_fillStyles.addAll(Arrays.asList(shapeWithStyle.fillStyles.fillStyles));
_lineStyles.addAll(Arrays.asList(shapeWithStyle.lineStyles.lineStyles));
}
_fillStylesEnd = new ArrayList<>();
_lineStylesEnd = new ArrayList<>();
if (endShape instanceof SHAPEWITHSTYLE) {
SHAPEWITHSTYLE shapeWithStyle = (SHAPEWITHSTYLE) endShape;
_fillStylesEnd.addAll(Arrays.asList(shapeWithStyle.fillStyles.fillStyles));
_lineStylesEnd.addAll(Arrays.asList(shapeWithStyle.lineStyles.lineStyles));
}
}
public void export() {
// Create edge maps
_fillEdgeMaps = new ArrayList<>();
_lineEdgeMaps = new ArrayList<>();
createEdgeMaps(_fillStyles, _lineStyles, _fillStylesEnd, _lineStylesEnd, _fillEdgeMaps, _lineEdgeMaps);
// Let the doc handler know that a shape export starts
beginShape();
// Export fills and strokes for each group separately
for (int i = 0; i < _lineEdgeMaps.size(); i++) {
// Export fills first
exportFillPath(i);
// Export strokes last
exportLinePath(i);
}
// Let the doc handler know that we're done exporting a shape
endShape();
}
protected void createEdgeMaps(List<FILLSTYLE> fillStyles, List<LINESTYLE> lineStyles,
List<FILLSTYLE> fillStylesEnd, List<LINESTYLE> lineStylesEnd,
List<Map<Integer, List<IMorphEdge>>> fillEdgeMaps, List<Map<Integer, List<IMorphEdge>>> lineEdgeMaps) {
if (!edgeMapsCreated) {
int xPos = 0;
int yPos = 0;
int xPosEnd = 0;
int yPosEnd = 0;
int fillStyleIdxOffset = 0;
int lineStyleIdxOffset = 0;
int currentFillStyleIdx0 = 0;
int currentFillStyleIdx1 = 0;
int currentLineStyleIdx = 0;
List<IMorphEdge> subPath = new ArrayList<>();
Map<Integer, List<IMorphEdge>> currentFillEdgeMap = new HashMap<>();
Map<Integer, List<IMorphEdge>> currentLineEdgeMap = new HashMap<>();
List<SHAPERECORD> records = shape.shapeRecords;
List<SHAPERECORD> recordsEnd = shapeEnd.shapeRecords;
if (records.size() != recordsEnd.size()) {
throw new Error("Begin and end shaperecord list length should be the same.");
}
for (int i = 0; i < records.size(); i++) {
SHAPERECORD shapeRecord = records.get(i);
SHAPERECORD shapeRecordEnd = recordsEnd.get(i);
if ((shapeRecord instanceof StyleChangeRecord && !(shapeRecordEnd instanceof StyleChangeRecord))
|| (shapeRecord instanceof StraightEdgeRecord && !(shapeRecordEnd instanceof StraightEdgeRecord))
|| (shapeRecord instanceof CurvedEdgeRecord && !(shapeRecordEnd instanceof CurvedEdgeRecord))
|| (shapeRecord instanceof EndShapeRecord && !(shapeRecordEnd instanceof EndShapeRecord))) {
throw new Error("Begin and end shaperecord should have the same type.");
}
if (shapeRecord instanceof StyleChangeRecord) {
StyleChangeRecord styleChangeRecord = (StyleChangeRecord) shapeRecord;
if (styleChangeRecord.stateLineStyle || styleChangeRecord.stateFillStyle0 || styleChangeRecord.stateFillStyle1) {
processSubPath(subPath, currentLineStyleIdx, currentFillStyleIdx0, currentFillStyleIdx1, currentFillEdgeMap, currentLineEdgeMap);
subPath = new ArrayList<>();
}
if (styleChangeRecord.stateNewStyles) {
fillStyleIdxOffset = fillStyles.size();
lineStyleIdxOffset = lineStyles.size();
appendFillStyles(fillStyles, styleChangeRecord.fillStyles.fillStyles);
appendLineStyles(lineStyles, styleChangeRecord.lineStyles.lineStyles);
appendFillStyles(fillStylesEnd, styleChangeRecord.fillStyles.fillStyles);
appendLineStyles(lineStylesEnd, styleChangeRecord.lineStyles.lineStyles);
}
// Check if all styles are reset to 0.
// This (probably) means that a new group starts with the next record
if (styleChangeRecord.stateLineStyle && styleChangeRecord.lineStyle == 0
&& styleChangeRecord.stateFillStyle0 && styleChangeRecord.fillStyle0 == 0
&& styleChangeRecord.stateFillStyle1 && styleChangeRecord.fillStyle1 == 0) {
// do not clean the edges for morphshapes
//cleanEdgeMap(currentFillEdgeMap);
//cleanEdgeMap(currentLineEdgeMap);
fillEdgeMaps.add(currentFillEdgeMap);
lineEdgeMaps.add(currentLineEdgeMap);
currentFillEdgeMap = new HashMap<>();
currentLineEdgeMap = new HashMap<>();
currentLineStyleIdx = 0;
currentFillStyleIdx0 = 0;
currentFillStyleIdx1 = 0;
} else {
if (styleChangeRecord.stateLineStyle) {
currentLineStyleIdx = styleChangeRecord.lineStyle;
if (currentLineStyleIdx > 0) {
currentLineStyleIdx += lineStyleIdxOffset;
}
}
if (styleChangeRecord.stateFillStyle0) {
currentFillStyleIdx0 = styleChangeRecord.fillStyle0;
if (currentFillStyleIdx0 > 0) {
currentFillStyleIdx0 += fillStyleIdxOffset;
}
}
if (styleChangeRecord.stateFillStyle1) {
currentFillStyleIdx1 = styleChangeRecord.fillStyle1;
if (currentFillStyleIdx1 > 0) {
currentFillStyleIdx1 += fillStyleIdxOffset;
}
}
}
if (styleChangeRecord.stateMoveTo) {
xPos = styleChangeRecord.moveDeltaX;
yPos = styleChangeRecord.moveDeltaY;
}
StyleChangeRecord styleChangeRecordEnd = (StyleChangeRecord) shapeRecordEnd;
if (styleChangeRecordEnd.stateMoveTo) {
xPosEnd = styleChangeRecordEnd.moveDeltaX;
yPosEnd = styleChangeRecordEnd.moveDeltaY;
}
} else if (shapeRecord instanceof StraightEdgeRecord) {
StraightEdgeRecord straightEdgeRecord = (StraightEdgeRecord) shapeRecord;
int xPosFrom = xPos;
int yPosFrom = yPos;
if (straightEdgeRecord.generalLineFlag) {
xPos += straightEdgeRecord.deltaX;
yPos += straightEdgeRecord.deltaY;
} else if (straightEdgeRecord.vertLineFlag) {
yPos += straightEdgeRecord.deltaY;
} else {
xPos += straightEdgeRecord.deltaX;
}
StraightEdgeRecord straightEdgeRecordEnd = (StraightEdgeRecord) shapeRecordEnd;
int xPosEndFrom = xPosEnd;
int yPosEndFrom = yPosEnd;
if (straightEdgeRecordEnd.generalLineFlag) {
xPosEnd += straightEdgeRecordEnd.deltaX;
yPosEnd += straightEdgeRecordEnd.deltaY;
} else if (straightEdgeRecordEnd.vertLineFlag) {
yPosEnd += straightEdgeRecordEnd.deltaY;
} else {
xPosEnd += straightEdgeRecordEnd.deltaX;
}
subPath.add(new StraightMorphEdge(xPosFrom, yPosFrom, xPos, yPos, xPosEndFrom, yPosEndFrom, xPosEnd, yPosEnd, currentLineStyleIdx, currentFillStyleIdx1));
} else if (shapeRecord instanceof CurvedEdgeRecord) {
CurvedEdgeRecord curvedEdgeRecord = (CurvedEdgeRecord) shapeRecord;
int xPosFrom = xPos;
int yPosFrom = yPos;
int xPosControl = xPos + curvedEdgeRecord.controlDeltaX;
int yPosControl = yPos + curvedEdgeRecord.controlDeltaY;
xPos = xPosControl + curvedEdgeRecord.anchorDeltaX;
yPos = yPosControl + curvedEdgeRecord.anchorDeltaY;
CurvedEdgeRecord curvedEdgeRecordEnd = (CurvedEdgeRecord) shapeRecordEnd;
int xPosEndFrom = xPosEnd;
int yPosEndFrom = yPosEnd;
int xPosEndControl = xPosEnd + curvedEdgeRecordEnd.controlDeltaX;
int yPosEndControl = yPosEnd + curvedEdgeRecordEnd.controlDeltaY;
xPosEnd = xPosEndControl + curvedEdgeRecordEnd.anchorDeltaX;
yPosEnd = yPosEndControl + curvedEdgeRecordEnd.anchorDeltaY;
subPath.add(new CurvedMorphEdge(xPosFrom, yPosFrom, xPosControl, yPosControl, xPos, yPos, xPosEndFrom, yPosEndFrom, xPosEndControl, yPosEndControl, xPosEnd, yPosEnd, currentLineStyleIdx, currentFillStyleIdx1));
} else if (shapeRecord instanceof EndShapeRecord) {
// We're done. Process the last subpath, if any
processSubPath(subPath, currentLineStyleIdx, currentFillStyleIdx0, currentFillStyleIdx1, currentFillEdgeMap, currentLineEdgeMap);
// do not clean the edges for morphshapes
//cleanEdgeMap(currentFillEdgeMap);
//cleanEdgeMap(currentLineEdgeMap);
fillEdgeMaps.add(currentFillEdgeMap);
lineEdgeMaps.add(currentLineEdgeMap);
}
}
edgeMapsCreated = true;
}
}
protected void processSubPath(List<IMorphEdge> subPath, int lineStyleIdx, int fillStyleIdx0, int fillStyleIdx1,
Map<Integer, List<IMorphEdge>> currentFillEdgeMap, Map<Integer, List<IMorphEdge>> currentLineEdgeMap) {
List<IMorphEdge> path;
if (fillStyleIdx0 != 0) {
path = currentFillEdgeMap.get(fillStyleIdx0);
if (path == null) {
path = new ArrayList<>();
currentFillEdgeMap.put(fillStyleIdx0, path);
}
for (int j = subPath.size() - 1; j >= 0; j--) {
path.add(subPath.get(j).reverseWithNewFillStyle(fillStyleIdx0));
}
}
if (fillStyleIdx1 != 0) {
path = currentFillEdgeMap.get(fillStyleIdx1);
if (path == null) {
path = new ArrayList<>();
currentFillEdgeMap.put(fillStyleIdx1, path);
}
appendEdges(path, subPath);
}
if (lineStyleIdx != 0) {
path = currentLineEdgeMap.get(lineStyleIdx);
if (path == null) {
path = new ArrayList<>();
currentLineEdgeMap.put(lineStyleIdx, path);
}
appendEdges(path, subPath);
}
}
protected void exportFillPath(int groupIndex) {
List<IMorphEdge> path = createPathFromEdgeMap(_fillEdgeMaps.get(groupIndex));
int posX = Integer.MAX_VALUE;
int posY = Integer.MAX_VALUE;
int fillStyleIdx = Integer.MAX_VALUE;
if (path.size() > 0) {
beginFills();
for (int i = 0; i < path.size(); i++) {
IMorphEdge e = path.get(i);
if (fillStyleIdx != e.getFillStyleIdx()) {
if (fillStyleIdx != Integer.MAX_VALUE) {
endFill();
}
fillStyleIdx = e.getFillStyleIdx();
posX = Integer.MAX_VALUE;
posY = Integer.MAX_VALUE;
if (fillStyleIdx - 1 < _fillStyles.size()) {
Matrix matrix;
Matrix matrixEnd;
FILLSTYLE fillStyle = _fillStyles.get(fillStyleIdx - 1);
FILLSTYLE fillStyleEnd = _fillStylesEnd.get(fillStyleIdx - 1);
switch (fillStyle.fillStyleType) {
case FILLSTYLE.SOLID:
// Solid fill
if (colorTransform == null) {
beginFill(fillStyle.color, fillStyleEnd.color);
} else {
beginFill(colorTransform.apply(fillStyle.color), colorTransform.apply(fillStyleEnd.color));
}
break;
case FILLSTYLE.LINEAR_GRADIENT:
case FILLSTYLE.RADIAL_GRADIENT:
case FILLSTYLE.FOCAL_RADIAL_GRADIENT:
// Gradient fill
matrix = new Matrix(fillStyle.gradientMatrix);
matrixEnd = new Matrix(fillStyleEnd.gradientMatrix);
beginGradientFill(
fillStyle.fillStyleType,
colorTransform == null ? fillStyle.gradient.gradientRecords : colorTransform.apply(fillStyle.gradient.gradientRecords),
colorTransform == null ? fillStyleEnd.gradient.gradientRecords : colorTransform.apply(fillStyleEnd.gradient.gradientRecords),
matrix,
matrixEnd,
fillStyle.gradient.spreadMode,
fillStyle.gradient.interpolationMode,
(fillStyle.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyle.gradient).focalPoint : 0,
(fillStyleEnd.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyleEnd.gradient).focalPoint : 0
);
break;
case FILLSTYLE.REPEATING_BITMAP:
case FILLSTYLE.CLIPPED_BITMAP:
case FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP:
case FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP:
// Bitmap fill
matrix = new Matrix(fillStyle.bitmapMatrix);
matrixEnd = new Matrix(fillStyleEnd.bitmapMatrix);
beginBitmapFill(
fillStyle.bitmapId,
matrix,
matrixEnd,
(fillStyle.fillStyleType == FILLSTYLE.REPEATING_BITMAP || fillStyle.fillStyleType == FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP),
(fillStyle.fillStyleType == FILLSTYLE.REPEATING_BITMAP || fillStyle.fillStyleType == FILLSTYLE.CLIPPED_BITMAP),
colorTransform
);
break;
}
} else {
// Font shapes define no fillstyles per se, but do reference fillstyle index 1,
// which represents the font color. We just report null in this case.
beginFill(null, null);
}
}
if (posX != e.getFromX() || posY != e.getFromY()) {
moveTo(e.getFromX(), e.getFromY(), e.getFromEndX(), e.getFromEndY());
}
if (e instanceof CurvedMorphEdge) {
CurvedMorphEdge c = (CurvedMorphEdge) e;
curveTo(c.getControlX(), c.getControlY(), c.toX, c.toY, c.getControlEndX(), c.getControlEndY(), c.toEndX, c.toEndY);
} else {
lineTo(e.getToX(), e.getToY(), e.getToEndX(), e.getToEndY());
}
posX = e.getToX();
posY = e.getToY();
}
if (fillStyleIdx != Integer.MAX_VALUE) {
endFill();
}
endFills();
}
}
protected void exportLinePath(int groupIndex) {
List<IMorphEdge> path = createPathFromEdgeMap(_lineEdgeMaps.get(groupIndex));
int posX = Integer.MAX_VALUE;
int posY = Integer.MAX_VALUE;
int lineStyleIdx = Integer.MAX_VALUE;
if (path.size() > 0) {
beginLines();
for (int i = 0; i < path.size(); i++) {
IMorphEdge e = path.get(i);
if (lineStyleIdx != e.getLineStyleIdx()) {
lineStyleIdx = e.getLineStyleIdx();
posX = Integer.MAX_VALUE;
posY = Integer.MAX_VALUE;
LINESTYLE lineStyle = null;
LINESTYLE lineStyleEnd = null;
try {
lineStyle = _lineStyles.get(lineStyleIdx - 1);
lineStyleEnd = _lineStylesEnd.get(lineStyleIdx - 1);
} catch (Exception ex) {
}
if (lineStyle != null) {
String scaleMode = "NORMAL";
boolean pixelHintingFlag = false;
int startCapStyle = LINESTYLE2.ROUND_CAP;
int endCapStyle = LINESTYLE2.ROUND_CAP;
int joinStyle = LINESTYLE2.ROUND_JOIN;
float miterLimitFactor = 3f;
boolean hasFillFlag = false;
if (lineStyle instanceof LINESTYLE2) {
LINESTYLE2 lineStyle2 = (LINESTYLE2) lineStyle;
if (lineStyle2.noHScaleFlag && lineStyle2.noVScaleFlag) {
scaleMode = "NONE";
} else if (lineStyle2.noHScaleFlag) {
scaleMode = "VERTICAL";
} else if (lineStyle2.noVScaleFlag) {
scaleMode = "HORIZONTAL";
}
pixelHintingFlag = lineStyle2.pixelHintingFlag;
startCapStyle = lineStyle2.startCapStyle;
endCapStyle = lineStyle2.endCapStyle;
joinStyle = lineStyle2.joinStyle;
miterLimitFactor = lineStyle2.miterLimitFactor;
hasFillFlag = lineStyle2.hasFillFlag;
}
lineStyle(
lineStyle.width,
lineStyleEnd.width,
colorTransform == null ? lineStyle.color : colorTransform.apply(lineStyle.color),
colorTransform == null ? lineStyleEnd.color : colorTransform.apply(lineStyleEnd.color),
pixelHintingFlag,
scaleMode,
startCapStyle,
endCapStyle,
joinStyle,
miterLimitFactor);
if (hasFillFlag) {
LINESTYLE2 lineStyle2 = (LINESTYLE2) lineStyle;
FILLSTYLE fillStyle = lineStyle2.fillType;
LINESTYLE2 lineStyle2End = (LINESTYLE2) lineStyleEnd;
FILLSTYLE fillStyleEnd = lineStyle2End.fillType;
switch (fillStyle.fillStyleType) {
case FILLSTYLE.LINEAR_GRADIENT:
case FILLSTYLE.RADIAL_GRADIENT:
case FILLSTYLE.FOCAL_RADIAL_GRADIENT:
// Gradient fill
Matrix matrix = new Matrix(fillStyle.gradientMatrix);
Matrix matrixEnd = new Matrix(fillStyleEnd.gradientMatrix);
lineGradientStyle(
fillStyle.fillStyleType,
fillStyle.gradient.gradientRecords,
fillStyleEnd.gradient.gradientRecords,
matrix,
matrixEnd,
fillStyle.gradient.spreadMode,
fillStyle.gradient.interpolationMode,
(fillStyle.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyle.gradient).focalPoint : 0,
(fillStyleEnd.gradient instanceof FOCALGRADIENT) ? ((FOCALGRADIENT) fillStyleEnd.gradient).focalPoint : 0
);
break;
}
}
} else {
// We should never get here
lineStyle(1, 1, new RGB(Color.black), new RGB(Color.BLACK), false, "NORMAL", 0, 0, 0, 3);
}
}
if (posX != e.getFromX() || posY != e.getFromY()) {
moveTo(e.getFromX(), e.getFromY(), e.getFromEndX(), e.getFromEndY());
}
if (e instanceof CurvedMorphEdge) {
CurvedMorphEdge c = (CurvedMorphEdge) e;
curveTo(c.getControlX(), c.getControlY(), c.toX, c.toY, c.getControlEndX(), c.getControlEndY(), c.toEndX, c.toEndY);
} else {
lineTo(e.getToX(), e.getToY(), e.getToEndX(), e.getToEndY());
}
posX = e.getToX();
posY = e.getToY();
}
endLines();
}
}
protected List<IMorphEdge> createPathFromEdgeMap(Map<Integer, List<IMorphEdge>> edgeMap) {
List<IMorphEdge> newPath = new ArrayList<>();
List<Integer> styleIdxArray = new ArrayList<>();
for (Integer styleIdx : edgeMap.keySet()) {
styleIdxArray.add(styleIdx);
}
Collections.sort(styleIdxArray);
for (int i = 0; i < styleIdxArray.size(); i++) {
appendEdges(newPath, edgeMap.get(styleIdxArray.get(i)));
}
return newPath;
}
protected void cleanEdgeMap(Map<Integer, List<IMorphEdge>> edgeMap) {
for (Integer styleIdx : edgeMap.keySet()) {
List<IMorphEdge> subPath = edgeMap.get(styleIdx);
if (subPath != null && subPath.size() > 0) {
int idx;
IMorphEdge prevEdge = null;
List<IMorphEdge> tmpPath = new ArrayList<>();
Map<Long, List<IMorphEdge>> coordMap = createCoordMap(subPath);
while (subPath.size() > 0) {
idx = 0;
while (idx < subPath.size()) {
if (prevEdge != null) {
IMorphEdge subPathEdge = subPath.get(idx);
if (prevEdge.getToX() != subPathEdge.getFromX() || prevEdge.getToY() != subPathEdge.getFromY()) {
IMorphEdge edge = findNextEdgeInCoordMap(coordMap, prevEdge);
if (edge != null) {
idx = subPath.indexOf(edge);
} else {
idx = 0;
prevEdge = null;
}
continue;
}
}
IMorphEdge edge = subPath.remove(idx);
tmpPath.add(edge);
removeEdgeFromCoordMap(coordMap, edge);
prevEdge = edge;
}
}
edgeMap.put(styleIdx, tmpPath);
}
}
}
protected Map<Long, List<IMorphEdge>> createCoordMap(List<IMorphEdge> path) {
Map<Long, List<IMorphEdge>> coordMap = new HashMap<>();
for (int i = 0; i < path.size(); i++) {
IMorphEdge edge = path.get(i);
long fromLong = (((long) edge.getFromX()) << 32) | (edge.getFromY() & 0xffffffffL);
List<IMorphEdge> coordMapArray = coordMap.get(fromLong);
if (coordMapArray == null) {
List<IMorphEdge> list = new ArrayList<>();
list.add(path.get(i));
coordMap.put(fromLong, list);
} else {
coordMapArray.add(path.get(i));
}
}
return coordMap;
}
protected void removeEdgeFromCoordMap(Map<Long, List<IMorphEdge>> coordMap, IMorphEdge edge) {
long fromLong = (((long) edge.getFromX()) << 32) | (edge.getFromY() & 0xffffffffL);
List<IMorphEdge> coordMapArray = coordMap.get(fromLong);
if (coordMapArray != null) {
if (coordMapArray.size() == 1) {
coordMap.remove(fromLong);
} else {
int i = coordMapArray.indexOf(edge);
if (i > -1) {
coordMapArray.remove(i);
}
}
}
}
protected IMorphEdge findNextEdgeInCoordMap(Map<Long, List<IMorphEdge>> coordMap, IMorphEdge edge) {
long toLong = (((long) edge.getToX()) << 32) | (edge.getToY() & 0xffffffffL);
List<IMorphEdge> coordMapArray = coordMap.get(toLong);
if (coordMapArray != null && coordMapArray.size() > 0) {
return coordMapArray.get(0);
}
return null;
}
protected void appendFillStyles(List<FILLSTYLE> v1, FILLSTYLE[] v2) {
v1.addAll(Arrays.asList(v2));
}
protected void appendLineStyles(List<LINESTYLE> v1, LINESTYLE[] v2) {
v1.addAll(Arrays.asList(v2));
}
protected void appendEdges(List<IMorphEdge> v1, List<IMorphEdge> v2) {
for (int i = 0; i < v2.size(); i++) {
v1.add(v2.get(i));
}
}
}