Esempio n. 1
0
  private DiscreteInlineOperation handle(DiscreteInlineOperation operation, boolean addToRowWidth) {
    int advanceCount = operation.getAdvanceCount();
    int increaseCount = operation.getIncreaseCount();

    // can't handle colors at this point
    if (operation instanceof YarnReferenceHolder
        && ((YarnReferenceHolder) operation).getYarnIdRef() != null) {
      return null;
    }

    if (dynamicFirstRowCastOn) {
      // dynamically cast on the advance count (since all stitches are
      // unaccounted for)
      // then slip them in reverse so that we can work them "normally"
      renderingContext.getEngine().castOn(new InlineCastOn(advanceCount));
      renderingContext.getEngine().reverseSlip(advanceCount);
    }
    StitchNature stitchNature =
        operation instanceof StitchNatureProducer
            ? ((StitchNatureProducer) operation).getStitchNatureProduced()
            : null;
    if (addToRowWidth) {
      this.currentRowInfo.addToRowWidth(advanceCount + increaseCount);
    }
    advanceAndIncrease(advanceCount, increaseCount, stitchNature);

    return operation;
  }
Esempio n. 2
0
  protected InlineOperation handle(WorkEven object) {
    // A WorkEven means to knit knits and purl purls
    int numberOfTimes = object.getNumberOfTimes() == null ? 1 : object.getNumberOfTimes();
    List<DiscreteInlineOperation> newOperations =
        new ArrayList<DiscreteInlineOperation>(numberOfTimes);
    for (int i = 0; i < numberOfTimes; i++) {
      StitchNature currentStitchNature =
          renderingContext.getEngine().peekAtNextStitch().getCurrentNature();
      // reverse the stitch nature if working from the wrong side
      if (renderingContext.getEngine().getDirection() == Direction.BACKWARDS) {
        currentStitchNature = StitchNature.reverse(currentStitchNature);
      }

      // knit the knits and purl the purls
      if (currentStitchNature == StitchNature.KNIT) {
        newOperations.add(new Knit(1, null, object.getYarnIdRef()));
      } else { // lastOperation == StitchOperation.PURL
        newOperations.add(new Purl(1, null, object.getYarnIdRef()));
      }
      this.currentRowInfo.addToRowWidth(1);
      advanceAndIncrease(1, 0, currentStitchNature);
    }
    return newOperations.size() == 1 ? newOperations.get(0) : new OperationGroup(newOperations);
  }
Esempio n. 3
0
 protected void advanceAndIncrease(int advanceCount, int increaseCount, StitchNature nature) {
   if (increaseCount < 0) {
     // decrease the number specified by increaseCount
     for (int i = 0; i > increaseCount; i--) {
       renderingContext.getEngine().knitTwoTogether();
       renderingContext.getEngine().reverseSlip();
     }
   } else if (increaseCount > 0) {
     // increase the number specified by increaseCount
     for (int i = 0; i < increaseCount; i++) {
       renderingContext.getEngine().increase(new Increase(1));
       renderingContext.getEngine().reverseSlip();
     }
   }
   // advance the engine the number that this operations says to advance
   // plus the increases
   if (nature == null) {
     renderingContext.getEngine().slip(advanceCount + increaseCount);
   } else if (nature == StitchNature.PURL) {
     renderingContext.getEngine().purl(advanceCount + increaseCount);
   } else { // nature == StitchNature.KNIT
     renderingContext.getEngine().knit(advanceCount + increaseCount);
   }
 }
Esempio n. 4
0
  public Analysis analyzeInstruction(
      Instruction originalInstruction,
      RepeatInstruction repeatInstruction,
      boolean fromInstructionDefinition) {
    this.maxWidth = 0;
    this.rowInfos.clear();
    this.currentRowInfo = null;
    this.currentlyRepeating = false;
    this.shape = KnittingShape.FLAT;

    Object engineState = renderingContext.getEngine().save();

    if (fromInstructionDefinition && originalInstruction.getStartingStitchCount() != null) {
      renderingContext.getEngine().castOn(originalInstruction.getStartingStitchCount(), false);
    } else {
      this.dynamicFirstRowCastOn = fromInstructionDefinition;
    }

    int startingStitches = renderingContext.getEngine().getTotalNumberOfStitchesInRow();

    try {
      if (!originalInstruction.hasRows()) {
        // cannot handle for-each-row-in-instruction yet. Possibly this
        // would be expanded ahead of time.
        log.info("Cannot handle an Instruction whose operations are not made up entirely of Rows");
        return new Analysis();
      }

      List<Row> newRows = analyzeInstructionOnce(originalInstruction);
      if (newRows == null) {
        return new Analysis();
      }

      // TODO RepeatInstruction analysis here....

      // FIXME for now, simply refuse to chart if the chart is unbalanced
      // and there is a known repeat-instruction
      if (!fromInstructionDefinition && repeatInstruction != null) {
        int endingStitches = renderingContext.getEngine().getTotalNumberOfStitchesInRow();
        if (startingStitches != endingStitches) {
          return new Analysis();
        }
      }

      // if we do tack on rows as the result of a repeat-instruction,
      // make sure we give the new instruction an unclassified ID instead
      // of the original ID. We don't want someone else adding a
      // repeat-instruction to the original + repeat-instruction chart.

      // end RepeatInstruction analysis

      Instruction newInstruction = new Instruction(originalInstruction, newRows);

      Analysis result = new Analysis();
      result.setInstructionToUse(newInstruction);
      result.setChartable(true);
      result.setMaxWidth(this.maxWidth);
      result.setRowInfos(this.rowInfos);
      result.setContainsNoStitchOperations(this.containsNoStitchOperations);
      result.setKnittingShape(this.shape);
      result.setStartingSide(this.startingSide);
      return result;
    } finally {
      renderingContext.getEngine().restore(engineState);
    }
  }
