                             :baseline PApplet/BASELINE})
 
 #+clj
-(defn
-  ^{:requires-bindings true
-    :processing-name "textAlign()"
-    :category "Typography"
-    :subcategory "Attributes"
-    :added "1.0"}
-  text-align
-  "Sets the current alignment for drawing text. Available modes are:
-
-  horizontal - :left, :center, and :right
-  vertical   - :top, :bottom, :center, and :baseline
-
-  An optional second parameter specifies the vertical alignment
-  mode. :baseline is the default. The :top and :center parameters are
-  straightforward. The :bottom parameter offsets the line based on the
-  current text-descent. For multiple lines, the final line will be
-  aligned to the bottom, with the previous lines appearing above it.
-
-  When using text with width and height parameters, :baseline is
-  ignored, and treated as :top. (Otherwise, text would by default draw
-  outside the box, since :baseline is the default setting. :baseline is
-  not a useful drawing mode for text drawn in a rectangle.)
-
-  The vertical alignment is based on the value of text-ascent, which
-  many fonts do not specify correctly. It may be necessary to use a
-  hack and offset by a few pixels by hand so that the offset looks
-  correct. To do this as less of a hack, use some percentage of
-  text-ascent or text-descent so that the hack works even if you
-  change the size of the font."
-  ([align]
-     (let [align (resolve-constant-key align horizontal-alignment-modes)]
-       (.textAlign (current-graphics) (int align))))
-  ([align-x align-y]
-     (let [align-x (resolve-constant-key align-x horizontal-alignment-modes)
-           align-y (resolve-constant-key align-y vertical-alignment-modes)]
-       (.textAlign (current-graphics) (int align-x) (int align-y)))))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "textAscent()"
-    :category "Typography"
-    :subcategory "Metrics"
-    :added "1.0"}
-  text-ascent
-  "Returns the ascent of the current font at its current size. This
-  information is useful for determining the height of the font above
-  the baseline. For example, adding the text-ascent and text-descent
-  values will give you the total height of the line."
-  []
-  (.textAscent (current-graphics)))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "textDescent()"
-    :category "Typography"
-    :subcategory "Metrics"
-    :added "1.0"}
-  text-descent
-  "Returns descent of the current font at its current size. This
-  information is useful for determining the height of the font below
-  the baseline. For example, adding the text-ascent and text-descent
-  values will give you the total height of the line."
-  []
-  (.textDescent (current-graphics)))
-
-#+clj
-(defn
-  ^{:requires-bindings true
-    :processing-name "textFont()"
-    :category "Typography"
-    :subcategory "Loading & Displaying"
-    :added "1.0"}
-  text-font
-  "Sets the current font that will be drawn with the text
-  function. Fonts must be loaded with load-font before it can be
-  used. This font will be used in all subsequent calls to the text
-  function. If no size parameter is input, the font will appear at its
-  original size until it is changed with text-size.
-
-  Because fonts are usually bitmaped, you should create fonts at the
-  sizes that will be used most commonly. Using textFont without the
-  size parameter will result in the cleanest-looking text.
-
-  With the default (JAVA2D) and PDF renderers, it's also possible to
-  enable the use of native fonts via the command
-  (hint :enable-native-fonts). This will produce vector text in JAVA2D
-  sketches and PDF output in cases where the vector data is available:
-  when the font is still installed, or the font is created via the
-  create-font fn"
-  ([^PFont font] (.textFont (current-graphics) font))
-  ([^PFont font size] (.textFont (current-graphics) font (int size))))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "textLeading()"
-    :category "Typography"
-    :subcategory "Attributes"
-    :added "1.0"}
-  text-leading
-  "Sets the spacing between lines of text in units of pixels. This
-  setting will be used in all subsequent calls to the text function."
-  [leading]
-  (.textLeading (current-graphics) (float leading)))
-
-#+clj
 (def ^{:private true}
   text-modes {:model PConstants/MODEL
               :shape PConstants/SHAPE})
 
 #+clj
