1 23 24 package org.gjt.sp.jedit.print; 25 26 import javax.swing.text.TabExpander ; 28 import javax.swing.SwingUtilities ; 29 import java.awt.font.*; 30 import java.awt.geom.*; 31 import java.awt.print.*; 32 import java.awt.*; 33 import java.lang.reflect.Method ; 34 import java.util.*; 35 import java.util.List ; 36 37 import org.gjt.sp.jedit.syntax.*; 38 import org.gjt.sp.jedit.*; 39 import org.gjt.sp.util.*; 40 42 45 class BufferPrintable implements Printable 46 { 47 BufferPrintable(PrinterJob job, Object format, 49 View view, Buffer buffer, Font font, boolean header, 50 boolean footer, boolean lineNumbers, boolean color) 51 { 52 this.job = job; 53 this.format = format; 54 this.view = view; 55 this.buffer = buffer; 56 this.font = font; 57 this.header = header; 58 this.footer = footer; 59 this.lineNumbers = lineNumbers; 60 61 styles = GUIUtilities.loadStyles(jEdit.getProperty("print.font"), 62 jEdit.getIntegerProperty("print.fontsize",10),color); 63 styles[Token.NULL] = new SyntaxStyle(textColor,null,font); 64 65 for(int i = 0; i < styles.length; i++) 67 { 68 SyntaxStyle s = styles[i]; 69 if(s.getForegroundColor().equals(Color.WHITE) 70 && s.getBackgroundColor() == null) 71 { 72 styles[i] = new SyntaxStyle( 73 Color.BLACK, 74 styles[i].getBackgroundColor(), 75 styles[i].getFont()); 76 } 77 } 78 79 lineList = new ArrayList<Chunk>(); 80 81 tokenHandler = new DisplayTokenHandler(); 82 } 84 public void print() 86 { 87 try 88 { 89 91 if(format == null) 92 job.print(); 93 else 94 { 95 Method method = PrinterJob.class.getMethod( 96 "print",new Class [] { Class.forName( 97 "javax.print.attribute.PrintRequestAttributeSet") }); 98 method.invoke(job,new Object [] { format }); 99 } 100 } 101 catch(PrinterAbortException ae) 102 { 103 Log.log(Log.DEBUG,this,ae); 104 } 105 catch(Exception e) 106 { 107 Log.log(Log.ERROR,this,e); 108 final String [] args = { e.toString() }; 109 SwingUtilities.invokeLater(new Runnable () 110 { 111 public void run() 112 { 113 GUIUtilities.error(view,"print-error",args); 114 } 115 }); 116 } 117 finally 118 { 119 } 121 } 123 public int print(Graphics _gfx, PageFormat pageFormat, int pageIndex) 125 throws PrinterException 126 { 127 if(frc == null) 130 { 131 frc = ((Graphics2D)_gfx).getFontRenderContext(); 132 Log.log(Log.DEBUG,this,"Font render context is " + frc); 133 } 134 135 Log.log(Log.DEBUG,this,"Asked to print page " + pageIndex); 136 Log.log(Log.DEBUG,this,"Current page is " + currentPage); 137 138 if(pageIndex > currentPage) 139 { 140 for(int i = currentPage; i < pageIndex; i++) 141 { 142 Log.log(Log.DEBUG,this,"Current physical line is now " + currentPageStart); 143 currentPhysicalLine = currentPageStart; 144 printPage(_gfx,pageFormat,i,true); 145 } 146 147 currentPage = pageIndex - 1; 148 Log.log(Log.DEBUG,this,"Current page is now " + currentPage); 149 } 150 151 if(pageIndex == currentPage + 1) 152 { 153 if(end) 154 { 155 Log.log(Log.DEBUG,this,"The end"); 156 return NO_SUCH_PAGE; 157 } 158 159 currentPageStart = currentPhysicalLine; 160 Log.log(Log.DEBUG,this,"#2 - Current physical line is now " + currentPageStart); 161 currentPage = pageIndex; 162 Log.log(Log.DEBUG,this,"#2 - Current page is now " + currentPage); 163 } 164 else if(pageIndex == currentPage) 165 { 166 currentPhysicalLine = currentPageStart; 167 Log.log(Log.DEBUG,this,"#3 - Current physical line is now " + currentPageStart); 168 } 169 170 printPage(_gfx,pageFormat,pageIndex,true); 171 172 return PAGE_EXISTS; 173 } 175 177 private static Color headerColor = Color.lightGray; 179 private static Color headerTextColor = Color.black; 180 private static Color footerColor = Color.lightGray; 181 private static Color footerTextColor = Color.black; 182 private static Color lineNumberColor = Color.gray; 183 private static Color textColor = Color.black; 184 186 private PrinterJob job; 188 private Object format; 189 190 private View view; 191 private Buffer buffer; 192 private Font font; 193 private SyntaxStyle[] styles; 194 private boolean header; 195 private boolean footer; 196 private boolean lineNumbers; 197 198 private int currentPage; 199 private int currentPageStart; 200 private int currentPhysicalLine; 201 private boolean end; 202 203 private LineMetrics lm; 204 private final List <Chunk> lineList; 205 206 private FontRenderContext frc; 207 208 private DisplayTokenHandler tokenHandler; 209 211 private void printPage(Graphics _gfx, PageFormat pageFormat, int pageIndex, 213 boolean actuallyPaint) 214 { 215 Log.log(Log.DEBUG,this,"printPage(" + pageIndex + ',' + actuallyPaint + ')'); 216 Graphics2D gfx = (Graphics2D)_gfx; 217 gfx.setFont(font); 218 219 double pageX = pageFormat.getImageableX(); 220 double pageY = pageFormat.getImageableY(); 221 double pageWidth = pageFormat.getImageableWidth(); 222 double pageHeight = pageFormat.getImageableHeight(); 223 224 Log.log(Log.DEBUG,this,"#1 - Page dimensions: " + pageWidth 225 + 'x' + pageHeight); 226 227 if(header) 228 { 229 double headerHeight = paintHeader(gfx,pageX,pageY,pageWidth, 230 actuallyPaint); 231 pageY += headerHeight; 232 pageHeight -= headerHeight; 233 } 234 235 if(footer) 236 { 237 double footerHeight = paintFooter(gfx,pageX,pageY,pageWidth, 238 pageHeight,pageIndex,actuallyPaint); 239 pageHeight -= footerHeight; 240 } 241 242 boolean glyphVector = jEdit.getBooleanProperty("print.glyphVector"); 243 double lineNumberWidth; 244 245 if(lineNumbers) 247 { 248 int lineNumberDigits = (int)Math.ceil(Math.log(buffer.getLineCount() + 1) 251 / Math.log(10)) + 1; 252 253 char[] chars = new char[lineNumberDigits]; 255 for(int i = 0; i < chars.length; i++) 256 chars[i] = ' '; 257 lineNumberWidth = font.getStringBounds(chars, 258 0,lineNumberDigits,frc).getWidth(); 259 } 260 else 261 lineNumberWidth = 0.0; 262 264 Log.log(Log.DEBUG,this,"#2 - Page dimensions: " 265 + (pageWidth - lineNumberWidth) 266 + 'x' + pageHeight); 267 268 int tabSize = jEdit.getIntegerProperty("print.tabSize",8); 270 char[] chars = new char[tabSize]; 271 for(int i = 0; i < chars.length; i++) 272 chars[i] = ' '; 273 double tabWidth = font.getStringBounds(chars, 274 0,tabSize,frc).getWidth(); 275 PrintTabExpander e = new PrintTabExpander(tabWidth); 276 278 lm = font.getLineMetrics("gGyYX",frc); 279 Log.log(Log.DEBUG,this,"Line height is " + lm.getHeight()); 280 281 double y = 0.0; 282 print_loop: for(;;) 283 { 284 if(currentPhysicalLine == buffer.getLineCount()) 285 { 286 Log.log(Log.DEBUG,this,"Finished buffer"); 287 end = true; 288 break print_loop; 289 } 290 if (!jEdit.getBooleanProperty("print.folds",true) && 291 !view.getTextArea().getDisplayManager().isLineVisible(currentPhysicalLine)) 292 { 293 294 Log.log(Log.DEBUG,this,"Skipping invisible line"); 295 currentPhysicalLine++; 296 continue; 297 } 298 299 lineList.clear(); 300 301 tokenHandler.init(styles,frc,e,lineList, 302 (float)(pageWidth - lineNumberWidth)); 303 304 buffer.markTokens(currentPhysicalLine,tokenHandler); 305 if(lineList.isEmpty()) 306 lineList.add(null); 307 308 if(y + (lm.getHeight() * lineList.size()) >= pageHeight) 309 { 310 Log.log(Log.DEBUG,this,"Finished page before line " + currentPhysicalLine); 311 break print_loop; 312 } 313 314 if(lineNumbers && actuallyPaint) 315 { 316 gfx.setFont(font); 317 gfx.setColor(lineNumberColor); 318 gfx.drawString(String.valueOf(currentPhysicalLine + 1), 319 (float)pageX,(float)(pageY + y + lm.getHeight())); 320 } 321 322 for(int i = 0; i < lineList.size(); i++) 323 { 324 y += lm.getHeight(); 325 Chunk chunks = lineList.get(i); 326 if(chunks != null && actuallyPaint) 327 { 328 Chunk.paintChunkBackgrounds(chunks,gfx, 329 (float)(pageX + lineNumberWidth), 330 (float)(pageY + y)); 331 Chunk.paintChunkList(chunks,gfx, 332 (float)(pageX + lineNumberWidth), 333 (float)(pageY + y),glyphVector); 334 } 335 } 336 337 currentPhysicalLine++; 338 } 339 } 341 private double paintHeader(Graphics2D gfx, double pageX, double pageY, 343 double pageWidth, boolean actuallyPaint) 344 { 345 String headerText = jEdit.getProperty("print.headerText", 346 new String [] { buffer.getName() }); 347 FontRenderContext frc = gfx.getFontRenderContext(); 348 lm = font.getLineMetrics(headerText,frc); 349 350 Rectangle2D bounds = font.getStringBounds(headerText,frc); 351 Rectangle2D headerBounds = new Rectangle2D.Double( 352 pageX,pageY,pageWidth,bounds.getHeight()); 353 354 if(actuallyPaint) 355 { 356 gfx.setColor(headerColor); 357 gfx.fill(headerBounds); 358 gfx.setColor(headerTextColor); 359 gfx.drawString(headerText, 360 (float)(pageX + (pageWidth - bounds.getWidth()) / 2), 361 (float)(pageY + lm.getAscent())); 362 } 363 364 return headerBounds.getHeight(); 365 } 366 368 private double paintFooter(Graphics2D gfx, double pageX, double pageY, 370 double pageWidth, double pageHeight, int pageIndex, 371 boolean actuallyPaint) 372 { 373 String footerText = jEdit.getProperty("print.footerText", 374 new Object [] { new Date(), Integer.valueOf(pageIndex + 1)}); 375 FontRenderContext frc = gfx.getFontRenderContext(); 376 lm = font.getLineMetrics(footerText,frc); 377 378 Rectangle2D bounds = font.getStringBounds(footerText,frc); 379 Rectangle2D footerBounds = new Rectangle2D.Double( 380 pageX,pageY + pageHeight - bounds.getHeight(), 381 pageWidth,bounds.getHeight()); 382 383 if(actuallyPaint) 384 { 385 gfx.setColor(footerColor); 386 gfx.fill(footerBounds); 387 gfx.setColor(footerTextColor); 388 gfx.drawString(footerText, 389 (float)(pageX + (pageWidth - bounds.getWidth()) / 2), 390 (float)(pageY + pageHeight - bounds.getHeight() 391 + lm.getAscent())); 392 } 393 394 return footerBounds.getHeight(); 395 } 397 399 static class PrintTabExpander implements TabExpander 401 { 402 private double tabWidth; 403 404 PrintTabExpander(double tabWidth) 406 { 407 this.tabWidth = tabWidth; 408 } 410 public float nextTabStop(float x, int tabOffset) 412 { 413 int ntabs = (int)((x + 1) / tabWidth); 414 return (float)((ntabs + 1) * tabWidth); 415 } } } 418 | Popular Tags |