drop type varchar2_array
/
drop type number_array
/

create or replace java source named "ImageGenerator" as
import java.awt.*;
import java.awt.image.*;
import java.awt.font.*;
import java.io.*;
import oracle.jdbc.*;
import oracle.sql.*;
import java.util.*;
import javax.imageio.*;
import java.sql.*;

public class DBImage {
  private static final int TEXTALIGN_LEFT = 1;
  private static final int TEXTALIGN_RIGHT = 2;
  private static final int TEXTALIGN_CENTER = 3;

  private static Hashtable hsImageHandles = new Hashtable();
  private static Hashtable hsImageGraphics = new Hashtable();
  private static Map mRenderingHints = null;

  private static String DB_ARRAY_NAME = "VARCHAR2_ARRAY";

  private static Random rRandom = null;

  static {
    mRenderingHints = new Hashtable();
    mRenderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    mRenderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
  }

  private static String getRandomString(int iLength) {
    byte[] bRandomBytes = new byte[10];
    if (rRandom == null) {
      rRandom = new Random();
    }
    rRandom.nextBytes(bRandomBytes);
    return new String(bRandomBytes);
  }

  public static void setFontPath(String fp) {
    String sR = System.setProperty("sun.java2d.fontpath", fp);
  }

  public static String getImageHandle(oracle.sql.BLOB oImage) throws Exception {
    InputStream imageStream = oImage.getBinaryStream();
    String sImageName = getRandomString(10);
    while (hsImageHandles.containsKey(sImageName)) {
      sImageName = getRandomString(10);
    }
    BufferedImage bi = ImageIO.read(imageStream);
    hsImageHandles.put(sImageName, bi);
    Graphics2D ig = bi.createGraphics();
    ig.addRenderingHints(mRenderingHints);

    hsImageGraphics.put(sImageName, ig);
    return sImageName;
  }

  public static String createImageHandle(int iWidth, int iHeight) {
    String sImageName = getRandomString(10);
    while (hsImageHandles.containsKey(sImageName)) {
      sImageName = getRandomString(10);
    }
    BufferedImage bi = new BufferedImage(iWidth, iHeight, BufferedImage.TYPE_INT_RGB);
    hsImageHandles.put(sImageName, bi);
    Graphics2D ig = bi.createGraphics();
    ig.addRenderingHints(mRenderingHints);

    hsImageGraphics.put(sImageName, ig);
    return sImageName;
  }

  public static ARRAY getImageHandles() throws Exception {
    Connection con = null;
    ArrayDescriptor descr = null;

    int i = 0;
    Enumeration eHandleNames = hsImageHandles.keys();
    String[] saHandles = new String[hsImageHandles.size()];
    while  (eHandleNames.hasMoreElements()) {
      saHandles[i++] = (String)eHandleNames.nextElement();
    }
    con = DriverManager.getConnection("jdbc:default:connection:");
    descr = ArrayDescriptor.createDescriptor(DB_ARRAY_NAME, con);
    return new ARRAY(descr, con, saHandles);
  }

