00001 package edu.stanford.hci.r3.render;
00002
00003 import java.awt.Color;
00004 import java.awt.Graphics2D;
00005 import java.awt.geom.AffineTransform;
00006 import java.io.File;
00007 import java.io.FileNotFoundException;
00008 import java.io.FileOutputStream;
00009 import java.util.List;
00010
00011 import javax.media.jai.TiledImage;
00012
00013 import com.lowagie.text.Document;
00014 import com.lowagie.text.DocumentException;
00015 import com.lowagie.text.Rectangle;
00016 import com.lowagie.text.pdf.PdfContentByte;
00017 import com.lowagie.text.pdf.PdfWriter;
00018
00019 import edu.stanford.hci.r3.paper.Region;
00020 import edu.stanford.hci.r3.paper.Sheet;
00021 import edu.stanford.hci.r3.pattern.TiledPattern;
00022 import edu.stanford.hci.r3.pattern.TiledPatternGenerator;
00023 import edu.stanford.hci.r3.pattern.coordinates.PatternLocationToSheetLocationMapping;
00024 import edu.stanford.hci.r3.pattern.coordinates.conversion.TiledPatternCoordinateConverter;
00025 import edu.stanford.hci.r3.pattern.output.PDFPatternGenerator;
00026 import edu.stanford.hci.r3.units.Pixels;
00027 import edu.stanford.hci.r3.units.Points;
00028 import edu.stanford.hci.r3.units.Units;
00029 import edu.stanford.hci.r3.units.coordinates.Coordinates;
00030 import edu.stanford.hci.r3.util.DebugUtils;
00031 import edu.stanford.hci.r3.util.MathUtils;
00032 import edu.stanford.hci.r3.util.graphics.GraphicsUtils;
00033 import edu.stanford.hci.r3.util.graphics.ImageUtils;
00034 import edu.stanford.hci.r3.util.graphics.JAIUtils;
00035
00051 public class SheetRenderer {
00052
00056 private TiledPatternGenerator generator;
00057
00061 private File mostRecentlyRenderedPDFFile;
00062
00066 private Color patternColor = Color.BLACK;
00067
00072 private int patternDotSizeAdjustment = 0;
00073
00079 private PatternLocationToSheetLocationMapping patternInformation;
00080
00085 protected boolean renderActiveRegionsWithPattern = true;
00086
00090 protected Sheet sheet;
00091
00097 public SheetRenderer(Sheet s) {
00098 this(s, new TiledPatternGenerator());
00099 }
00100
00108 public SheetRenderer(Sheet s, TiledPatternGenerator patternGenerator) {
00109 sheet = s;
00110 patternInformation = sheet.getPatternLocationToSheetLocationMapping();
00111 generator = patternGenerator;
00112 }
00113
00117 public PatternLocationToSheetLocationMapping getPatternInformation() {
00118 return patternInformation;
00119 }
00120
00132 private void renderPattern(PdfContentByte cb) {
00133
00134 final List<Region> regions = sheet.getRegions();
00135
00136
00137 final PDFPatternGenerator pgen = new PDFPatternGenerator(cb, sheet.getWidth(), sheet.getHeight());
00138 pgen.setPatternColor(patternColor);
00139
00140
00141 pgen.adjustPatternSize(patternDotSizeAdjustment);
00142
00143
00144 for (Region r : regions) {
00145 if (!r.isActive()) {
00146 continue;
00147 }
00148
00149 DebugUtils.println("-------------");
00150
00151
00152 Coordinates regionOffset = sheet.getRegionOffset(r);
00153
00154
00155
00156
00157
00158 final Units scaledWidth = r.getWidth();
00159 final Units scaledHeight = r.getHeight();
00160
00161
00162
00163
00164
00165 final TiledPattern pattern = generator.getPattern(scaledWidth, scaledHeight);
00166
00167 DebugUtils.println("Rendering Pattern for " + r.getName());
00168
00169 pgen.renderPattern(pattern,
00170 Units.add(r.getOriginX(), regionOffset.getX()),
00171 Units.add(r.getOriginY(), regionOffset.getY()));
00172
00173
00174
00175
00176 final TiledPatternCoordinateConverter tiledPatternInRegion = (TiledPatternCoordinateConverter) patternInformation
00177 .getPatternBoundsOfRegion(r);
00178 tiledPatternInRegion.setPatternInformationByReadingItFrom(pattern);
00179
00180
00181
00182
00183
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 }
00201
00211 public void renderToG2D(Graphics2D g2d) {
00212
00213 g2d.setRenderingHints(GraphicsUtils.getBestRenderingHints());
00214
00215 final List<Region> regions = sheet.getRegions();
00216
00217
00218 for (Region r : regions) {
00219
00220
00221 final AffineTransform currTransform = new AffineTransform(g2d.getTransform());
00222 DebugUtils.println("Rendering " + r.getName());
00223 final Coordinates regionOffset = sheet.getRegionOffset(r);
00224 final double xOffsetPts = regionOffset.getX().getValueInPoints();
00225 final double yOffsetPts = regionOffset.getY().getValueInPoints();
00226
00227
00228 g2d.translate((int) xOffsetPts, (int) yOffsetPts);
00229 r.getRenderer().renderToG2D(g2d);
00230 g2d.setTransform(currTransform);
00231 }
00232 }
00233
00239 public void renderToJPEG(File file) {
00240 renderToJPEG(file, Pixels.ONE);
00241 }
00242
00250 public void renderToJPEG(File destJPEGFile, Pixels destUnits) {
00251 final Units width = sheet.getWidth();
00252 final Units height = sheet.getHeight();
00253
00254 final double scale = Points.ONE.getConversionTo(destUnits);
00255
00256 final int w = MathUtils.rint(width.getValueIn(destUnits));
00257 final int h = MathUtils.rint(height.getValueIn(destUnits));
00258 final TiledImage image = JAIUtils.createWritableBufferWithoutAlpha(w, h);
00259 final Graphics2D graphics2D = image.createGraphics();
00260 graphics2D.setRenderingHints(GraphicsUtils.getBestRenderingHints());
00261
00262
00263
00264
00265 graphics2D.setTransform(AffineTransform.getScaleInstance(scale, scale));
00266
00267
00268 graphics2D.setColor(Color.WHITE);
00269 graphics2D.fillRect(0, 0, w, h);
00270
00271 renderToG2D(graphics2D);
00272 graphics2D.dispose();
00273 ImageUtils.writeImageToJPEG(image.getAsBufferedImage(), destJPEGFile);
00274 }
00275
00282 public void renderToPDF(File destPDFFile) {
00283 try {
00284 final FileOutputStream fileOutputStream = new FileOutputStream(destPDFFile);
00285
00286 final Rectangle pageSize = new Rectangle(0, 0, (int) Math.round(sheet.getWidth()
00287 .getValueInPoints()), (int) Math.round(sheet.getHeight().getValueInPoints()));
00288
00289
00290 final Document doc = new Document(pageSize, 0, 0, 0, 0);
00291 final PdfWriter writer = PdfWriter.getInstance(doc, fileOutputStream);
00292 doc.open();
00293
00294 final PdfContentByte topLayer = writer.getDirectContent();
00295 final PdfContentByte bottomLayer = writer.getDirectContentUnder();
00296 renderToPDFContentLayers(destPDFFile, topLayer, bottomLayer);
00297
00298 doc.close();
00299
00300
00301 savePatternInformation();
00302 } catch (FileNotFoundException e) {
00303 e.printStackTrace();
00304 } catch (DocumentException e) {
00305 e.printStackTrace();
00306 }
00307 }
00308
00314 protected void renderToPDFContentLayers(File destPDFFile, PdfContentByte topLayer,
00315 PdfContentByte bottomLayer) {
00316 mostRecentlyRenderedPDFFile = destPDFFile;
00317
00318 final Units width = sheet.getWidth();
00319 final Units height = sheet.getHeight();
00320 final float wPoints = (float) width.getValueInPoints();
00321 final float hPoints = (float) height.getValueInPoints();
00322
00323
00324 final Graphics2D g2dOver = topLayer.createGraphicsShapes(wPoints, hPoints);
00325
00326 renderToG2D(g2dOver);
00327
00328
00329 g2dOver.dispose();
00330
00331
00332 if (renderActiveRegionsWithPattern) {
00333 DebugUtils.println("Rendering Pattern");
00334
00335
00336
00337
00338 renderPattern(topLayer);
00339 }
00340 }
00341
00346 public void savePatternInformation() {
00347 if (mostRecentlyRenderedPDFFile == null) {
00348 System.err.println("SheetRenderer: We cannot save the pattern information "
00349 + "without a destination file. Please render a PDF first "
00350 + "so we know where to put the pattern configuration file!");
00351 } else {
00352 File parentDir = mostRecentlyRenderedPDFFile.getParentFile();
00353 String fileName = mostRecentlyRenderedPDFFile.getName();
00354 if (fileName.contains(".pdf")) {
00355 fileName = fileName.replace(".pdf", ".patternInfo.xml");
00356 } else {
00357 fileName = fileName + ".patternInfo.xml";
00358 }
00359 File destFile = new File(parentDir, fileName);
00360 savePatternInformation(destFile);
00361 }
00362 }
00363
00370 public void savePatternInformation(File patternInfoFile) {
00371
00372 patternInformation.saveConfigurationToXML(patternInfoFile);
00373 DebugUtils.println("Pattern Information saved to " + patternInfoFile.getAbsolutePath());
00374 }
00375
00379 public void setPatternColor(Color pColor) {
00380 patternColor = pColor;
00381 }
00382
00390 public void setPatternGenerator(TiledPatternGenerator tiledPatternGenerator) {
00391 generator = tiledPatternGenerator;
00392 }
00393
00397 public void setRenderActiveRegionsWithPattern(boolean activeWithPattern) {
00398 renderActiveRegionsWithPattern = activeWithPattern;
00399 }
00400
00404 public void useLargerPatternDots() {
00405 patternDotSizeAdjustment++;
00406 }
00407
00411 public void useSmallerPatternDots() {
00412 patternDotSizeAdjustment--;
00413 }
00414 }