Package ch.sahits.game.graphic.image

Source Code of ch.sahits.game.graphic.image.OpenPatricianPainter

package ch.sahits.game.graphic.image;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.RasterFormatException;
import java.io.IOException;
import java.util.HashMap;

import javax.swing.JPanel;

import ch.sahits.game.graphic.image.FontLoader;
import ch.sahits.game.graphic.image.ImagesLoader;
/**
* Utility class for with methods common to all UI painters
* @author Andi Hotz, (c) Sahits GmbH, 2011
* Created on Mar 26, 2011
*
*/
public class OpenPatricianPainter {
 
  private HashMap<String,Dimension> imgDimensionCache = new HashMap<String,Dimension>();
  /**
   * Retrieve the image dimensions from the cache or store it there if they are not available
   * @param fileName
   * @return
   */
  private synchronized Dimension getImageDimesnion(String fileName){
    if (imgDimensionCache.containsKey(fileName)){
      return imgDimensionCache.get(fileName);
    } else {
      ImagesLoader loader = new ImagesLoader();
      BufferedImage baseImg = loader.loadImage(fileName);
      Dimension dim = new Dimension(baseImg.getWidth(), baseImg.getHeight());
      imgDimensionCache.put(fileName, dim);
      return dim;
    }
  }
  /**
   * Create a BufferedImage of the specified dimensions. The image is tiled with <code>imageName</code>.
   * @param imageName of the image
   * @param width of the image
   * @param heigth of the image
   * @param comp Component on which is drawn
   * @return
   */
  public static BufferedImage createTiledImage(String imageName, int width, int heigth){
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice gs = ge.getDefaultScreenDevice();
    GraphicsConfiguration gconf = gs.getDefaultConfiguration();
   
      ImagesLoader loader = new ImagesLoader();
      BufferedImage baseImg = loader.loadImage(imageName);
      final int xSize = baseImg.getWidth();
      final int ySize = baseImg.getHeight();
      int vCount = width/xSize;
      if (width%xSize>0){
        vCount++;
      }
      int hCount = heigth/ySize;
      if (heigth%ySize>0){
        hCount++;
      }
   
    BufferedImage img = gconf.createCompatibleImage(vCount*xSize, hCount*ySize, Transparency.BITMASK);
   
    // fill in the image
    Graphics2D g = img.createGraphics();
    for (int xCount=0;xCount<=vCount;xCount++){
      for (int yCount=0;yCount<=hCount;yCount++){
        final int xpos = xCount*xSize;
        final int ypos = yCount*ySize;
        g.drawImage(baseImg, xpos, ypos,null);
      }
    }
    return cropImage(img, width, heigth);
  }

  /**
   * Paint the image onto the component. If the image is larger the image is clipped. If the image
   * is smaller it is repeated.
   * @param g Graphics used to draw on
   * @param imageName name of the tiled image
   * @param comp Component on which to draw
   * @param rect rectangle which is to be drawn of the whole
   */
  public static void drawBackground(Graphics g, String imageName, Rectangle rect) {
    final int width = rect.width;
    final int height = rect.height;
    BufferedImage img = createTiledImage(imageName, width, height);
    drawTile(img, rect.x, rect.y, width, height, g);
  }

  /**
   * Wrapper method for drawing a tile at a specified position
   * @param img Original image to be used
   * @param x position of the top right corner
   * @param y position of the top right corner
   * @param width of the image to be drawn (the rest is clipped away)
   * @param height of the image to be drawn (the rest is clipped away)
   * @param comp Component on which the image is drawn
   * @param g Graphics used for the drawing
   */
  public static void drawTile(BufferedImage img, int x, int y, int width,
      int height, Graphics g) {
    if (width>img.getWidth()){
      throw new IllegalArgumentException("The drawing is wider than the image: no stretching allowd");
    }
    if (height>img.getHeight()){
      throw new IllegalArgumentException("The drawing is heigher than the image: no stretching allowd");
    }
//System.out.println("Draw image with size ("+img.getWidth()+"x"+img.getHeight()+") at ("+x+"x"+y+") with dimensions ("+width+"x"+height+")");   
     g.drawImage(img, x, y, width, height, null);
  }
  /**
   * Create an image that crops the image on the left and bottom side to create an image of the desired
   * proportions.
   * @param img Original image
   * @param destWidth destination width must be smaller than the image's width
   * @param destHeight destination height must be smaller than the image's height
   * @return cropped image with the dimension <code>destWidthxdestHeight</code>
   */
  private static BufferedImage cropImage(BufferedImage img, int destWidth, int destHeight){
    if (img.getWidth()<destWidth){
      throw new IllegalArgumentException("The destination width must be smaller than the image width");
    }
    if (img.getHeight()<destHeight){
      throw new IllegalArgumentException("The destination height must be smaller than the image height");
    }
     try {
      return img.getSubimage(0, 0, destWidth, destHeight);
    } catch (RasterFormatException e) {
      System.out.println(e.getMessage()+" - Original"+img.getWidth()+"x"+img.getHeight()+", "+destWidth+"x"+destHeight);
      throw e;
    }

  }
   /**
    * Draw a string on the component
    * @param graphics Graphics context that is used
    * @param s String to be drawn
    * @param fontSize Font size in pt to be used
    * @param posX Center X position of the string
    * @param posY Center y position of the string
    */
  public void drawString(Graphics2D graphics, String s, int fontSize,
      int posX, int posY) {
     
      try {
      GlyphVector gv = createGlyphVector(graphics, s, fontSize);
      Rectangle2D box = gv.getVisualBounds();
      float x = posX-(float)box.getCenterX();
      float y = posY-(float)box.getCenterY();
      graphics.drawGlyphVector(gv, x, y);
    } catch (FontFormatException e) {
    } catch (IOException e) {
    }
  }
  /**
   * Create the glyph vector using the string
   * @param graphics to be used
   * @param s String
   * @param fontSize font size in points
   * @return {@link GlyphVector}
   * @throws FontFormatException
   * @throws IOException
   */
  public static GlyphVector createGlyphVector(Graphics2D graphics, String s,
      int fontSize) throws FontFormatException, IOException {
    // TODO: make non static
    Font font = FontLoader.getInstance().createStranbergFont(fontSize);
    return createGlyphVector(graphics, s, font);
  }
  /**
   * Create a glyph vector based on a font
   * @param graphics
   * @param s
   * @param font
   * @return
   */
  public static GlyphVector createGlyphVector(Graphics2D graphics, String s,
      Font font) {
    graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    FontRenderContext frc = graphics.getFontRenderContext();

    GlyphVector gv = font.createGlyphVector(frc, s);
    return gv;
  }
  /**
   * Create the glyph vector using the string
   * @param s String
   * @param fontSize font size in points
   * @return {@link GlyphVector}
   * @throws FontFormatException
   * @throws IOException
   */
  public GlyphVector createGlyphVector(String s, int fontSize) throws FontFormatException, IOException{
    FontRenderContext frc = new FontRenderContext(new AffineTransform(), true, true);
    Font font = FontLoader.getInstance().createStranbergFont(fontSize);
    GlyphVector gv = font.createGlyphVector(frc, s);
    return gv;
  }
  /**
   * Create turned steering wheel. 0% is whole on the left and 100% whole on the right
   * @param width width of the component
   * @param percent of the turning
   */
  public BufferedImage createSteeringWheel(int width, float percent){
    if (percent<0 || percent>100){
      throw new IllegalArgumentException("percent must ly withing [0,100]");
    }
    String fileName = "SteeringWheel.png";

    Dimension dim = getImageDimesnion(fileName);

      double scale =  width / dim.getWidth();

      final double angle = computeSteeringWheelAngle(percent);

    OpenPatricianImageRotator rotator = new OpenPatricianImageRotator();
    return rotator.rotateImage(fileName, angle, scale, 1, 2);

  }
  /**
   * Compute the angle in degrees based on the percentage.
   * @param percentage
   * @return
   */
  private double computeSteeringWheelAngle(float percentage){
    return percentage*160/100+10;
  }
  /**
   * Create the polygon that represents the handle of the steering wheel
   * @param width of the component the polygon is based upon
   * @param percent of the rotation
   * @return
   */
  public Polygon getSteeringWheelHandle(int width, float percent){
    String fileName = "SteeringWheel.png";

    Dimension dim = getImageDimesnion(fileName);

      double scale =  width / dim.getWidth();

      final double angle = computeSteeringWheelAngle(percent);
     
      Polygon poly = new Polygon(); // The handle in the unscaled unrotated image
      poly.addPoint(0, 235);
      poly.addPoint(80, 235);
      poly.addPoint(80, 260);
      poly.addPoint(0, 260);
//System.out.print("Original polynom: ");
//OpenPatricianImageRotator.print(poly);
//System.out.println("");
      OpenPatricianImageRotator rotator = new OpenPatricianImageRotator();
    return rotator.rotatePolygon(poly, angle, scale, (int)Math.rint(dim.getWidth()), (int)Math.rint(dim.getHeight()));
  }
  /**
   * Compute the slider track rectangle.
   * @param orientation
   * @param width
   * @param castMin cast value of the minimum
   * @param castMax cast value of the maximum
   * @return
   */
  public Rectangle computeSliderTrack(int width, float castMin, float castMax){
     
      Polygon poly = getSteeringWheelHandle(width, castMin);
      int minX  = (int) Math.rint(poly.getBounds().getMinX());
      int maxY = (int)Math.rint(poly.getBounds().getMaxY());
      poly = getSteeringWheelHandle(width, castMax);
      int maxX = (int)Math.rint(poly.getBounds().getMaxX());
      poly = getSteeringWheelHandle(width, (castMax-castMax)/2);
      int minY = (int)Math.rint(poly.getBounds().getMinY());
     
      return new Rectangle(minX, minY, maxX-minX, maxY-minY);       
  }
  /**
   * Scale an input image along the x-axis only. The scaled dimension may not exactly match the
   * desired, but it will be best match
   * @param img Image to be scaled
   * @param destWidth width of the scaled image
   * @return scaled image or null if the input was null
   */
  public static BufferedImage scaleX(BufferedImage img, int destWidth){
    if (destWidth<=0){
      throw new IllegalArgumentException("The final width must be larger than 0");
    }
    if (img==null) return null; // can happen when quitting
      float xScale = (float) destWidth / img.getWidth();
      float yScale = 1;
      AffineTransform at = new AffineTransform();
      at.scale(xScale, yScale);
     
      // instantiate and apply affine transformation filter
      BufferedImageOp bio = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
      return bio.filter(img, null);
   }
  /**
   * Scale an input image along the y-axis only. The scaled dimension may not exactly match the
   * desired, but it will be best match
   * @param img Image to be scaled
   * @param destHeight height of the scaled image
   * @return scaled image or null if the input was null
   */
  public static BufferedImage scaleY(BufferedImage img, int destHeight){
    if (destHeight<=0){
      throw new IllegalArgumentException("The final height must be larger than 0");
    }
    if (img==null) return null; // can happen when quitting
      float xScale = 1;
      float yScale = (float) destHeight / img.getHeight();
      AffineTransform at = new AffineTransform();
      at.scale(xScale, yScale);
     
      // instantiate and apply affine transformation filter
      BufferedImageOp bio = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
      return bio.filter(img, null);
   }
}
TOP

Related Classes of ch.sahits.game.graphic.image.OpenPatricianPainter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.