-(defn
-  ^{:requires-bindings true
-    :processing-name "textMode()"
-    :category "Typography"
-    :subcategory "Attributes"
-    :added "1.0"}
-  text-mode
-  "Sets the way text draws to the screen - available modes
-  are :model and :shape
-
-  In the default configuration (the :model mode), it's possible to
-  rotate, scale, and place letters in two and three dimensional space.
-
-  The :shape mode draws text using the the glyph outlines of
-  individual characters rather than as textures. This mode is only
-  only supported with the PDF and OPENGL renderer settings. With the
-  PDF renderer, you must specify the :shape text-mode before any other
-  drawing occurs. If the outlines are not available, then
-  :shape will be ignored and :model will be used instead.
-
-  The :shape option in OPENGL mode can be combined with begin-raw to
-  write vector-accurate text to 2D and 3D output files, for instance
-  DXF or PDF. :shape is not currently optimized for OPENGL, so if
-  recording shape data, use :model until you're ready to capture the
-  geometry with begin-raw."
-  [mode]
-  (let [mode (resolve-constant-key mode text-modes)]
-    (.textMode (current-graphics) (int mode))))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "textSize()"
-    :category "Typography"
-    :subcategory "Attributes"
-    :added "1.0"}
-  text-size
-  "Sets the current font size. This size will be used in all
-  subsequent calls to the text fn. Font size is measured in
-  units of pixels."
-  [size]
-  (.textSize (current-graphics) (float size)))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "texture()"
-    :category "Shape"
-    :subcategory "Vertex"
-    :added "1.0"}
-  texture
-  "Sets a texture to be applied to vertex points. The texture fn must
-  be called between begin-shape and end-shape and before any calls to
-  vertex.
-
-  When textures are in use, the fill color is ignored. Instead, use
-  tint to specify the color of the texture as it is applied to the
-  shape."
-  #+clj [^PImage img]
-  #+cljs [img]
-  (.texture (current-graphics) img))
-
-#+clj
 (def ^{:private true}
   texture-modes {:image PApplet/IMAGE
                  :normal PApplet/NORMAL})
 
 #+clj
-(defn
-    ^{:requires-bindings true
-     :processing-name "textureMode()"
-     :category "Shape"
-     :subcategory "Vertex"
-     :added "1.0"}
-  texture-mode
-  "Sets the coordinate space for texture mapping. There are two
-  options, :image and :normal.
-
-  :image refers to the actual coordinates of the image and :normal
-  refers to a normalized space of values ranging from 0 to 1. The
-  default mode is :image. In :image, if an image is 100 x 200 pixels,
-  mapping the image onto the entire size of a quad would require the
-  points (0,0) (0,100) (100,200) (0,200). The same mapping in
-  NORMAL_SPACE is (0,0) (0,1) (1,1) (0,1)."
-  [mode]
-  (let [mode (resolve-constant-key mode texture-modes)]
-    (.textureMode (current-graphics) (int mode))))
-
-#+clj
 (def ^{:private true}
   texture-wrap-modes {:clamp PApplet/CLAMP
                       :repeat PApplet/REPEAT})