  public static void setBackground(String sImageName, int r, int g, int b) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).setBackground(new Color(r,g,b));
  }

  public static void clearImage(String sImageName) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).clearRect(0,0, ((BufferedImage)hsImageHandles.get(sImageName)).getWidth(),  ((BufferedImage)hsImageHandles.get(sImageName)).getHeight());
  }

  public static void setFont(String sImageName, String family, String style, int size) {
   int iStyle = 0;
   if (style != null) {
     if (style.indexOf("BOLD") != -1) {
       iStyle = iStyle + Font.BOLD;
     }
     if (style.indexOf("ITALIC") != -1) {
       iStyle = iStyle + Font.ITALIC;
     }
   }
   ((Graphics2D)hsImageGraphics.get(sImageName)).setFont(new Font(family, iStyle, size));
  }

  public static void setText(String sImageName, int x, int y, String text, int align) {
   TextLayout tl = new TextLayout(
     text,
     ((Graphics2D)hsImageGraphics.get(sImageName)).getFont(),
     ((Graphics2D)hsImageGraphics.get(sImageName)).getFontRenderContext()
   );
   if (align == TEXTALIGN_LEFT) {
     tl.draw(((Graphics2D)hsImageGraphics.get(sImageName)), (float)x, (float)y);
   } else if (align == TEXTALIGN_RIGHT) {
     tl.draw(((Graphics2D)hsImageGraphics.get(sImageName)), (float)(x - (tl.getBounds().getWidth())), (float)y);
   } else if (align == TEXTALIGN_CENTER) {
     tl.draw(((Graphics2D)hsImageGraphics.get(sImageName)), (float)(x - (tl.getBounds().getWidth() / 2)), (float)y);
   }
  }

  public static void setText(String sImageName, int x, int y, String text, int align, int degree) {
   ((Graphics2D)hsImageGraphics.get(sImageName)).translate(x,y);
   ((Graphics2D)hsImageGraphics.get(sImageName)).rotate(-((Math.PI / 180) * degree));
   setText(sImageName, 0, 0, text, align);
   ((Graphics2D)hsImageGraphics.get(sImageName)).rotate(((Math.PI / 180) * degree));
   ((Graphics2D)hsImageGraphics.get(sImageName)).translate(-x,-y);
  }

  public static void drawLine(String sImageName, int x1, int y1, int x2, int y2) {
   ((Graphics2D)hsImageGraphics.get(sImageName)).drawLine(x1, y1,x2,y2);
  }

  public static void setColor(String sImageName, int r, int g, int b) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).setColor(new Color(r,g,b));
  }

  public static void setStroke(String sImageName, int width, oracle.sql.ARRAY dash)
  throws SQLException{
    if (dash == null) {
      ((Graphics2D)hsImageGraphics.get(sImageName)).setStroke(new BasicStroke(width));
    } else {
      ((Graphics2D)hsImageGraphics.get(sImageName)).setStroke(new BasicStroke(width, 0,0,1.0f, dash.getFloatArray(),0));
    }
  }

  public static void setStroke(String sImageName, int width) throws SQLException {
    setStroke(sImageName, width, null);
  }

  public static void drawPolygon(String sImageName, oracle.sql.ARRAY coords) throws SQLException{
    doDrawPolygon(sImageName, coords, false);
  }

  public static void drawArc(String sImageName, int x, int y, int width, int height, int startAngle, int incrAngle) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).drawArc(x,y,width, height, startAngle, incrAngle);
  }

  public static void drawFilledArc(String sImageName, int x, int y, int width, int height, int startAngle, int incrAngle) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).fillArc(x,y,width, height, startAngle, incrAngle);
  }

  public static void drawFilledPolygon(String sImageName, oracle.sql.ARRAY coords) throws SQLException{
    doDrawPolygon(sImageName, coords, true);
  }

  public static void drawPolyLine(String sImageName, oracle.sql.ARRAY coords) throws SQLException{
    int[] cArray = coords.getIntArray();
    int[] x = new int[cArray.length/2];
    int[] y = new int[cArray.length/2];
    for (int i=0;i<cArray.length;i=i+2) {
      x[i/2] = cArray[i];
      y[i/2] = cArray[i+1];
    }
    ((Graphics2D)hsImageGraphics.get(sImageName)).drawPolyline(x, y, x.length);
  }

  public static void doDrawPolygon(String sImageName, oracle.sql.ARRAY coords, boolean fill) throws SQLException{
    int[] cArray = coords.getIntArray();
    int[] x = new int[cArray.length/2];
    int[] y = new int[cArray.length/2];
    for (int i=0;i<cArray.length;i=i+2) {
      x[i/2] = cArray[i];
      y[i/2] = cArray[i+1];
    }
    if (fill) {
      ((Graphics2D)hsImageGraphics.get(sImageName)).fillPolygon(x, y, x.length);
    } else {
      ((Graphics2D)hsImageGraphics.get(sImageName)).drawPolygon(x, y, x.length);
    }
  }

  public static void drawFilledPolygon(String sImageName, oracle.sql.ARRAY x, oracle.sql.ARRAY y, int count)
  throws SQLException {
    int[] xArray = x.getIntArray();
    int[] yArray = y.getIntArray();

    ((Graphics2D)hsImageGraphics.get(sImageName)).fillPolygon(xArray, yArray, count);
  }

  public static void drawFilledRect(String sImageName, int x1, int y1, int width, int height) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).fill(new Rectangle(x1, y1, width, height));
  }

  public static int getWidth(String sImageName) {
    return ((BufferedImage)hsImageHandles.get(sImageName)).getWidth();
  }

  public static int getHeight(String sImageName) {
    return ((BufferedImage)hsImageHandles.get(sImageName)).getHeight();
  }

  public static void drawRect(String sImageName, int x1, int y1, int width, int height) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).draw(new Rectangle(x1, y1, width, height));
  }

  public static void draw3DRect(String sImageName, int x1, int y1, int width, int height) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).draw3DRect(x1, y1, width, height, true);
  }

  public static void drawFilled3DRect(String sImageName, int x1, int y1, int width, int height) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).fill3DRect(x1, y1, width, height, true);
  }

  public static void drawOval(String sImageName, int x1, int y1, int width, int height) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).drawOval(x1, y1, width, height);
  }

  public static void drawFilledOval(String sImageName, int x1, int y1, int width, int height) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).fillOval(x1, y1, width, height);
  }

  public static void destroyImageHandle(String sImageName) {
    ((Graphics2D)hsImageGraphics.get(sImageName)).dispose();
    hsImageGraphics.remove(sImageName);
    hsImageHandles.remove(sImageName);
  }

  public static BLOB getImageBlob(String sImageName, String sImageType) throws Exception {
    Connection con = DriverManager.getConnection("jdbc:default:connection:");
    BLOB b = BLOB.createTemporary(con, true, BLOB.DURATION_CALL);
    OutputStream imageOs = b.getBinaryOutputStream(0L);
    ImageIO.write((BufferedImage)hsImageHandles.get(sImageName), sImageType, imageOs);
    imageOs.flush();
    imageOs.close();
    return b;
  }

  public static ARRAY getFontNames() throws Exception{
    Connection con = DriverManager.getConnection("jdbc:default:connection:");
    ArrayDescriptor descr = ArrayDescriptor.createDescriptor(DB_ARRAY_NAME, con);

    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    String[] sFontName = new String[ge.getAllFonts().length];
    for (int i=1;i<ge.getAllFonts().length;i++) {
      sFontName[i] = ge.getAllFonts()[i].getFontName();
    }
    return new ARRAY(descr, con, sFontName);
  }
}
/

