private void assertOriginalState() {
   // capture state right after the cast-on row before startNewRow() is
   // called
   assertEquals(1, engine.getTotalRowsCompleted());
   assertEquals(1, engine.getCurrentRowNumber());
   assertEquals(40, engine.getTotalNumberOfStitchesInRow());
   assertEquals(0, engine.getStitchesRemainingInRow());
   assertEquals(Direction.FORWARDS, engine.getDirection());
   assertEquals(KnittingShape.FLAT, engine.getKnittingShape());
 }
Exemple #2
0
 /**
  * A repeat is necessary only when its until condition has not yet been met.
  *
  * @param repeat
  * @param engine
  * @return
  */
 protected boolean isRepeatNecessary(Repeat repeat, KnittingEngine engine) {
   Until until = repeat.getUntil();
   Integer value = repeat.getValue();
   switch (until) {
     case TIMES:
       // repeat if we have to repeat more than 0 times
       return value > 0;
     case BEFORE_END:
       return engine.getStitchesRemainingInRow() > value;
     case END:
       return engine.getStitchesRemainingInRow() > 0;
     case BEFORE_GAP:
       return engine.getStitchesToGap() > value;
     case BEFORE_MARKER:
       return engine.getStitchesToNextMarker() > value;
     case MARKER:
       return engine.getStitchesToNextMarker() > 0;
     default:
       throw new RuntimeException("The until value [" + until + "] has not been properly coded");
   }
 }
Exemple #3
0
  protected InlineOperation handle(Repeat oldRepeat) {

    // initialize variables for this method
    KnittingEngine engine = renderingContext.getEngine();
    Until until = oldRepeat.getUntil();
    Integer value = oldRepeat.getValue();

    // ensure that we can continue to analyze this instruction for charting
    if (dynamicFirstRowCastOn && until != Until.TIMES) {
      log.info(
          "Cannot chart this instruction because it is both defined in the header (i.e. without a knitting context) "
              + "and the first row has a repeat section that requires a knitting context."
              + "This can be fixed either by declaring the 'until' attribute of the repeat in the first row to be of type 'times', "
              + "or by including the repeats in the directions "
              + "section of the pattern instead of in the header.");
      return null;
    }
    if (currentlyRepeating) {
      log.info("Cannot currently chart nested repeats. This feature may be expanded in the future");
      return null;
    }

    // see if we need to repeat at all. If not, just return "0 repeats"
    if (!isRepeatNecessary(oldRepeat, engine)) {
      return new Repeat(Until.TIMES, 0);
    }

    // at this point, we have to do the repeat (1 or more times)
    currentlyRepeating = true;

    // start gathering up information for the new repeat. Our goal is to
    // convert all repeats
    // into an until value that represents TIMES. This is so we won't need
    // the engine to chart.
    List<DiscreteInlineOperation> newOperations = new ArrayList<DiscreteInlineOperation>();

    // gather current (pre-repeat) state
    Object engineState = engine.save();
    int originalChartWidth = this.currentRowInfo.getRowWidth();

    // walk through all the instructions of this repeat ONCE to calculate
    // the advance and increase count. If we find a work-even, remove
    // the repeat all together and completely expand the row
    boolean contextualOperationFound = false;
    for (InlineOperation operation : oldRepeat.getOperations()) {
      if (!contextualOperationFound && operation instanceof WorkEven) {
        contextualOperationFound = true;
        // if we find out there are contextual operations, clear out
        // newOperations
        // and wait for the actual repeat. We'll gather that info then.
        newOperations.clear();
        break;
      }
      InlineOperation newOperation = handle(operation);
      // if a non-discrete inline operation or null is returned, we cannot
      // chart, so return null up the chain
      if (!(newOperation instanceof DiscreteInlineOperation)) {
        return null;
      }
      newOperations.add((DiscreteInlineOperation) newOperation);
    }

    // reset the engine to the state before we repeated once
    engine.restore(engineState);
    this.currentRowInfo.setRowWidth(originalChartWidth);

    int counter = 0;
    switch (until) {
      case TIMES:
        for (int i = 0; i < value; i++) {
          // advanceAndIncrease(advanceCount, increaseCount);
          for (InlineOperation operation : oldRepeat.getOperations()) {
            DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation);
            if (contextualOperationFound) {
              newOperations.add(newOperation);
            }
          }
        }
        counter = value;
        break;
      case BEFORE_END:
        while (engine.getStitchesRemainingInRow() > value) {
          // advanceAndIncrease(advanceCount, increaseCount);
          for (InlineOperation operation : oldRepeat.getOperations()) {
            DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation);
            if (contextualOperationFound) {
              newOperations.add(newOperation);
            }
          }
          counter++;
        }
        break;
      case END:
        while (engine.getStitchesRemainingInRow() > 0) {
          // advanceAndIncrease(advanceCount, increaseCount);
          for (InlineOperation operation : oldRepeat.getOperations()) {
            DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation);
            if (contextualOperationFound) {
              newOperations.add(newOperation);
            }
          }
          counter++;
        }
        break;
      case BEFORE_GAP:
        while (engine.getStitchesToGap() > value) {
          // advanceAndIncrease(advanceCount, increaseCount);
          for (InlineOperation operation : oldRepeat.getOperations()) {
            DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation);
            if (contextualOperationFound) {
              newOperations.add(newOperation);
            }
          }
          counter++;
        }
        break;
      case BEFORE_MARKER:
        while (engine.getStitchesToNextMarker() > value) {
          // advanceAndIncrease(advanceCount, increaseCount);
          for (InlineOperation operation : oldRepeat.getOperations()) {
            DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation);
            if (contextualOperationFound) {
              newOperations.add(newOperation);
            }
          }
          counter++;
        }
        break;
      case MARKER:
        while (engine.getStitchesToNextMarker() > 0) {
          // advanceAndIncrease(advanceCount, increaseCount);
          for (InlineOperation operation : oldRepeat.getOperations()) {
            DiscreteInlineOperation newOperation = (DiscreteInlineOperation) handle(operation);
            if (contextualOperationFound) {
              newOperations.add(newOperation);
            }
          }
          counter++;
        }
        break;
      default:
        throw new RuntimeException("The until value [" + until + "] has not been properly coded");
    }

    currentlyRepeating = false;
    if (contextualOperationFound) {
      // make a stitch group out of all of the gathered operations if
      // we are dealing with work even operations
      return new OperationGroup(newOperations);
    } else {
      Repeat newRepeat = new Repeat();
      newRepeat.setOperations(newOperations);
      newRepeat.setUntil(Until.TIMES);
      newRepeat.setValue(counter);
      return newRepeat;
    }
  }