gt:                 if (lineStyleIdx != e.getLineStyleIdx()) {
context: /*
   *  Copyright (C) 2010-2015 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
                                  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.apply(fillStyle.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);
  