alter java source "ImageGenerator" compile
/

create type VARCHAR2_ARRAY as table of VARCHAR2(4000)
/
create type number_array as table of number
/

create or replace package image_generator is
  TEXTALIGN_LEFT constant number := 1;
  TEXTALIGN_RIGHT constant number := 2;
  TEXTALIGN_CENTER constant number := 3;

  function create_image_handle(p_width number, p_height number) return varchar2;
  function get_image_handle(p_image blob) return varchar2;
  procedure set_background(p_img_name varchar2, p_r number, p_g number, p_b number);
  procedure clear_image(p_img_name varchar2);
  procedure set_font(p_img_name varchar2, p_font_family varchar2, p_font_style varchar2, p_font_size number);
  procedure draw_text(p_img_name varchar2, p_x number, p_y number, p_text varchar2, p_align number);
  procedure draw_text(p_img_name varchar2, p_x number, p_y number, p_text varchar2, p_align number, p_degree number);
  procedure set_color(p_img_name varchar2, p_r number, p_g number, p_b number);
  procedure set_stroke_width(p_img_name varchar2, p_width number);
  procedure set_stroke(p_img_name varchar2, p_width number, p_dash_array number_array);
  procedure draw_filled_rect(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number);
  procedure draw_rect(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number);
  procedure draw_polygon(p_img_name varchar2, p_coords number_array);
  procedure draw_polyline(p_img_name varchar2, p_coords number_array);
  procedure draw_filled_polygon(p_img_name varchar2, p_coords number_array);
  procedure draw_filled_3d_rect(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number);
  procedure draw_arc(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number, p_start_angle number, p_arc_angle number);
  procedure draw_filled_arc(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number, p_start_angle number, p_arc_angle number);
  procedure draw_3d_rect(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number);
  procedure draw_line(p_img_name varchar2, p_x1 number, p_y1 number, p_x2 number, p_y2 number);
  function get_Image(p_img_name varchar2, p_img_type varchar2) return BLOB;
  procedure destroy_image(p_img_name varchar2);
  function get_font_names return VARCHAR2_ARRAY;
  function get_image_handles return VARCHAR2_ARRAY;
  
  procedure draw_oval(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number);
  procedure draw_filled_oval(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number);
  function get_width(p_img_name varchar2) return number;
  function get_height(p_img_name varchar2) return number;
  procedure set_font_path(p_font_path varchar2);
end image_generator;
/