Esempio n. 5
0
 protected InlineOperation handle(PlaceMarker object) {
   renderingContext.getEngine().placeMarker();
   return object;
 }
Esempio n. 6
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;
    }
  }
Esempio n. 7
0
  protected Row analyzeRow(Row originalRow) {
    KnittingEngine engine = renderingContext.getEngine();
    // can't handle short rows
    if (originalRow.isShortRow()) {
      return null;
    }
    // can't handle colors (right now)
    if (originalRow.getYarnIdRef() != null) {
      return null;
    }

    List<InlineOperation> newOperations = new ArrayList<InlineOperation>();
    Row newRow = new Row(originalRow, newOperations);
    this.currentRowInfo = new RowInfo();

    // Begin the row for the engine
    if (dynamicFirstRowCastOn) {
      // if this is an instruction definition, infer the intended shape
      // from what is specified by the first row's shape.
      // If nothing is specified, flat knitting is assumed.
      if (originalRow.getType() != null) {
        this.shape = originalRow.getType();
      }
      // cast on one stitch so that we can start a new row below
      engine.castOn(1, false);
    }
    engine.startNewRow();
    if (this.startingSide == null) {
      this.startingSide = Side.RIGHT;
      if (dynamicFirstRowCastOn && originalRow.getSide() == Side.WRONG) {
        this.startingSide = Side.WRONG;
        engine.knit();
        engine.endRow();
        engine.startNewRow();
      } else if (engine.getDirection() == Direction.BACKWARDS) {
        this.startingSide = Side.WRONG;
      }
    }

    // Walk through all of the row's operations and see how it affects the
    // counts
    for (InlineOperation operation : originalRow.getOperations()) {
      InlineOperation newOperation = handle(operation);
      // if null is returned, we cannot chart, so return null up the chain
      if (newOperation == null) {
        return null;
      }
      newOperations.add(newOperation);
    }

    // End the row for the engine
    if (dynamicFirstRowCastOn) {
      // remove the "extra" stitch we created in order to start the row.
      engine.reverseSlip(1);
      // don't swallow the real stitch's nature
      StitchNature stitchNature = engine.peekAtNextStitch().getCurrentNature();
      if (stitchNature == StitchNature.PURL) {
        engine.purlTwoTogether();
      } else {
        engine.knitTwoTogether();
      }
      // now pretend like all is normal
      dynamicFirstRowCastOn = false;
    }
    engine.endRow();

    // if this row pushed the bounds of the previously recorded maximum
    // width, record the new max width
    if (currentRowInfo.getRowWidth() > maxWidth) {
      maxWidth = currentRowInfo.getRowWidth();
    }

    // if (!repeatInCurrentRow) {
    // resetGlobalRepeatTracker();
    // }

    this.rowInfos.add(currentRowInfo);
    return newRow;
  }
Esempio n. 8
0
  @Override
  public void end(Object element, Renderer renderer) {
    RenderingContext context = renderer.getRenderingContext();
    // retrieve the "before" and "after" visiting states of the knitting
    // engine so that we have something to go back to
    Object beforeVisitingEngineState = context.getPatternState().retrieveSavedEngineState();
    Object afterVisitingEngineState = context.getEngine().save();
    // start with the state before the instruction was sent through the
    // engine
    renderer.getRenderingContext().getEngine().restore(beforeVisitingEngineState);

    // retrieve the instruction from the knitting context's repository
    // rather than the instruction from the document, as the rows
    // may have been expanded.
    PatternRepository repository = context.getPatternRepository();
    Instruction instruction = (Instruction) element;
    String id = instruction.getId();
    Instruction candidateInstruction =
        context.getKnittingContext().getPatternRepository().getBlockInstruction(id);

    // have the renderer evaluate the instruction and return a different
    // instruction if it wants to change anything. Pass it a sibling
    // repeat-instruction
    // if it can be found.
    Instruction instructionToUse =
        renderer.evaluateInstruction(
            candidateInstruction, findSiblingRepeatInstruction(instruction, renderer));
    // if the renderer didn't alter anything, it returns null
    if (instructionToUse == null) {
      instructionToUse = candidateInstruction;
    }

    InstructionInfo instructionInfo;
    if (instructionToUse.hasLabelOrMessageKey()) {
      instructionInfo =
          deriveInstructionInfo(instructionToUse, deriveLabel(instruction, repository));
      repository.addGlobalInstruction(instructionInfo);
    } else {
      instructionInfo = deriveInstructionInfo(instructionToUse, null);
      repository.addLocalInstruction(instructionInfo);
    }

    context.getPatternState().setCurrentInstructionInfo(instructionInfo);
    if (instructionInfo.getRowRange() != null) {
      setLastExpressedRowNumber(instructionInfo.getRowRange().getMaximumInteger(), context);
      // if setLastExpressedRowNumber resets the local instructions, this
      // would also clear out the currently executing instruction. We
      // don't want that to happen, so add it back in.
      // FIXME this is really backwards; maybe we should redo this
      if (repository.getInstruction(instruction.getId()) == null) {
        repository.addLocalInstruction(instructionInfo);
      }
    }
    renderer.beginInstruction(instructionInfo);
    InstructionController embeddedController = new InstructionController(getEventHandlerFactory());
    embeddedController.visitInstruction(instructionToUse, renderer);
    context.getPatternState().clearCurrentInstructionInfo();
    renderer.endInstruction();

    // restore to the way things were (after engine processing but before
    // this method was called)
    renderer.getRenderingContext().getEngine().restore(afterVisitingEngineState);
  }