📄 gcanvas.java
字号:
package no.geosoft.cc.graphics;import java.util.HashMap;import java.io.File;import java.io.IOException;import java.io.OutputStream;import java.io.FileOutputStream;import java.awt.AWTException;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Component;import java.awt.Container;import java.awt.Dimension;import java.awt.Font;import java.awt.Graphics2D;import java.awt.Graphics;import java.awt.Image;import java.awt.LayoutManager;import java.awt.Paint;import java.awt.Polygon;import java.awt.RenderingHints;import java.awt.event.ComponentEvent;import java.awt.event.ComponentListener;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import java.awt.font.TextLayout;import java.awt.geom.Area;import java.awt.geom.Rectangle2D;import java.awt.image.BufferedImage;import java.awt.print.PageFormat;import java.awt.print.Printable;import java.awt.print.PrinterException;import java.awt.print.PrinterJob;import javax.swing.JComponent;import javax.swing.RepaintManager;import no.geosoft.cc.geometry.Rect;import no.geosoft.cc.geometry.Region;import no.geosoft.cc.io.GifEncoder;/** * G rendering engine. * <p> * The canvas is the AWT component where the graphics is displayed. * * @author <a href="mailto:jacob.dreyer@geosoft.no">Jacob Dreyer</a> */ class GCanvas extends JComponent implements Printable, LayoutManager, MouseListener, MouseMotionListener, ComponentListener{ private final GWindow window_; private final RepaintManager repaintManager_; private Graphics graphics_; private Image backBuffer_; private Area clipArea_; private Rect cleared_; /** * Create a graphic canvas. * * @param window GWindow of this canvas. */ GCanvas (GWindow window) { window_ = window; setLayout (this); repaintManager_ = RepaintManager.currentManager (this); // We handle double buffering manually repaintManager_.setDoubleBufferingEnabled (false); backBuffer_ = null; clipArea_ = null; cleared_ = null; addMouseListener (this); addMouseMotionListener (this); addComponentListener (this); } /** * Override the JPanel default to indicate that this canvas is * double buffered. * * @return True always. */ public boolean isDoubleBuffered() { return true; } /** * Override the JPanel default repaint method and do nothing. * TODO: Check this. */ public void repaint() { } /** * Override the JPanel update method and do nothing. * TODO: Check this. * * @param graphics The Graphics2D instance. */ public void update (Graphics graphics) { } /** * Create a new image back buffer. The back buffes has the size * of the cnvas and is recreated each time the canvas size * changes (on resize events). */ private void createBackBuffer() { int width = getWidth(); int height = getHeight(); if (width <= 0 || height <= 0) return; // If component has no parent, null is returned backBuffer_ = createImage (width, height); // Fill back buffer with background color if (backBuffer_ != null) { Graphics2D canvas = (Graphics2D) backBuffer_.getGraphics(); canvas.setColor (getBackground()); canvas.fillRect (0, 0, width, height); } } /** * Paint this component by copying the back buffer into the * front buffer. * * @param graphics The Java2D graphics instance. */ public void paintComponent (Graphics graphics) { if (backBuffer_ == null || graphics == null || cleared_ == null) return; graphics_ = graphics; // TODO: Is it possible to save the rect from clear() and // only copy this part?? // Copy the current back buffer to the front buffer Graphics2D frontBuffer = (Graphics2D) graphics_; frontBuffer.drawImage (backBuffer_, cleared_.x, cleared_.y, cleared_.width, cleared_.height, cleared_.x, cleared_.y, cleared_.width, cleared_.height, this); // TODO: These work as well. Which method is better? // frontBuffer.drawImage (backBuffer_, 0, 0, getWidth(), getHeight(), this); // frontBuffer.drawImage (backBuffer_, null, this); // frontBuffer.drawImage (backBuffer_, 0, 0, this); // Due to a bug in the repaint manager // TODO: Check this if (repaintManager_.getDirtyRegion (this).isEmpty()) return; // Mark as valid repaintManager_.paintDirtyRegions(); repaintManager_.markCompletelyClean (this); cleared_ = null; } /** * Clear the specified area in the back buffer. * * @param rectangle Rectangle area to clear in the back buffer. */ void clear (Rect rectangle) { if (graphics_ == null || backBuffer_ == null) return; Graphics2D canvas = (Graphics2D) backBuffer_.getGraphics(); // Clear by filling rectangle with background color canvas.setClip (clipArea_); canvas.setColor (getBackground()); canvas.fillRect (rectangle.x, rectangle.y, rectangle.width, rectangle.height); } /** * Refresh this canvas. */ void refresh() { paintComponent (getGraphics()); } /** * Set clip area for upcomming draw operations. * * @param region Region to use as clip area. */ void setClipArea (Region region) { clipArea_ = region == null || region.isEmpty() ? null : region.createArea(); } /** * Render the specified polyline into back buffer using the * specified style. * * @param x Polyline x coordinates. * @param y Polyline y coordinates. * @param style Style used for rendering. */ void render (int x[], int y[], GStyle style) { if (backBuffer_ == null) createBackBuffer(); if (backBuffer_ == null) return; Graphics2D canvas = (Graphics2D) backBuffer_.getGraphics(); canvas.setRenderingHint (RenderingHints.KEY_ANTIALIASING, style.isAntialiased() ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); canvas.setColor (style.getForegroundColor()); canvas.setStroke (style.getStroke()); canvas.setClip (clipArea_); Paint paint = style.getPaint(); if (paint != null) { Paint defaultPaint = canvas.getPaint(); canvas.setPaint (paint); canvas.fill (new Polygon (x, y, x.length)); canvas.setPaint (defaultPaint); if (style.isLineVisible()) canvas.drawPolyline (x, y, x.length); } else { if (style.isLineVisible()) canvas.drawPolyline (x, y, x.length); } } /** * Render the specified text element into back buffer using the * specified style. * * @param text Text to render. * @param style Style used for rendering. */ void render (GText text, GStyle style) { if (backBuffer_ == null) return; String string = text.getText(); if (string == null || string.length() == 0) return; Graphics2D canvas = (Graphics2D) backBuffer_.getGraphics(); canvas.setRenderingHint (RenderingHints.KEY_TEXT_ANTIALIASING, style.isAntialiased() ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); canvas.setFont (style.getFont()); int fontSize = style.getFont().getSize(); Color foregroundColor = style.getForegroundColor(); Color backgroundColor = style.getBackgroundColor(); Rect rectangle = text.getRectangle(); // Draw box if (backgroundColor != null) { canvas.setColor (backgroundColor); canvas.fillRect (rectangle.x, rectangle.y, rectangle.width, rectangle.height); } // Draw text, center it in the rectangle box canvas.setColor (foregroundColor); TextLayout layout = new TextLayout (text.getText(), style.getFont(), canvas.getFontRenderContext()); Rectangle2D bounds = layout.getBounds(); double textWidth = bounds.getWidth(); double textHeight = bounds.getHeight(); int x = rectangle.x + (int) Math.round ((rectangle.width - textWidth) / 2.0) - (int) Math.floor (bounds.getX()); int y = rectangle.y + (int) Math.round ((rectangle.height - textHeight) / 2.0) - (int) Math.floor (bounds.getY()); layout.draw (canvas, (float) x, (float) y); } /** * Render the specified image into back buffer. * * @param image Image to render. */ void render (GImage image) { Graphics2D canvas = (Graphics2D) backBuffer_.getGraphics(); Rect rectangle = image.getRectangle(); canvas.drawImage (image.getImage(), rectangle.x, rectangle.y, this); } /** * Render the specified image at every vertex along the specified * polyline. * * @param x Polyline x components.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -