docs: public void publish(boolean block, boolean skip) {
  		
  		//Sort components so we always get the same timline order...
  //		Arrays.sort(components);
  		
  		//If blocking behavior has been requested, wait until any previous call 
  		//to the image encoding thread has finished. The rest of the
  		//code in this function is written from an "encode if possible" perspective.
  		if (!skip) imageEncoder.waitUntilFinished();
  
  		if(!imageEncoder.isWorking()) {
  			timelinesToRefresh.clear();
  			if (bounds != null) {
  				min = bounds.min+origin;
  				max = bounds.max+origin;
  			}
  			else {
  				min = origin;
  				max = Long.MIN_VALUE;
  			}
  			for(int tl = 0; tl < components.length; tl++) {
  				String comp = components[tl];
  				SymbolicTimeline stl  = null;
  				//synchronized(ans) {
  				synchronized(an) {
  					//stl = new SymbolicTimeline(ans, comp);
  					if (markingsToExclude != null) stl = new SymbolicTimeline(an, comp, markingsToExclude);
  					else stl = new SymbolicTimeline(an, comp);
  				}
  				if (bounds == null) {
  					if (stl.getPulses()[stl.getPulses().length-1] > max) max = stl.getPulses()[stl.getPulses().length-1];
  				}
  				timelinesToRefresh.add(stl);
  			}
  			long delta = 0;
  			double portionBefore = 0.9;
  			if (slidingWindow && bounds != null) {
  				delta = bounds.max-bounds.min;				
  				if (((double)timeNow)/temporalResolution > origin+((double)delta)*portionBefore) {
  					min = (long)( ((double)timeNow)/(double)temporalResolution  -  ((double)delta)*portionBefore);
  					max = (long)( ((double)timeNow)/(double)temporalResolution  +  ((double)delta)*(1-portionBefore));
  				}
  			}
  			imageEncoder.encodeTimelines(timelinesToRefresh);
  			logger.finest("Image being rendered...");
  		}
  		else {
  			logger.finest("Skipped rendering image.");
  		}
  		
  		//If blocking behavior has been requested, do not return until
  		//the image encoding thread has finished.
  		if (block) imageEncoder.waitUntilFinished();
  	}