create or replace package body image_generator is
  function create_image_handle(p_width number, p_height number) return varchar2
  is language java name 'DBImage.createImageHandle(int, int) return java.lang.String';

  function get_image_handle(p_image blob) return varchar2
  is language java name 'DBImage.getImageHandle(oracle.sql.BLOB) return java.lang.String';

  procedure set_background(p_img_name varchar2, p_r number, p_g number, p_b number)
  is language java name 'DBImage.setBackground(java.lang.String, int, int, int)';

  procedure clear_image(p_img_name varchar2)
  is language java name 'DBImage.clearImage(java.lang.String)';

  procedure set_font(p_img_name varchar2, p_font_family varchar2, p_font_style varchar2, p_font_size number)
  is language java name 'DBImage.setFont(java.lang.String, java.lang.String, java.lang.String, int)';

  procedure draw_text(p_img_name varchar2, p_x number, p_y number, p_text varchar2, p_align number)
  is language java name 'DBImage.setText(java.lang.String, int, int, java.lang.String, int)';

  procedure draw_text(p_img_name varchar2, p_x number, p_y number, p_text varchar2, p_align number, p_degree number)
  is language java name 'DBImage.setText(java.lang.String, int, int, java.lang.String, int, int)';

  procedure set_color(p_img_name varchar2, p_r number, p_g number, p_b number)
  is language java name 'DBImage.setColor(java.lang.String, int, int, int)';

  procedure set_stroke_width(p_img_name varchar2, p_width number)
  is language java name 'DBImage.setStroke(java.lang.String, int)';

  procedure set_stroke(p_img_name varchar2, p_width number, p_dash_array number_array)
  is language java name 'DBImage.setStroke(java.lang.String, int, oracle.sql.ARRAY)';

  procedure draw_filled_rect(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number)
  is language java name 'DBImage.drawFilledRect(java.lang.String, int, int, int, int)';

  procedure draw_filled_3d_rect(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number)
  is language java name 'DBImage.drawFilled3DRect(java.lang.String, int, int, int, int)';

  procedure draw_filled_oval(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number)
  is language java name 'DBImage.drawFilledOval(java.lang.String, int, int, int, int)';

  procedure draw_rect(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number)
  is language java name 'DBImage.drawRect(java.lang.String, int, int, int, int)';

  procedure draw_polygon(p_img_name varchar2, p_coords number_array)
  is language java name 'DBImage.drawPolygon(java.lang.String, oracle.sql.ARRAY)';

  procedure draw_polyline(p_img_name varchar2, p_coords number_array)
  is language java name 'DBImage.drawPolyline(java.lang.String, oracle.sql.ARRAY)';

  procedure draw_filled_polygon(p_img_name varchar2, p_coords number_array)
  is language java name 'DBImage.drawFilledPolygon(java.lang.String, oracle.sql.ARRAY)';

  procedure draw_arc(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number, p_start_angle number, p_arc_angle number)
  is language java name 'DBImage.drawArc(java.lang.String, int, int, int, int, int, int)';

  procedure draw_filled_arc(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number, p_start_angle number, p_arc_angle number)
  is language java name 'DBImage.drawFilledArc(java.lang.String, int, int, int, int, int, int)';

  procedure draw_3d_rect(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number)
  is language java name 'DBImage.draw3DRect(java.lang.String, int, int, int, int)';

  procedure draw_oval(p_img_name varchar2, p_x number, p_y number, p_width number, p_height number)
  is language java name 'DBImage.drawOval(java.lang.String, int, int, int, int)';

  function get_Image(p_img_name varchar2, p_img_type varchar2) return BLOB
  is language java name 'DBImage.getImageBlob(java.lang.String, java.lang.String) return oracle.sql.BLOB';

  procedure destroy_image(p_img_name varchar2)
  is language java name 'DBImage.destroyImageHandle(java.lang.String)';

  function get_font_names return VARCHAR2_ARRAY
  is language java name 'DBImage.getFontNames() return oracle.sql.ARRAY';

  function get_image_handles return VARCHAR2_ARRAY
  is language java name 'DBImage.getImageHandles() return oracle.sql.ARRAY';

  procedure draw_line(p_img_name varchar2, p_x1 number, p_y1 number, p_x2 number, p_y2 number)
  is language java name 'DBImage.drawLine(java.lang.String, int, int, int, int)';

  procedure set_font_path(p_font_path varchar2)
  is language java name 'DBImage.setFontPath(java.lang.String)';

  function get_width(p_img_name varchar2) return number
  is language java name 'DBImage.getWidth(java.lang.String) return int';
  function get_height(p_img_name varchar2) return number
  is language java name 'DBImage.getHeight(java.lang.String) return int';
end image_generator;
/