-
-#+clj
-(defn
-    ^{:requires-bindings true
-     :processing-name "textureWrap()"
-     :category "Shape"
-     :subcategory "Vertex"
-     :added "2.0"}
-  texture-wrap
-  "Defines if textures repeat or draw once within a texture map. The two
-  parameters are :clamp (the default behavior) and :repeat. This function
-  only works with the :p2d and :p3d renderers."
-  [mode]
-  (let [mode (resolve-constant-key mode texture-wrap-modes)]
-    (.textureWrap (current-graphics) mode)))
-
-#+clj
-(defn
-  ^{:requires-bindings true
-    :processing-name "textWidth()"
-    :category "Typography"
-    :subcategory "Attributes"
-    :added "1.0"}
-  text-width
-  "Calculates and returns the width of any text string."
-  [^String data]
-  (.textWidth (current-graphics) data))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "tint()"
-    :category "Image"
-    :subcategory "Loading & Displaying"
-    :added "1.0"}
-  tint-float
-  "Sets the fill value for displaying images. Images can be tinted to
-  specified colors or made transparent by setting the alpha.
-
-  To make an image transparent, but not change it's color, use white
-  as the tint color and specify an alpha value. For instance,
-  tint(255, 128) will make an image 50% transparent (unless
-  colorMode() has been used).
-
-  The value for the parameter gray must be less than or equal to the
-  current maximum value as specified by colorMode(). The default
-  maximum value is 255.
-
-  Also used to control the coloring of textures in 3D."
-  ([gray] (.tint (current-graphics) (float gray)))
-  ([gray alpha] (.tint (current-graphics) (float gray) (float alpha)))
-  ([r g b] (.tint (current-graphics) (float r)(float g) (float b)))
-  ([r g b a] (.tint (current-graphics) (float g) (float g) (float b) (float a))))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "tint()"
-    :category "Image"
-    :subcategory "Loading & Displaying"
-    :added "1.0"}
-  tint-int
-  "Sets the fill value for displaying images. Images can be tinted to
-  specified colors or made transparent by setting the alpha.
-
-  To make an image transparent, but not change it's color, use white
-  as the tint color and specify an alpha value. For instance,
-  tint(255, 128) will make an image 50% transparent (unless
-  colorMode() has been used).
-
-  The value for the parameter gray must be less than or equal to the
-  current maximum value as specified by colorMode(). The default
-  maximum value is 255.
-
-  Also used to control the coloring of textures in 3D."
-  ([rgb] (.tint (current-graphics) (int rgb)))
-  ([rgb alpha] (.tint (current-graphics) (int rgb) (float alpha))))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "tint()"
-    :category "Image"
-    :subcategory "Loading & Displaying"
-    :added "1.0"}
-  tint
-  "Sets the fill value for displaying images. Images can be tinted to
-  specified colors or made transparent by setting the alpha.
-
-  To make an image transparent, but not change it's color, use white
-  as the tint color and specify an alpha value. For instance,
-  tint(255, 128) will make an image 50% transparent (unless
-  colorMode() has been used).
-
-  The value for the parameter gray must be less than or equal to the
-  current maximum value as specified by colorMode(). The default
-  maximum value is 255.
-
-  Also used to control the coloring of textures in 3D."
-  #+clj ([rgb] (if (int-like? rgb) (tint-int rgb) (tint-float rgb)))
-  #+clj ([rgb alpha] (if (int-like? rgb) (tint-int rgb alpha) (tint-float rgb alpha)))
-  ([r g b] (tint-float r g b))
-  ([r g b a] (tint-float r g b a)))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "translate()"
-    :category "Transform"
-    :subcategory nil
-    :added "1.0"}
-  translate
-  "Specifies an amount to displace objects within the display
-  window. The x parameter specifies left/right translation, the y
-  parameter specifies up/down translation, and the z parameter
-  specifies translations toward/away from the screen.  Transformations
-  apply to everything that happens after and subsequent calls to the
-  function accumulates the effect. For example, calling (translate 50
-  0) and then (translate 20, 0) is the same as (translate 70, 0). If
-  translate is called within draw, the transformation is reset when
-  the loop begins again. This function can be further controlled by
-  the push-matrix and pop-matrix."
-  ([v] (apply translate v))
-  ([tx ty] (.translate (current-graphics) (float tx) (float ty)))
-  ([tx ty tz] (.translate (current-graphics) (float tx) (float ty) (float tz))))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "triangle()"
-    :category "Shape"
-    :subcategory "2D Primitives"
-    :added "1.0"}
-  triangle
-  "A triangle is a plane created by connecting three points. The first
-  two arguments specify the first point, the middle two arguments
-  specify the second point, and the last two arguments specify the
-  third point."
-  [x1 y1 x2 y2 x3 y3]
-  (.triangle (current-graphics)
-             (float x1) (float y1)
-             (float x2) (float y2)
-             (float x3) (float y3)))
-
-#+clj
-(defn
-  ^{:require-binding false
-    :processing-name "unbinary()"
-    :category "Data"
-    :subcategory "Conversion"
-    :added "1.0"}
-  unbinary
-  "Unpack a binary string to an integer. See binary for converting
-  integers to strings."
-  [str-val]
-  (PApplet/unbinary (str str-val)))
-
-#+clj
-(defn
-  ^{:require-binding false
-    :processing-name "hex()"
-    :category "Data"
-    :subcategory "Conversion"}
-  unhex
-  "Converts a String representation of a hexadecimal number to its
-  equivalent integer value."
-  [hex-str]
-  (PApplet/unhex (str hex-str)))
-
-#+clj
-(defn
-  ^{:requires-bindings true
-    :processing-name "updatePixels()"
-    :category "Image"
-    :subcategory "Pixels"
-    :added "1.0"}
-  update-pixels
-  "Updates the display window or image with the data in the pixels array.
-  Use in conjunction with (pixels). If you're only reading pixels from
-  the array, there's no need to call update-pixels unless there are
-  changes.
-
-  Certain renderers may or may not seem to require pixels or
-  update-pixels. However, the rule is that any time you want to
-  manipulate the pixels array, you must first call pixels, and
-  after changes have been made, call update-pixels. Even if the
-  renderer may not seem to use this function in the current Processing
-  release, this will always be subject to change."
-  ([] (update-pixels (current-graphics)))
-  ([^PImage img] (.updatePixels img)))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "vertex()"
-    :category "Shape"
-    :subcategory "Vertex"
-    :added "1.0"}
-  vertex
-  "All shapes are constructed by connecting a series of
-  vertices. vertex is used to specify the vertex coordinates for
-  points, lines, triangles, quads, and polygons and is used
-  exclusively within the begin-shape and end-shape fns.
-
-  Drawing a vertex in 3D using the z parameter requires the :p3d or
-  :opengl renderers to be used.
-
-  This function is also used to map a texture onto the geometry. The
-  texture fn declares the texture to apply to the geometry and the u
-  and v coordinates set define the mapping of this texture to the
-  form. By default, the coordinates used for u and v are specified in
-  relation to the image's size in pixels, but this relation can be
-  changed with texture-mode."
-  ([x y] (.vertex (current-graphics) (float x) (float y)))
-  ([x y z] (.vertex (current-graphics) (float x) (float y) (float z)))
-  ([x y u v] (.vertex (current-graphics) (float x) (float y) (float u) (float v)))
-  ([x y z u v]
-     (.vertex (current-graphics) (float x) (float y) (float z) (float u) (float v))))
-
-#+clj
-(defn
-  ^{:requires-bindings false
-    :processing-name "year()"
-    :category "Input"
-    :subcategory "Time & Date"
-    :added "1.0"}
-  year
-  "Returns the current year as an integer (2003, 2004, 2005, etc)."
-  []
-  (PApplet/year))
-
-(defn
-  ^{:requires-bindings true
-    :processing-name "getWidth()"
-    :category "Environment"
-    :subcategory nil
-    :added "1.0"}
-  width
-  "Width of the display window. The value of width is zero until size is
-  called."
-  []
-  #+clj (.getWidth (current-applet))
-  #+cljs (.-width (current-graphics)))
-
-#+clj
-(defmacro
-  ^{:requires-bindings true
-    :processing-name nil
-    :category "Color"
-    :subcategory "Utility Macros"
-    :added "1.7"}
-  with-fill
-  "Temporarily set the fill color for the body of this macro.
-   The code outside of with-fill form will have the previous fill color set.
-
-   The fill color has to be in a vector!
-   Example: (with-fill [255] ...)
-            (with-fill [10 80 98] ...)"
-  [fill-args & body]
-  `(let [old-fill# (current-fill)]
-     (apply fill ~fill-args)
-     ~@body
-     (fill old-fill#)))
-
-#+clj
-(defmacro
-  ^{:requires-bindings true
-    :processing-name nil
-    :category "Color"
-    :subcategory "Utility Macros"
-    :added "1.7"}
-  with-stroke
-  "Temporarily set the stroke color for the body of this macro.
-   The code outside of with-stroke form will have the previous stroke color set.
-
-   The stroke color has to be in a vector!
-   Example: (with-stroke [255] ...)
-            (with-stroke [10 80 98] ...)"
-  [stroke-args & body]
-  `(let [old-stroke# (current-stroke)]
-     (apply stroke ~stroke-args)
-     ~@body
-     (stroke old-stroke#)))
-
-#+clj
-(defmacro
-  ^{:requires-bindings true
-    :processing-name nil
-    :category "Transform"
-    :subcategory "Utility Macros"
-    :added "1.0"}
-  with-translation
-  "Performs body with translation, restores current transformation on
-  exit."
-  [translation-vector & body]
-  `(let [tr# ~translation-vector]
-     (push-matrix)
-     (translate tr#)
-     ~@body
-     (pop-matrix)))
-
-#+clj
-(defmacro
-  ^{:requires-bindings true
-    :processing-name nil
-    :category "Transform"
-    :subcategory "Utility Macros"
-    :added "1.0"}
-  with-rotation
-  "Performs body with rotation, restores current transformation on exit.
-  Accepts a vector [angle] or [angle x-axis y-axis z-axis].
-
-  Example:
-    (with-rotation [angle]
-      (vertex 1 2))"
-  [rotation & body]
-  `(let [tr# ~rotation]
-     (push-matrix)
-     (apply rotate tr#)
-     ~@body
-     (pop-matrix)))
-
-#+clj
-(defmacro
-  ^{:requires-bindings true
-    :processing-name nil
-    :category "Rendering"
-    :added "1.7"}
-  with-graphics
-  "All subsequent calls of any drawing function will draw on given graphics.
-  'with-graphics' cannot be nested (you can draw simultaneously only on 1 graphics)"
-  [graphics & body]
-  `(binding [*graphics* ~graphics]
-     (.beginDraw ~graphics)
-     ~@body
-     (.endDraw ~graphics)))
 
 ;;; Useful trig constants
 #+clj (def PI  (float Math/PI))

                      :radius PApplet/RADIUS
                      :corner PApplet/CORNER
                      :corners PApplet/CORNERS})

#+clj
(defn
  ^{:requires-bindings true
    :processing-name "ellipseMode()"
    :category "Shape"
    :subcategory "Attributes"
    :added "1.0"}
  ellipse-mode
  "Modifies the origin of the ellispse according to the specified mode:

  :center  - specifies the location of the ellipse as
             the center of the shape. (Default).
  :radius  - similar to center, but the width and height parameters to
             ellipse specify the radius of the ellipse, rather than the
             diameter.
  :corner  - draws the shape from the upper-left corner of its bounding
             box.
  :corners - uses the four parameters to ellipse to set two opposing
             corners of the ellipse's bounding box."
  [mode]
  (let [mode (resolve-constant-key mode ellipse-modes)]
    (.ellipseMode (current-graphics) (int mode))))

(defn
  ^{:requires-bindings true
    :processing-name "emissive()"
    :category "Lights, Camera"
    :subcategory "Material Properties"
    :added "1.0"}
  emissive-float
  "Sets the emissive color of the material used for drawing shapes
 drawn to the screen. Used in combination with ambient, specular, and
 shininess in setting the material properties of shapes. Converts all
 args to floats"
  ([float-val] (.emissive (current-graphics) (float float-val)))
  ([r g b] (.emissive (current-graphics) (float r) (float g) (float b))))

(defn
  ^{:requires-bindings true
    :processing-name "emissive()"
    :category "Lights, Camera"
    :subcategory "Material Properties"
    :added "1.0"}
  emissive-int
  "Sets the emissive color of the material used for drawing shapes
  drawn to the screen. Used in combination with ambient, specular, and
  shininess in setting the material properties of shapes. Converts all
  args to ints"
  [int-val] (.emissive (current-graphics) (int int-val)))

#+clj
(defn
  ^{:requires-bindings true
    :processing-name "emissive()"
    :category "Lights, Camera"
    :subcategory "Material Properties"
    :added "1.0"}
  emissive
  "Sets the emissive color of the material used for drawing shapes
  drawn to the screen. Used in combination with ambient, specular, and
  shininess in setting the material properties of shapes.

  If passed one arg - it is assumed to be an int (i.e. a color),
  multiple args are converted to floats."
  ([c] (if (int-like? c) (emissive-int c) (emissive-float c)))
  ([r g b] (emissive-float r g b)))

(defn
  ^{:requires-bindings true
    :processing-name "endCamera()"
    :category "Lights, Camera"
    :subcategory "Camera"
    :added "1.0"}
  end-camera
  "Unsets the matrix mode from the camera matrix. See begin-camera."
  []
  (.endCamera (current-graphics)))


(defn
  ^{:requires-bindings true
    :processing-name "endContour()"
    :category "Shape"
    :subcategory "Vertex"
    :added "2.0"}
  end-contour
  "Use the begin-contour and end-contour function to create negative
  shapes within shapes. These functions can only be within a
  begin-shape/end-shape pair and they only work with the :p2d and :p3d
  renderers."
  []
  (.endContour (current-graphics)))

(defn
  ^{:requires-bindings true
    :processing-name "endRaw()"
    :category "Output"
    :subcategory "Files"
    :added "1.0"}
  end-raw
  "Complement to begin-raw; they must always be used together. See
  the begin-raw docstring for details."
  []
  (.endRaw (current-graphics)))


(defn
  ^{:requires-bindings true
    :processing-name "endShape()"
    :category "Shape"
    :subcategory "Vertex"
    :added "1.0"}
  end-shape
  "May only be called after begin-shape. When end-shape is called,
  all of image data defined since the previous call to begin-shape is
  written into the image buffer. The keyword :close may be passed to
  close the shape (to connect the beginning and the end)."
  ([] (.endShape (current-applet)))
  ([mode]
     (when-not (= :close mode)
       #+clj (throw (Exception. (str "Unknown mode value: " mode ". Expected :close")))
       #+cljs nil)
     (.endShape (current-applet)
                #+clj PApplet/CLOSE
                #+cljs 2)))

(defn
  ^{:requires-bindings true
    :processing-name "exit()"
    :category "Structure"
    :subcategory nil
    :added "1.0"}
  exit
  "Quits/stops/exits the program.  Rather than terminating
  immediately, exit will cause the sketch to exit after draw has
  completed (or after setup completes if called during the setup
  method). "
  []
  #+clj (applet-close (current-applet))
  #+cljs (.exit (current-applet)))

#+clj
(defn
  ^{:requires-bindings false
    :processing-name "exp()"
    :category "Math"
    :subcategory "Calculation"
    :added "1.0"}
  exp
  "Returns Euler's number e (2.71828...) raised to the power of the
  value parameter."
  [val]
  (PApplet/exp (float val)))

(defn
  ^{:requires-bindings true
    :processing-name "fill()"
    :category "Color"
    :subcategory "Setting"
    :added "1.0"}
  fill-float
  "Sets the color used to fill shapes. For example, (fill 204 102 0),
  will specify that all subsequent shapes will be filled with orange."
  ([gray] (.fill (current-graphics) (float gray)))
  ([gray alpha] (.fill (current-graphics) (float gray) (float alpha)))
  ([r g b] (.fill (current-graphics) (float r) (float g) (float b)))
  ([r g b alpha] (.fill (current-graphics) (float r) (float g) (float b) (float alpha))))

(defn
  ^{:requires-bindings true
    :processing-name "fill()"
    :category "Color"
    :subcategory "Setting"
    :added "1.0"}
  fill-int
  "Sets the color used to fill shapes."
  ([rgb] (.fill (current-graphics) (int rgb)))
  ([rgb alpha] (.fill (current-graphics) (int rgb) (float alpha))))

(defn
  ^{:requires-bindings true
    :processing-name "fill()"
    :category "Color"
    :subcategory "Setting"
    :added "1.0"}
  fill
  "Sets the color used to fill shapes."
  #+clj ([rgb] (if (int-like? rgb) (fill-int rgb) (fill-float rgb)))
  #+clj ([rgb alpha] (if (int-like? rgb) (fill-int rgb alpha) (fill-float rgb alpha)))
  ([r g b] (fill-float r g b))
  ([r g b a] (fill-float r g b a)))

#+clj
(def ^{:private true}
  filter-modes {:threshold PConstants/THRESHOLD
                :gray PConstants/GRAY
                :invert PConstants/INVERT
                :posterize PConstants/POSTERIZE
                :blur PConstants/BLUR
                :opaque PConstants/OPAQUE
                :erode PConstants/ERODE
                :dilate PConstants/DILATE})

#+clj
(defn
  ^{:requires-bindings true
    :processing-name "filter()"
    :category "Image"
    :subcategory "Pixels"
    :added "1.0"}
  display-filter
  "Originally named filter in Processing Language.
  Filters the display window with the specified mode and level.
  Level defines the quality of the filter and mode may be one of the following keywords:

  :threshold - converts the image to black and white pixels depending
               if they are above or below the threshold defined by
               the level parameter. The level must be between
               0.0 (black) and 1.0 (white). If no level is specified,
               0.5 is used.
  :gray      - converts any colors in the image to grayscale
               equivalents. Doesn't work with level.
  :invert    - sets each pixel to its inverse value. Doesn't work with level.
  :posterize - limits each channel of the image to the number of
               colors specified as the level parameter. The parameter can
               be set to values between 2 and 255, but results are most
               noticeable in the lower ranges.
  :blur      - executes a Guassian blur with the level parameter
               specifying the extent of the blurring. If no level
               parameter is used, the blur is equivalent to Guassian
               blur of radius 1.
  :opaque    - sets the alpha channel to entirely opaque. Doesn't work with level.
  :erode     - reduces the light areas. Doesn't work with level.
  :dilate    - increases the light areas.  Doesn't work with level."
  ([mode]
   (.filter (current-graphics)
            (int (resolve-constant-key mode filter-modes))))

  ([mode level]
     (let [mode (resolve-constant-key mode filter-modes)]
       (.filter (current-graphics) (int mode) (float level)))))

#+clj
(defn
  ^{:requires-bindings true
    :processing-name "filter()"
    :category "Image"
    :subcategory "Pixels"
    :added "2.0"}
  filter-shader
  "Originally named filter in Processing Language.
  Filters the display window with given shader (only in :p2d and :p3d modes)."
  [^PShader shader-obj] (.filter (current-graphics) shader-obj))

#+clj
(defn
  ^{:requires-bindings false
    :processing-name "floor()"
    :category "Math"
    :subcategory "Calculation"
    :added "2.0"}
  floor
  "Calculates the closest int value that is less than or equal to the valu  e of the parameter. For example, (floor 9.03) returns the
  value 9."
  [n]
  (PApplet/floor (float n)))

#+clj
(defn
  ^{:requires-bindings true
    :processing-name "focused"
    :category "Environment"
    :subcategory nil
    :added "1.0"}
  focused
  "Returns a boolean value representing whether the applet has focus."
  []  (.-focused (current-applet)))

(defn
  ^{:requires-bindings true
    :processing-name "frameCount"
    :category "Environment"
    :subcategory nil
    :added "1.0"}
  frame-count
  "The system variable frameCount contains the number of frames
  displayed since the program started. Inside setup() the value is 0
  and and after the first iteration of draw it is 1, etc."
  []
  (.frameCount (current-applet)))

(defn
  ^{:requires-bindings true
    :processing-name "frameRate"
    :category "Environment"
    :subcategory nil
    :added "1.0"}
  current-frame-rate
  "Returns the current framerate"
  []
  (.frameRate (current-applet)))

(defn
  ^{:requires-bindings true
    :processing-name "frameRate()"
    :category "Environment"
    :subcategory nil
    :added "1.0"}
  frame-rate
  "Specifies a new target framerate (number of frames to be displayed every
  second). If the processor is not fast enough to maintain the
  specified rate, it will not be achieved. For example, the function
  call (frame-rate 30) will attempt to refresh 30 times a second. It
  is recommended to set the frame rate within setup. The default rate
  is 60 frames per second."
  [new-rate]
  (.frameRate (current-applet) (float new-rate)))

(defn
  ^{:requires-bindings true
    :processing-name "frustum()"
    :category "Lights, Camera"
    :subcategory "Camera"
    :added "1.0"}
  frustum
  "Sets a perspective matrix defined through the parameters. Works
  like glFrustum, except it wipes out the current perspective matrix
  rather than muliplying itself with it."
  [left right bottom top near far]
  (.frustum (current-graphics) (float left) (float right) (float bottom) (float top)
            (float near) (float far)))

#+clj
(defn
  ^{:requires-bindings true
    :processing-name "get()"
    :category "Image"
    :subcategory "Pixels"
    :added "1.0"}
  get-pixel
  "Reads the color of any pixel or grabs a section of an image. If no
  parameters are specified, a copy of entire image is returned. Get the
  value of one pixel by specifying an x,y coordinate. Get a section of
  the image by specifying an additional width and height parameter.
  If the pixel requested is outside of the image window, black is returned.
  The numbers returned are scaled according to the current color ranges,
  but only RGB values are returned by this function. For example, even though
  you may have drawn a shape with (color-mode :hsb), the numbers returned
  will be in RGB.

  Getting the color of a single pixel with (get x y) is easy, but not
  as fast as grabbing the data directly using the pixels fn.

  If no img specified - current-graphics is used."
  ([] (get-pixel (current-graphics)))
  ([^PImage img] (.get img))
  ([x y] (get-pixel (current-graphics) x y))
  ([^PImage img x y] (.get img (int x) (int y)))
  ([x y w h] (get-pixel (current-graphics) x y w h))
  ([^PImage img x y w h] (.get img (int x) (int y) (int w) (int h))))

(defn
  ^{:requires-bindings true
    :processing-name "green()"
    :category "Color"
    :subcategory "Creating & Reading"
    :added "1.0"}
  green
  "Extracts the green value from a color, scaled to match current
  color-mode. This value is always returned as a float so be careful
  not to assign it to an int value."
  [col]
  (.green (current-graphics) (int col)))

#+clj
(defn
  ^{:require-binding false
    :processing-name "hex()"
    :category "Data"
    :subcategory "Conversion"}
  hex
  "Converts a byte, char, int, or color to a String containing the
  equivalent hexadecimal notation. For example color(0, 102, 153) will
  convert to the String \"FF006699\". This function can help make your
  geeky debugging sessions much happier. "
  ([val] (PApplet/hex (int val)))
  ([val num-digits] (PApplet/hex (int val) (int num-digits))))

(defn
  ^{:requires-bindings true
    :processing-name "getHeight()"
    :category "Environment"
    :subcategory nil
    :added "1.0"}
  height
  "Height of the display window. The value of height is zero until
  size is called."
  []
  #+clj (.getHeight (current-applet))
  #+cljs (.-height (current-graphics)))

#+clj
(def ^{:private true}

               :sphere 40
               :box 41})

#+clj
(def ^{:private true}
  blend-modes {:blend PApplet/BLEND
