code: # -----------------------------------------------------------------------------
  # Copyright (c) 2009-2016 Nicolas P. Rougier. All rights reserved.
  # Distributed under the (new) BSD License.
  # -----------------------------------------------------------------------------
  import numpy as np
  from glumpy import app, gl, gloo
  from glumpy.transforms import Position, OrthographicProjection, PanZoom
  
  # Create window
  window = app.Window(width=2*512, height=512, color=(1,1,1,1))
  
  # What to draw when necessary
  @window.event
  def on_draw(dt):
      window.clear()
      program.draw(gl.GL_POINTS)
      program['orientation'][-1] += np.pi/1024.0
  
  # Setup some markers
  n = 500+1
  data = np.zeros(n, dtype=[('position',    np.float32, 2),
                            ('fg_color',    np.float32, 4),
                            ('bg_color',    np.float32, 4),
                            ('size',        np.float32, 1),
                            ('head',        np.float32, 1),
                            ('orientation', np.float32, 1),
                            ('linewidth',   np.float32, 1)])
  data = data.view(gloo.VertexBuffer)
  data['linewidth'] = 1
  data['fg_color'] = 0, 0, 0, 1
  data['bg_color'] = 0, 0, 0, 1
  data['orientation'] = 0
  data['head'] = 0.25
  radius, theta, dtheta = 245.0, 0.0, 6.5 / 180.0 * np.pi
  for i in range(500):
      theta += dtheta
      x = 256 + radius * np.cos(theta)
      y = 256 + radius * np.sin(theta)
      r = 10.1 - i * 0.01
      radius -= 0.4
      data['orientation'][i] = theta + np.pi
      data['position'][i] = x, y
      data['size'][i] = 2 * r
      data['linewidth'][i] = 1.5 - 0.5*i/500.
  
  data['position'][-1]    = 512+256, 256
  data['size'][-1]        = 512/np.sqrt(2)
  data['linewidth'][-1]   = 16.0
  data['fg_color'][-1]    = 0, 0, 0, 1
  data['bg_color'][-1]    = .95, .95, .95, 1
  data['orientation'][-1] = 0
  
  program = gloo.Program("arrows/arrow.vert", "arrows/arrow.frag")
  program.bind(data)
  program['antialias'] = 1.00
  program['arrow']     = "stealth"
  program['paint']     = "filled"
  transform = OrthographicProjection(Position("position"))
  program['transform'] = transform
  window.attach(transform)
  
  app.run()
   # -----------------------------------------------------------------------------
  # Copyright (c) 2009-2016 Nicolas P. Rougier. All rights reserved.
  # Distributed under the (new) BSD License.
  # -----------------------------------------------------------------------------
  """ Fast and failsafe GL console """
  import numpy as np
  from glumpy import gl, glm, gloo
  
  
  # Translated from
  # http://www.piclist.com/tecHREF/datafile/charset/extractor/charset_extractor.htm
  __font_6x8__ = np.array([
      (0x00,0x00,0x00,0x00,0x00,0x00), (0x10,0xE3,0x84,0x10,0x01,0x00),
      (0x6D,0xB4,0x80,0x00,0x00,0x00), (0x00,0xA7,0xCA,0x29,0xF2,0x80),
      (0x20,0xE4,0x0C,0x09,0xC1,0x00), (0x65,0x90,0x84,0x21,0x34,0xC0),
      (0x21,0x45,0x08,0x55,0x23,0x40), (0x30,0xC2,0x00,0x00,0x00,0x00),
      (0x10,0x82,0x08,0x20,0x81,0x00), (0x20,0x41,0x04,0x10,0x42,0x00),
      (0x00,0xA3,0x9F,0x38,0xA0,0x00), (0x00,0x41,0x1F,0x10,0x40,0x00),
      (0x00,0x00,0x00,0x00,0xC3,0x08), (0x00,0x00,0x1F,0x00,0x00,0x00),
      (0x00,0x00,0x00,0x00,0xC3,0x00), (0x00,0x10,0x84,0x21,0x00,0x00),
      (0x39,0x14,0xD5,0x65,0x13,0x80), (0x10,0xC1,0x04,0x10,0x43,0x80),
      (0x39,0x10,0x46,0x21,0x07,0xC0), (0x39,0x10,0x4E,0x05,0x13,0x80),
      (0x08,0x62,0x92,0x7C,0x20,0x80), (0x7D,0x04,0x1E,0x05,0x13,0x80),
      (0x18,0x84,0x1E,0x45,0x13,0x80), (0x7C,0x10,0x84,0x20,0x82,0x00),
      (0x39,0x14,0x4E,0x45,0x13,0x80), (0x39,0x14,0x4F,0x04,0x23,0x00),
      (0x00,0x03,0x0C,0x00,0xC3,0x00), (0x00,0x03,0x0C,0x00,0xC3,0x08),
      (0x08,0x42,0x10,0x20,0x40,0x80), (0x00,0x07,0xC0,0x01,0xF0,0x00),
      (0x20,0x40,0x81,0x08,0x42,0x00), (0x39,0x10,0x46,0x10,0x01,0x00),
      (0x39,0x15,0xD5,0x5D,0x03,0x80), (0x39,0x14,0x51,0x7D,0x14,0x40),
      (0x79,0x14,0x5E,0x45,0x17,0x80), (0x39,0x14,0x10,0x41,0x13,0x80),
      (0x79,0x14,0x51,0x45,0x17,0x80), (0x7D,0x04,0x1E,0x41,0x07,0xC0),
      (0x7D,0x04,0x1E,0x41,0x04,0x00), (0x39,0x14,0x17,0x45,0x13,0xC0),
      (0x45,0x14,0x5F,0x45,0x14,0x40), (0x38,0x41,0x04,0x10,0x43,0x80),
      (0x04,0x10,0x41,0x45,0x13,0x80), (0x45,0x25,0x18,0x51,0x24,0x40),
      (0x41,0x04,0x10,0x41,0x07,0xC0), (0x45,0xB5,0x51,0x45,0x14,0x40),
      (0x45,0x95,0x53,0x45,0x14,0x40), (0x39,0x14,0x51,0x45,0x13,0x80),
      (0x79,0x14,0x5E,0x41,0x04,0x00), (0x39,0x14,0x51,0x55,0x23,0x40),
      (0x79,0x14,0x5E,0x49,0x14,0x40), (0x39,0x14,0x0E,0x05,0x13,0x80),
      (0x7C,0x41,0x04,0x10,0x41,0x00), (0x45,0x14,0x51,0x45,0x13,0x80),
      (0x45,0x14,0x51,0x44,0xA1,0x00), (0x45,0x15,0x55,0x55,0x52,0x80),
      (0x45,0x12,0x84,0x29,0x14,0x40), (0x45,0x14,0x4A,0x10,0x41,0x00),
      (0x78,0x21,0x08,0x41,0x07,0x80), (0x38,0x82,0x08,0x20,0x83,0x80),
      (0x01,0x02,0x04,0x08,0x10,0x00), (0x38,0x20,0x82,0x08,0x23,0x80),
      (0x10,0xA4,0x40,0x00,0x00,0x00), (0x00,0x00,0x00,0x00,0x00,0x3F),
      (0x30,0xC1,0x00,0x00,0x00,0x00), (0x00,0x03,0x81,0x3D,0x13,0xC0),
      (0x41,0x07,0x91,0x45,0x17,0x80), (0x00,0x03,0x91,0x41,0x13,0x80),
      (0x04,0x13,0xD1,0x45,0x13,0xC0), (0x00,0x03,0x91,0x79,0x03,0x80),
      (0x18,0x82,0x1E,0x20,0x82,0x00), (0x00,0x03,0xD1,0x44,0xF0,0x4E),
      (0x41,0x07,0x12,0x49,0x24,0x80), (0x10,0x01,0x04,0x10,0x41,0x80),
      (0x08,0x01,0x82,0x08,0x24,0x8C), (0x41,0x04,0x94,0x61,0x44,0x80),
      (0x10,0x41,0x04,0x10,0x41,0x80), (0x00,0x06,0x95,0x55,0x14,0x40),
      (0x00,0x07,0x12,0x49,0x24,0x80), (0x00,0x03,0x91,0x45,0x13,0x80),
      (0x00,0x07,0x91,0x45,0x17,0x90), (0x00,0x03,0xD1,0x45,0x13,0xC1),
      (0x00,0x05,0x89,0x20,0x87,0x00), (0x00,0x03,0x90,0x38,0x13,0x80),
      (0x00,0x87,0x88,0x20,0xA1,0x00), (0x00,0x04,0x92,0x49,0x62,0x80),
      (0x00,0x04,0x51,0x44,0xA1,0x00), (0x00,0x04,0x51,0x55,0xF2,0x80),
      (0x00,0x04,0x92,0x31,0x24,0x80), (0x00,0x04,0x92,0x48,0xE1,0x18),
      (0x00,0x07,0x82,0x31,0x07,0x80), (0x18,0x82,0x18,0x20,0x81,0x80),
      (0x10,0x41,0x00,0x10,0x41,0x00), (0x30,0x20,0x83,0x08,0x23,0x00),
      (0x29,0x40,0x00,0x00,0x00,0x00), (0x10,0xE6,0xD1,0x45,0xF0,0x00)], dtype=np.float32)
  
  __vertex__ = """
  #version 120
  uniform mat4 projection;
  uniform float scale;
  uniform vec4 color;
  attribute vec2 position;
  attribute vec3 bytes_012, bytes_345;
  varying vec4 v_color;
  varying vec3 v_bytes_012, v_bytes_345;
  void main (void)
  {
      gl_Position = projection*vec4(position*scale, 0.0, 1.0);
      gl_PointSize = 8.0 * scale;
  
      v_color = color;
      v_bytes_012 = bytes_012;
      v_bytes_345 = bytes_345;
  }
  """
  
  __fragment__ = """
  #version 120
  float segment(float edge0, float edge1, float x)
  {
      return step(edge0,x) * (1.0-step(edge1,x));
  }
  varying vec4 v_color;
  varying vec3 v_bytes_012, v_bytes_345;
  void main(void)
  {
      vec2 uv = floor(gl_PointCoord.xy * 8.0);
      if(uv.x > 5.0) discard;
      if(uv.y > 7.0) discard;
      float index  = floor( (uv.y*6.0+uv.x)/8.0 );
      float offset = floor( mod(uv.y*6.0+uv.x,8.0));
      float byte = segment(0.0,1.0,index) * v_bytes_012.x
                 + segment(1.0,2.0,index) * v_bytes_012.y
                 + segment(2.0,3.0,index) * v_bytes_012.z
                 + segment(3.0,4.0,index) * v_bytes_345.x
                 + segment(4.0,5.0,index) * v_bytes_345.y
                 + segment(5.0,6.0,index) * v_bytes_345.z;
      if( floor(mod(byte / (128.0/pow(2.0,offset)), 2.0)) > 0.0 )
          gl_FragColor = v_color;
      else
          discard;
  }
  """
  
  
  class Console(object):
      """ Fast and failsafe GL console """
  
      def __init__(self, rows, cols, scale=2, color=(0,0,0,1)):
  
          # Harcoded because of font above and shader program
          self._cwidth = 6
          self._cheight = 8
          self._scale = int(max(scale,1))
  
          dtype = [("position", np.float32, 2),
                   ("glyph",    np.float32, 6)]
          self._program = gloo.Program(__vertex__, __fragment__)
          self._data = np.zeros((rows,cols), dtype).view(gloo.VertexBuffer)
          dtype = [("position",  np.float32, 2),
                   ("bytes_012", np.float32, 3),
                   ("bytes_345", np.float32, 3)]
          self._program.bind(self._data.view(dtype))
  
          # Initialize glyph position (they won't move)
          C,R = np.meshgrid(np.arange(cols), np.arange(rows))
          self._data['position'][...,0] = 4.0 + self.cwidth*C
          self._data['position'][...,1] = 4.0 + self.cheight*R
  
          self._program['scale'] = self._scale
          self._program['color'] = color
          self._rows, self._cols = rows, cols
          self._row = 0
  
  
      @property
      def scale(self):
          return self._scale
  
  
      @property
      def rows(self):
          return self._rows
  
  
      @property
      def cols(self):
          return self._cols
  
  
      @property
      def cwidth(self):
          return self._cwidth
  
  
      @property
      def cheight(self):
          return self._cheight + 2
  
  
      def on_resize(self, width, height):
          """ Update console projection """
  
          self._program["projection"] = glm.ortho(0, width, height, 0, -1, +1)
  
  
      def draw(self):
          """ Draw console """
  
          self._program.draw(gl.GL_POINTS)
  
  
      def clear(self):
          """ Clear console """
  
          self._data["glyph"] = 0
          self._row = 0
  
  
      def write(self, text=""):
          """ Write text and scroll """
  
          # Clear line
          self._data["glyph"][self._row] = 0
  
          if len(text):
              # Crop text if necessary
              text = text[:self._cols]
              # Write text
              I = np.array([ord(c)-32 for c in text])
              self._data["glyph"][self._row,:len(text)] = __font_6x8__[I]
  
          # Update row and scroll if necessary
          self._row += 1
          if self._row > self._rows-1:
              self._data["glyph"][:-n] = self._data["glyph"][n:]
              self._data["glyph"][-n:] = 0
              self._row = self._rows-1
  
apis: numpy.sqrt numpy.sin numpy.cos numpy.zeros
apis: numpy.array numpy.arange numpy.zeros