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()); }
/** * 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"); } }
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; } }