PDFPatternGenerator.java

00001 package edu.stanford.hci.r3.pattern.output;
00002 
00003 import java.awt.Color;
00004 import java.awt.geom.AffineTransform;
00005 import java.io.IOException;
00006 
00007 import com.lowagie.text.DocumentException;
00008 import com.lowagie.text.pdf.BaseFont;
00009 import com.lowagie.text.pdf.PdfContentByte;
00010 import com.lowagie.text.pdf.PdfTemplate;
00011 
00012 import edu.stanford.hci.r3.pattern.PatternJitter;
00013 import edu.stanford.hci.r3.pattern.TiledPattern;
00014 import edu.stanford.hci.r3.units.Units;
00015 import edu.stanford.hci.r3.util.DebugUtils;
00016 import edu.stanford.hci.r3.util.MathUtils;
00017 
00045 public class PDFPatternGenerator {
00046 
00050         private static final BaseFont BFONT_TAHOMA = createBaseFontTahoma();
00051 
00055         private static final BaseFont BFONT_ZAPF = createBaseFontZapfDingbats();
00056 
00061         private static final double convertHundredthsOfMMToPoints = 72 / 2540.0;
00062 
00066         private static final double convertPointsToHundredthsOfMM = 2540.0 / 72;
00067 
00071         private static final boolean DEBUG_PATTERN = false;
00072 
00076         private static final int DEFAULT_JITTER = 5;
00077 
00081         private static final int DEFAULT_PADDING = 30;
00082 
00086         private static final int X_FONT_OFFSET = -2;
00087 
00091         private static final int Y_FONT_OFFSET = 9;
00092 
00096         private static BaseFont createBaseFontTahoma() {
00097                 try {
00098                         return BaseFont.createFont("/fonts/tahoma.ttf", BaseFont.CP1252, BaseFont.EMBEDDED);
00099                 } catch (DocumentException e) {
00100                         e.printStackTrace();
00101                 } catch (IOException e) {
00102                         e.printStackTrace();
00103                 }
00104                 return null;
00105         }
00106 
00110         private static BaseFont createBaseFontZapfDingbats() {
00111                 try {
00112                         return BaseFont.createFont(BaseFont.ZAPFDINGBATS, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
00113                 } catch (DocumentException e) {
00114                         e.printStackTrace();
00115                 } catch (IOException e) {
00116                         e.printStackTrace();
00117                 }
00118                 return null;
00119         }
00120 
00124         private PdfContentByte content;
00125 
00129         private BaseFont debugFont;
00130 
00134         private String dotSymbol;
00135 
00139         private PdfTemplate dotTemplate;
00140 
00141         private int fontSize;
00142 
00146         private Units height;
00147 
00151         private Color patternColor = Color.BLACK;
00152 
00156         private BaseFont patternFont;
00157 
00161         private boolean useTemplateInsteadOfFont = true;
00162 
00166         private Units width;
00167 
00178         public PDFPatternGenerator(PdfContentByte cb, Units w, Units h) {
00179                 content = cb;
00180                 width = w;
00181                 height = h;
00182 
00183                 // transforms the content layer ONCE
00184                 // instead of specifying stuff in points (72 in an inch), we can now
00185                 // specify in 1/100 of a millimeter
00186                 // we need to scale down the numbers so when we specify something at 2540,
00187                 // we get only 72 points...
00188                 content.transform(AffineTransform.getScaleInstance(convertHundredthsOfMMToPoints,
00189                                 convertHundredthsOfMMToPoints));
00190 
00191                 if (useTemplateInsteadOfFont) {
00192                         createDotTemplate(0 /* default */);
00193                 }
00194 
00195                 // even if we are using templates, initialize fonts... for debugging
00196                 // initializePatternFont_Tahoma();
00197                 initializePatternFont_Zapf(); // *slightly* smaller file due to built-in font
00198         }
00199 
00205         public void adjustPatternSize(int patternDotSizeAdjustment) {
00206                 if (useTemplateInsteadOfFont) {
00207                         // if template aproach
00208                         createDotTemplate(patternDotSizeAdjustment);
00209                 } else {
00210                         // if font approach
00211                         fontSize += patternDotSizeAdjustment;
00212                 }
00213         }
00214 
00221         private void createDotTemplate(float adjustment) {
00222                 float radiusAdjustment = 0.5f * adjustment;
00223                 final float defaultRadius = 2.8f; // this is key (the right size)
00224                 float xCenter = defaultRadius;
00225                 float yCenter = defaultRadius;
00226 
00227                 // the dot as a pdf template (a rubber stamp)
00228                 dotTemplate = content.createTemplate(2 * xCenter + 1, 2 * yCenter + 1);
00229                 dotTemplate.circle(xCenter, yCenter, defaultRadius + radiusAdjustment);
00230                 dotTemplate.fill();
00231         }
00232 
00236         @SuppressWarnings("unused")
00237         private void initializePatternFont_Tahoma() {
00238                 setPatternFontSize(21);
00239                 debugFont = BFONT_TAHOMA;
00240                 patternFont = BFONT_TAHOMA;
00241                 dotSymbol = "•";
00242         }
00243 
00248         private void initializePatternFont_Zapf() {
00249                 setPatternFontSize(7);
00250                 debugFont = BFONT_TAHOMA;
00251                 patternFont = BFONT_ZAPF;
00252                 dotSymbol = "l";
00253         }
00254 
00263         public void renderPattern(TiledPattern pattern, Units xOrigin, Units yOrigin) {
00264                 // flip the transform so that the top left of the page is 0,0
00265 
00266                 float heightOfPDF = (float) height.getValueInPoints();
00267 
00268                 // convert the origins to Points
00269                 final double xOrigInPoints = xOrigin.getValueInPoints();
00270                 final double yOrigInPoints = yOrigin.getValueInPoints();
00271 
00272                 final int numRows = pattern.getNumTotalRows();
00273                 final int numCols = pattern.getNumTotalColumns();
00274 
00275                 // this actually mirrors everything
00276                 // text will display upside down!
00277                 // this doesn't matter for symmetrical dots, though
00278                 // content.concatCTM(1f, 0f, 0f, -1f, 0f, heightOfPDF);
00279 
00280                 // work in hundredths of a millimeter
00281                 final float heightInHundredths = (float) (heightOfPDF * convertPointsToHundredthsOfMM);
00282 
00283                 // if we use the font approach
00284                 if (!useTemplateInsteadOfFont) {
00285                         content.beginText();
00286                         // GRAY, etc. do not work! The printer will do halftoning, which messes things up.
00287                         content.setFontAndSize(patternFont, fontSize);
00288                 }
00289 
00290                 content.setColorFill(patternColor);
00291                 // content.setColorFill(Color.CYAN);
00292                 // content.setColorFill(Color.BLACK);
00293 
00294                 final int initX = MathUtils.rint(xOrigInPoints * convertPointsToHundredthsOfMM);
00295 
00296                 int gridXPosition = initX;
00297                 int gridYPosition = MathUtils.rint(yOrigInPoints * convertPointsToHundredthsOfMM);
00298 
00299                 DebugUtils.println("PDFPatternGenerator: Dot Position is " + gridXPosition + " " + gridYPosition);
00300 
00301                 int xJitter = 0;
00302                 int yJitter = 0;
00303                 char currentJitterDirection;
00304 
00305                 for (int row = 0; row < numRows; row++) {
00306 
00307                         final String patternRow = pattern.getPatternOnRow(row);
00308                         final int rowLength = patternRow.length();
00309 
00310                         for (int i = 0; i < rowLength; i++) {
00311 
00312                                 // read the direction
00313                                 currentJitterDirection = patternRow.charAt(i);
00314 
00315                                 // reset the jitters (this is key!)
00316                                 xJitter = 0;
00317                                 yJitter = 0;
00318 
00319                                 switch (currentJitterDirection) {
00320                                 case PatternJitter.DOWN:
00321                                         // System.out.print("d");
00322                                         yJitter = DEFAULT_JITTER;
00323                                         break;
00324                                 case PatternJitter.UP:
00325                                         // System.out.print("u");
00326                                         yJitter = -DEFAULT_JITTER;
00327                                         break;
00328                                 case PatternJitter.LEFT:
00329                                         // System.out.print("l");
00330                                         xJitter = -DEFAULT_JITTER;
00331                                         break;
00332                                 case PatternJitter.RIGHT:
00333                                         // System.out.print("r");
00334                                         xJitter = DEFAULT_JITTER;
00335                                         break;
00336                                 }
00337 
00338                                 if (useTemplateInsteadOfFont) {
00339                                         content.addTemplate(dotTemplate, gridXPosition + xJitter, //
00340                                                         heightInHundredths - (gridYPosition + yJitter));
00341                                 } else {
00342                                         content.showTextAligned(PdfContentByte.ALIGN_CENTER, dotSymbol, //
00343                                                         gridXPosition + xJitter + X_FONT_OFFSET, //
00344                                                         heightInHundredths - (gridYPosition + yJitter + Y_FONT_OFFSET), 0);
00345                                 }
00346 
00347                                 gridXPosition += DEFAULT_PADDING;
00348 
00349                         }
00350                         gridXPosition = initX;
00351                         gridYPosition += DEFAULT_PADDING;
00352                         // System.out.println();
00353                 }
00354 
00355                 if (!useTemplateInsteadOfFont) {
00356                         content.endText();
00357                 }
00358         }
00359 
00363         public void setPatternColor(Color c) {
00364                 patternColor = c;
00365         }
00366 
00373         private void setPatternFontSize(int s) {
00374                 fontSize = s;
00375         }
00376 }

Generated on Sat Apr 14 18:21:36 2007 for R3 Paper Toolkit by  doxygen 1.4.7