[gatein-commits] gatein SVN: r2410 - in components/simplecaptcha: trunk and 14 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Wed Mar 31 11:23:51 EDT 2010


Author: thomas.heute at jboss.com
Date: 2010-03-31 11:23:50 -0400 (Wed, 31 Mar 2010)
New Revision: 2410

Added:
   components/simplecaptcha/tags/
   components/simplecaptcha/trunk/
   components/simplecaptcha/trunk/.classpath
   components/simplecaptcha/trunk/.project
   components/simplecaptcha/trunk/.settings/
   components/simplecaptcha/trunk/.settings/org.eclipse.jdt.core.prefs
   components/simplecaptcha/trunk/.settings/org.maven.ide.eclipse.prefs
   components/simplecaptcha/trunk/patch.txt
   components/simplecaptcha/trunk/pom.xml
   components/simplecaptcha/trunk/src/
   components/simplecaptcha/trunk/src/main/
   components/simplecaptcha/trunk/src/main/java/
   components/simplecaptcha/trunk/src/main/java/nl/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/Captcha.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/CaptchaBean.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/BackgroundProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/FlatColorBackgroundProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/GradiatedBackgroundProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/SquigglesBackgroundProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/TransparentBackgroundProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/BlockGimpyRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/DropShadowGimpyRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/FishEyeGimpyRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/GimpyRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/RippleGimpyRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/ShearGimpyRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/CurvedLineNoiseProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/NoiseProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/StraightLineNoiseProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/ChineseCaptchaServlet.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/SimpleCaptchaServlet.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/StickyCaptchaServlet.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/DefaultTextProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/FiveLetterFirstNameTextProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/TextProducer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/ColoredEdgesWordRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/DefaultWordRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/WordRenderer.java
   components/simplecaptcha/trunk/src/main/java/nl/captcha/util/
   components/simplecaptcha/trunk/src/main/java/nl/captcha/util/ImageUtil.java
Log:
Adding simplecatcha


Added: components/simplecaptcha/trunk/.classpath
===================================================================
--- components/simplecaptcha/trunk/.classpath	                        (rev 0)
+++ components/simplecaptcha/trunk/.classpath	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

Added: components/simplecaptcha/trunk/.project
===================================================================
--- components/simplecaptcha/trunk/.project	                        (rev 0)
+++ components/simplecaptcha/trunk/.project	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>sc</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
+			<arguments>
+				<dictionary>
+					<key>LaunchConfigHandle</key>
+					<value>&lt;project&gt;/.externalToolBuilders/build-jar.launch</value>
+				</dictionary>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

Added: components/simplecaptcha/trunk/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- components/simplecaptcha/trunk/.settings/org.eclipse.jdt.core.prefs	                        (rev 0)
+++ components/simplecaptcha/trunk/.settings/org.eclipse.jdt.core.prefs	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,5 @@
+#Wed Mar 31 16:06:54 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6

Added: components/simplecaptcha/trunk/.settings/org.maven.ide.eclipse.prefs
===================================================================
--- components/simplecaptcha/trunk/.settings/org.maven.ide.eclipse.prefs	                        (rev 0)
+++ components/simplecaptcha/trunk/.settings/org.maven.ide.eclipse.prefs	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,9 @@
+#Wed Mar 31 16:05:04 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1

Added: components/simplecaptcha/trunk/patch.txt
===================================================================
--- components/simplecaptcha/trunk/patch.txt	                        (rev 0)
+++ components/simplecaptcha/trunk/patch.txt	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1 @@
+This is a fork from SimpleCaptchia 1.1.1 to be compiled on JDK 5 and to use the com.jhlabs.filters libs available from iBiblio Maven repository

Added: components/simplecaptcha/trunk/pom.xml
===================================================================
--- components/simplecaptcha/trunk/pom.xml	                        (rev 0)
+++ components/simplecaptcha/trunk/pom.xml	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,30 @@
+<project>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+      <groupId>org.gatein</groupId>
+      <artifactId>gatein-parent</artifactId>
+      <version>1.0.0-GA</version>
+   </parent>
+
+   <groupId>org.gatein.simplecaptcha</groupId>
+   <artifactId>simplecaptcha</artifactId>
+   <version>1.1.1-GA-Patch01-SNAPSHOT</version>
+   <packaging>jar</packaging>
+
+   <dependencies>
+      <dependency>
+         <groupId>com.jhlabs</groupId>
+         <artifactId>filters</artifactId>
+         <version>2.0.235</version>
+      </dependency>
+      <dependency>
+         <groupId>javax.servlet</groupId>
+         <artifactId>servlet-api</artifactId>
+         <version>2.5</version>
+      </dependency>
+   </dependencies>
+
+</project>
+  

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/Captcha.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/Captcha.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/Captcha.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,265 @@
+package nl.captcha;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import javax.imageio.ImageIO;
+
+import nl.captcha.backgrounds.BackgroundProducer;
+import nl.captcha.backgrounds.TransparentBackgroundProducer;
+import nl.captcha.gimpy.GimpyRenderer;
+import nl.captcha.gimpy.RippleGimpyRenderer;
+import nl.captcha.noise.CurvedLineNoiseProducer;
+import nl.captcha.noise.NoiseProducer;
+import nl.captcha.text.producer.DefaultTextProducer;
+import nl.captcha.text.producer.TextProducer;
+import nl.captcha.text.renderer.DefaultWordRenderer;
+import nl.captcha.text.renderer.WordRenderer;
+
+
+/**
+ * A builder for generating a CAPTCHA image/answer pair.
+ * 
+ * <p>
+ * Example for generating a new CAPTCHA:
+ * </p>
+ * <pre>Captcha captcha = new Captcha.Builder(200, 50)
+ * 	.addText()
+ * 	.addBackground()
+ * 	.build();</pre>
+ * <p>Note that the <code>build()</code> must always be called last. Other methods are optional,
+ * and can sometimes be repeated. For example:</p>
+ * <pre>Captcha captcha = new Captcha.Builder(200, 50)
+ * 	.addText()
+ * 	.addNoise()
+ * 	.addNoise()
+ * 	.addNoise()
+ * 	.addBackground()
+ * 	.build();</pre>
+ * <p>Adding multiple backgrounds has no affect; the last background added will simply be the
+ * one that is eventually rendered.</p>
+ * <p>To validate that <code>answerStr</code> is a correct answer to the CAPTCHA:</p>
+ * 
+ * <code>captcha.isCorrect(answerStr);</code>
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * v
+ */
+public final class Captcha implements Serializable {
+
+    private static final long serialVersionUID = 617511236L;
+    public static final String NAME = "simpleCaptcha";
+    private Builder _builder;
+
+    private Captcha(Builder builder) {
+        _builder = builder;
+    }
+
+    public static class Builder implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /**
+         * @serial
+         */
+        private String _answer = "";
+        /**
+         * @serial
+         */
+        private BufferedImage _img;
+        /**
+         * @serial
+         */
+        private BufferedImage _bg;
+        private boolean _addBorder = false;
+
+        public Builder(int width, int height) {
+            _img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        }
+
+        /**
+         * Add a background using the default BackgroundProducer.
+         * 
+         * @return
+         */
+        public Builder addBackground() {
+            return addBackground(new TransparentBackgroundProducer());
+        }
+
+        /**
+         * Add a background using the given BackgroundProducer.
+         * 
+         * @param bgProd
+         * @return
+         */
+        public Builder addBackground(BackgroundProducer bgProd) {
+        	_bg = bgProd.getBackground(_img.getWidth(), _img.getHeight());
+            
+            return this;
+        }
+
+        /**
+         * Add text to the image using the default TextProducer
+         * 
+         * @return
+         */
+        public Builder addText() {
+            return addText(new DefaultTextProducer());
+        }
+
+        /**
+         * Add text to the image using the given TextProducer
+         * 
+         * @param txtProd
+         * @return
+         */
+        public Builder addText(TextProducer txtProd) {
+            return addText(txtProd, new DefaultWordRenderer());
+        }
+        
+        /**
+         * Display the answer on the image using the given WordRenderer.
+         *  
+         * @param wRenderer
+         * @return
+         */
+        public Builder addText(WordRenderer wRenderer) {
+        	return addText(new DefaultTextProducer(), wRenderer);
+        }
+        
+        public Builder addText(TextProducer txtProd, WordRenderer wRenderer) {
+        	_answer += txtProd.getText();
+        	wRenderer.render(_answer, _img);
+        	
+        	return this;
+        }
+
+        /**
+         * Add noise using the default NoiseProducer.
+         * 
+         * @return
+         */
+        public Builder addNoise() {
+            return this.addNoise(new CurvedLineNoiseProducer());
+        }
+
+        /**
+         * Add noise using the given NoiseProducer.
+         * 
+         * @param nProd
+         * @return
+         */
+        public Builder addNoise(NoiseProducer nProd) {
+            nProd.makeNoise(_img);
+            return this;
+        }
+
+        /**
+         * Gimp the image using the default GimpyRenderer.
+         * 
+         * @return
+         */
+        public Builder gimp() {
+            return gimp(new RippleGimpyRenderer());
+        }
+
+        /**
+         * Gimp the image using the given GimpyRenderer.
+         * 
+         * @param gimpy
+         * @return
+         */
+        public Builder gimp(GimpyRenderer gimpy) {
+            gimpy.gimp(_img);
+            return this;
+        }
+
+        /**
+         * Draw a single-pixel wide black border around the image.
+         * 
+         * @return
+         */
+        public Builder addBorder() {
+        	_addBorder = true;
+
+            return this;
+        }
+
+        /**
+         * Build the CAPTCHA. This method should always be called, and should always
+         * be called last.
+         * 
+         * @return
+         */
+        public Captcha build() {
+        	if (_bg == null) {
+        		_bg = new TransparentBackgroundProducer().getBackground(_img.getWidth(), _img.getHeight());
+        	}
+
+        	// Paint the main image over the background
+        	Graphics2D g = _bg.createGraphics();
+        	g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
+        	g.drawImage(_img, null, null);
+        	
+        	// Add the border, if necessary
+        	if (_addBorder) {
+        		int width = _img.getWidth();
+        		int height = _img.getHeight();
+        		
+	            g.setColor(Color.BLACK);
+	            g.drawLine(0, 0, 0, width);
+	            g.drawLine(0, 0, width, 0);
+	            g.drawLine(0, height - 1, width, height - 1);
+	            g.drawLine(width - 1, height - 1, width - 1, 0);
+        	}
+
+        	_img = _bg;
+        	
+            return new Captcha(this);
+        }
+
+        @Override
+        public String toString() {
+            StringBuffer sb = new StringBuffer();
+            sb.append("[Answer: ");
+            sb.append(_answer);
+            sb.append("][Image: ");
+            sb.append(_img);
+            sb.append("]");
+
+            return sb.toString();
+        }
+        
+        private void writeObject(ObjectOutputStream out) throws IOException {
+            out.writeObject(_answer);
+            ImageIO.write(_img, "png", ImageIO.createImageOutputStream(out));
+        }
+
+        private void readObject(ObjectInputStream in) throws IOException,
+                ClassNotFoundException {
+            _answer = (String) in.readObject();
+            _img = ImageIO.read(ImageIO.createImageInputStream(in));
+        }
+    }
+
+    public boolean isCorrect(String answer) {
+        return _builder._answer.equals(answer);
+    }
+    
+    public String getAnswer() {
+    	return _builder._answer;
+    }
+
+    public BufferedImage getImage() {
+        return _builder._img;
+    }
+
+    @Override
+    public String toString() {
+        return _builder.toString();
+    }
+}
\ No newline at end of file

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/CaptchaBean.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/CaptchaBean.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/CaptchaBean.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,122 @@
+package nl.captcha;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+import nl.captcha.backgrounds.BackgroundProducer;
+import nl.captcha.backgrounds.TransparentBackgroundProducer;
+import nl.captcha.gimpy.GimpyRenderer;
+import nl.captcha.noise.NoiseProducer;
+import nl.captcha.text.producer.TextProducer;
+import nl.captcha.text.renderer.DefaultWordRenderer;
+import nl.captcha.text.renderer.WordRenderer;
+
+
+/**
+ * Simple CAPTCHA bean intended to be used by Spring.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James
+ *
+ */
+public class CaptchaBean {
+	private BackgroundProducer _bgProd = new TransparentBackgroundProducer();
+	private TextProducer _txtProd;
+	private NoiseProducer _noiseProd;
+	private GimpyRenderer _gimpy;
+	private boolean _addBorder = false;
+	
+	private String _answer = "";
+	private BufferedImage _img;
+	private BufferedImage _bg;
+	
+	public CaptchaBean(int width, int height) {
+		_img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+	}
+	
+	public CaptchaBean build() {
+		// Add and render the text
+		if (_txtProd != null) {
+			_answer += _txtProd.getText();
+			WordRenderer wr = new DefaultWordRenderer();
+			wr.render(_answer, _img);
+		}
+		
+		if (_noiseProd != null) {
+			_noiseProd.makeNoise(_img);
+		}
+		
+		if (_gimpy != null) {
+			_gimpy.gimp(_img);
+		}
+		
+		_bg = _bgProd.getBackground(_img.getWidth(), _img.getHeight());
+		
+    	// Paint the main image over the background
+    	Graphics2D g = _bg.createGraphics();
+    	g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
+    	g.drawImage(_img, null, null);
+    	
+    	// Add the border, if necessary
+    	if (_addBorder) {
+    		int width = _img.getWidth();
+    		int height = _img.getHeight();
+    		
+            g.setColor(Color.BLACK);
+            g.drawLine(0, 0, 0, width);
+            g.drawLine(0, 0, width, 0);
+            g.drawLine(0, height - 1, width, height - 1);
+            g.drawLine(width - 1, height - 1, width - 1, 0);
+    	}
+    	_img = _bg;
+    	g.dispose();
+		
+		return this;
+	}
+	
+	public boolean isCorrect(String answer) {
+		return answer.equals(_answer);
+	}
+	
+	public BufferedImage getImage() {
+		return _img;
+	}
+	
+	public BackgroundProducer getBgProd() {
+		return _bgProd;
+	}
+	public void setBgProd(BackgroundProducer bgProd) {
+		_bgProd = bgProd;
+	}
+	public TextProducer getTxtProd() {
+		return _txtProd;
+	}
+	public void setTxtProd(TextProducer txtProd) {
+		_txtProd = txtProd;
+	}
+	public NoiseProducer getNoiseProd() {
+		return _noiseProd;
+	}
+	public void setNoiseProd(NoiseProducer noiseProd) {
+		_noiseProd = noiseProd;
+	}
+	public GimpyRenderer getGimpy() {
+		return _gimpy;
+	}
+	public void setGimpy(GimpyRenderer gimpy) {
+		_gimpy = gimpy;
+	}
+	public boolean isAddBorder() {
+		return _addBorder;
+	}
+	public void setAddBorder(boolean addBorder) {
+		_addBorder = addBorder;
+	}
+	public String getAnswer() {
+		return _answer;
+	}
+	public void setAnswer(String answer) {
+		_answer = answer;
+	}
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/BackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/BackgroundProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/BackgroundProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,21 @@
+package nl.captcha.backgrounds;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public interface BackgroundProducer {
+
+    /**
+     * Add the background to the given image.
+     * 
+     * @param image
+     * @return
+     */
+    public BufferedImage addBackground(BufferedImage image);
+    
+    public BufferedImage getBackground(int width, int height);
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/FlatColorBackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/FlatColorBackgroundProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/FlatColorBackgroundProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,38 @@
+package nl.captcha.backgrounds;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+public final class FlatColorBackgroundProducer implements BackgroundProducer {
+
+    private Color _color = Color.GRAY;
+
+    public FlatColorBackgroundProducer() {
+        this(Color.GRAY);
+    }
+
+    public FlatColorBackgroundProducer(Color color) {
+        _color = color;
+    }
+
+    public BufferedImage addBackground(BufferedImage bi) {
+        int width = bi.getWidth();
+        int height = bi.getHeight();
+        return this.getBackground(width, height);
+    }
+
+    public BufferedImage getBackground(int width, int height) {
+        BufferedImage img = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_RGB);
+
+        Graphics2D graphics = img.createGraphics();
+        graphics.setPaint(_color);
+        graphics.fill(new Rectangle2D.Double(0, 0, width, height));
+        graphics.drawImage(img, 0, 0, null);
+        graphics.dispose();
+
+        return img;
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/GradiatedBackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/GradiatedBackgroundProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/GradiatedBackgroundProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,64 @@
+package nl.captcha.backgrounds;
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Creates a gradiated background with the given <i>from</i> and <i>to</i>
+ * Color values. If none are specified they default to light gray and white
+ * respectively.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class GradiatedBackgroundProducer implements BackgroundProducer {
+
+    private Color _fromColor = Color.DARK_GRAY;
+    private Color _toColor = Color.WHITE;
+    
+    public BufferedImage getBackground(int width, int height) {
+        // create an opaque image
+        BufferedImage img = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_RGB);
+
+        Graphics2D g = img.createGraphics();
+        RenderingHints hints = new RenderingHints(
+                RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+
+        g.setRenderingHints(hints);
+
+        // create the gradient color
+        GradientPaint ytow = new GradientPaint(0, 0, _fromColor, width, height,
+                _toColor);
+
+        g.setPaint(ytow);
+        // draw gradient color
+        g.fill(new Rectangle2D.Double(0, 0, width, height));
+
+        // draw the transparent image over the background
+        g.drawImage(img, 0, 0, null);
+        g.dispose();
+
+        return img;
+    }
+
+    public BufferedImage addBackground(BufferedImage image) {
+        int width = image.getWidth();
+        int height = image.getHeight();
+        
+        return getBackground(width, height);
+    }
+
+    public void setFromColor(Color fromColor) {
+        _fromColor = fromColor;
+    }
+
+    public void setToColor(Color toColor) {
+        _toColor = toColor;
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/SquigglesBackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/SquigglesBackgroundProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/SquigglesBackgroundProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,49 @@
+package nl.captcha.backgrounds;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Graphics2D;
+import java.awt.geom.Arc2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Adds a black and white squiggly background to the image.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class SquigglesBackgroundProducer implements BackgroundProducer {
+
+    public BufferedImage addBackground(BufferedImage image) {
+        int width = image.getWidth();
+        int height = image.getHeight();
+        return getBackground(width, height);
+    }
+    
+    public BufferedImage getBackground(int width, int height) {
+        BufferedImage result = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_RGB);
+        Graphics2D graphics = result.createGraphics();
+
+        BasicStroke bs = new BasicStroke(2.0f, BasicStroke.CAP_BUTT,
+                BasicStroke.JOIN_MITER, 2.0f, new float[] { 2.0f, 2.0f }, 0.0f);
+        graphics.setStroke(bs);
+        AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
+                0.75f);
+        graphics.setComposite(ac);
+
+        graphics.translate(width * -1.0, 0.0);
+        double delta = 5.0;
+        double xt;
+        double ts = 0.0;
+        for (xt = 0.0; xt < (2.0 * width); xt += delta) {
+            Arc2D arc = new Arc2D.Double(0, 0, width, height, 0.0, 360.0,
+                    Arc2D.OPEN);
+            graphics.draw(arc);
+            graphics.translate(delta, 0.0);
+            ts += delta;
+        }
+        graphics.dispose();
+        return result;
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/TransparentBackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/TransparentBackgroundProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/TransparentBackgroundProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,29 @@
+package nl.captcha.backgrounds;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Generates a transparent background.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class TransparentBackgroundProducer implements BackgroundProducer {
+
+	public BufferedImage addBackground(BufferedImage image) {
+		return getBackground(image.getWidth(), image.getHeight());
+	}
+
+	public BufferedImage getBackground(int width, int height) {
+		BufferedImage bg = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
+		Graphics2D g = bg.createGraphics();
+
+		g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
+		g.fillRect(0, 0, width, height);
+		
+		return bg;
+	}
+
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/BlockGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/BlockGimpyRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/BlockGimpyRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,28 @@
+package nl.captcha.gimpy;
+
+import java.awt.image.BufferedImage;
+import com.jhlabs.image.BlockFilter;
+
+import static nl.captcha.util.ImageUtil.applyFilter;
+
+public class BlockGimpyRenderer implements GimpyRenderer {
+	
+	private static final int DEF_BLOCK_SIZE = 3;
+	private final int _blockSize;
+	
+	public BlockGimpyRenderer() {
+		this(DEF_BLOCK_SIZE);
+	}
+	
+	public BlockGimpyRenderer(int blockSize) {
+		_blockSize = blockSize;
+	}
+	
+	public void gimp(BufferedImage image) {
+		BlockFilter filter = new BlockFilter();
+		filter.setBlockSize(_blockSize);
+
+        BufferedImage buffer = filter.filter(image, null);
+        applyFilter(buffer, null);
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/DropShadowGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/DropShadowGimpyRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/DropShadowGimpyRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,38 @@
+package nl.captcha.gimpy;
+
+import java.awt.image.BufferedImage;
+import com.jhlabs.image.ShadowFilter;
+
+import static nl.captcha.util.ImageUtil.applyFilter;
+
+/**
+ * Twists text and adds a dark drop-shadow.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class DropShadowGimpyRenderer implements GimpyRenderer {
+	private static final int DEFAULT_RADIUS = 3;
+	private static final int DEFAULT_OPACITY = 75;
+	
+	private final int _radius;
+	private final int _opacity;
+	
+	public DropShadowGimpyRenderer() {
+		this(DEFAULT_RADIUS, DEFAULT_OPACITY);
+	}
+	
+	public DropShadowGimpyRenderer(int radius, int opacity) {
+		_radius = radius;
+		_opacity = opacity;
+	}
+
+    public void gimp(BufferedImage image) {
+        ShadowFilter sFilter = new ShadowFilter();
+        sFilter.setRadius(_radius);
+        sFilter.setOpacity(_opacity);
+        
+        BufferedImage buffer = sFilter.filter(image, null);
+        applyFilter(buffer, null);
+    }
+}
\ No newline at end of file

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/FishEyeGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/FishEyeGimpyRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/FishEyeGimpyRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,107 @@
+package nl.captcha.gimpy;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Overlays a warped grid to the image.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class FishEyeGimpyRenderer implements GimpyRenderer {
+	private final Color _hColor;
+	private final Color _vColor;
+	
+	public FishEyeGimpyRenderer() {
+		this(Color.BLACK, Color.BLACK);
+	}
+	
+	public FishEyeGimpyRenderer(Color hColor, Color vColor) {
+		_hColor = hColor;
+		_vColor = vColor;
+	}
+
+    public void gimp(BufferedImage image) {
+        int height = image.getHeight();
+        int width = image.getWidth();
+
+        int hstripes = height / 7;
+        int vstripes = width / 7;
+
+        // Calculate space between lines
+        int hspace = height / (hstripes + 1);
+        int vspace = width / (vstripes + 1);
+
+        Graphics2D graph = (Graphics2D) image.getGraphics();
+        // Draw the horizontal stripes
+        for (int i = hspace; i < height; i = i + hspace) {
+            graph.setColor(_hColor);
+            graph.drawLine(0, i, width, i);
+        }
+
+        // Draw the vertical stripes
+        for (int i = vspace; i < width; i = i + vspace) {
+            graph.setColor(_vColor);
+            graph.drawLine(i, 0, i, height);
+        }
+
+        // Create a pixel array of the original image.
+        // we need this later to do the operations on..
+        int pix[] = new int[height * width];
+        int j = 0;
+
+        for (int j1 = 0; j1 < width; j1++) {
+            for (int k1 = 0; k1 < height; k1++) {
+                pix[j] = image.getRGB(j1, k1);
+                j++;
+            }
+        }
+
+        double distance = ranInt(width / 4, width / 3);
+
+        // put the distortion in the (dead) middle
+        int wMid = image.getWidth() / 2;
+        int hMid = image.getHeight() / 2;
+
+        // again iterate over all pixels..
+        for (int x = 0; x < image.getWidth(); x++) {
+            for (int y = 0; y < image.getHeight(); y++) {
+
+                int relX = x - wMid;
+                int relY = y - hMid;
+
+                double d1 = Math.sqrt(relX * relX + relY * relY);
+                if (d1 < distance) {
+
+                    int j2 = wMid
+                            + (int) (((fishEyeFormula(d1 / distance) * distance) / d1) * (x - wMid));
+                    int k2 = hMid
+                            + (int) (((fishEyeFormula(d1 / distance) * distance) / d1) * (y - hMid));
+                    image.setRGB(x, y, pix[j2 * height + k2]);
+                }
+            }
+        }
+
+        graph.dispose();
+    }
+
+    private final int ranInt(int i, int j) {
+        double d = Math.random();
+        return (int) (i + ((j - i) + 1) * d);
+    }
+
+    private final double fishEyeFormula(double s) {
+        // implementation of:
+        // g(s) = - (3/4)s3 + (3/2)s2 + (1/4)s, with s from 0 to 1.
+        if (s < 0.0D) {
+            return 0.0D;
+        }
+        if (s > 1.0D) {
+            return s;
+        }
+
+        return -0.75D * s * s * s + 1.5D * s * s + 0.25D * s;
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/GimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/GimpyRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/GimpyRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,12 @@
+package nl.captcha.gimpy;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+
+public interface GimpyRenderer {
+    public void gimp(BufferedImage image);
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/RippleGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/RippleGimpyRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/RippleGimpyRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,33 @@
+package nl.captcha.gimpy;
+
+import java.awt.image.BufferedImage;
+
+import com.jhlabs.image.RippleFilter;
+import com.jhlabs.image.TransformFilter;
+
+import static nl.captcha.util.ImageUtil.applyFilter;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ */
+public class RippleGimpyRenderer implements GimpyRenderer {
+
+    /**
+     * Apply a RippleFilter to the image.
+     * 
+     * @param image The image to be distorted
+     */
+    public void gimp(BufferedImage image) {
+        RippleFilter filter = new RippleFilter();
+        filter.setWaveType(RippleFilter.SINE);
+        filter.setXAmplitude(2.6f);
+        filter.setYAmplitude(1.7f);
+        filter.setXWavelength(15);
+        filter.setYWavelength(5);
+        
+        filter.setEdgeAction(TransformFilter.BILINEAR);
+
+        BufferedImage buffer = filter.filter(image, null);
+        applyFilter(buffer, null);
+    }
+}
\ No newline at end of file

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/ShearGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/ShearGimpyRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/ShearGimpyRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,67 @@
+package nl.captcha.gimpy;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+import java.util.Random;
+
+public class ShearGimpyRenderer implements GimpyRenderer {
+
+    private final Random _gen = new SecureRandom();
+    private final Color _color;
+
+    public ShearGimpyRenderer() {
+        this(Color.GRAY);
+    }
+
+    public ShearGimpyRenderer(Color color) {
+        _color = color;
+    }
+
+    public void gimp(BufferedImage bi) {
+        Graphics2D g = bi.createGraphics();
+        shearX(g, bi.getWidth(), bi.getHeight());
+        shearY(g, bi.getWidth(), bi.getHeight());
+        g.dispose();
+    }
+
+    private void shearX(Graphics2D g, int w1, int h1) {
+        int period = _gen.nextInt(10) + 5;
+
+        boolean borderGap = true;
+        int frames = 15;
+        int phase = _gen.nextInt(5) + 2;
+
+        for (int i = 0; i < h1; i++) {
+            double d = (period >> 1)
+                    * Math.sin((double) i / (double) period
+                            + (6.2831853071795862D * phase) / frames);
+            g.copyArea(0, i, w1, 1, (int) d, 0);
+            if (borderGap) {
+                g.setColor(_color);
+                g.drawLine((int) d, i, 0, i);
+                g.drawLine((int) d + w1, i, w1, i);
+            }
+        }
+    }
+
+    private void shearY(Graphics2D g, int w1, int h1) {
+        int period = _gen.nextInt(30) + 10; // 50;
+
+        boolean borderGap = true;
+        int frames = 15;
+        int phase = 7;
+        for (int i = 0; i < w1; i++) {
+            double d = (period >> 1)
+                    * Math.sin((float) i / period
+                            + (6.2831853071795862D * phase) / frames);
+            g.copyArea(i, 0, 1, h1, 0, (int) d);
+            if (borderGap) {
+                g.setColor(_color);
+                g.drawLine(i, (int) d, i, 0);
+                g.drawLine(i, (int) d + h1, i, h1);
+            }
+        }
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/CurvedLineNoiseProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/CurvedLineNoiseProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/CurvedLineNoiseProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,87 @@
+package nl.captcha.noise;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * Adds a randomly curved line to the image.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class CurvedLineNoiseProducer implements NoiseProducer {
+
+    private static final Random RAND = new SecureRandom();
+
+    private final Color _color;
+    private final float _width;
+
+    public CurvedLineNoiseProducer() {
+        this(Color.BLACK, 3.0f);
+    }
+
+    public CurvedLineNoiseProducer(Color color, float width) {
+        _color = color;
+        _width = width;
+    }
+
+    public void makeNoise(BufferedImage image) {
+        int width = image.getWidth();
+        int height = image.getHeight();
+
+        // the curve from where the points are taken
+        CubicCurve2D cc = new CubicCurve2D.Float(width * .1f, height
+                * RAND.nextFloat(), width * .1f, height
+                * RAND.nextFloat(), width * .25f, height
+                * RAND.nextFloat(), width * .9f, height
+                * RAND.nextFloat());
+
+        // creates an iterator to define the boundary of the flattened curve
+        PathIterator pi = cc.getPathIterator(null, 2);
+        Point2D tmp[] = new Point2D[200];
+        int i = 0;
+
+        // while pi is iterating the curve, adds points to tmp array
+        while (!pi.isDone()) {
+            float[] coords = new float[6];
+            switch (pi.currentSegment(coords)) {
+            case PathIterator.SEG_MOVETO:
+            case PathIterator.SEG_LINETO:
+                tmp[i] = new Point2D.Float(coords[0], coords[1]);
+            }
+            i++;
+            pi.next();
+        }
+
+        // the points where the line changes the stroke and direction
+        Point2D[] pts = new Point2D[i];
+        // copies points from tmp to pts
+        System.arraycopy(tmp, 0, pts, 0, i);
+
+        Graphics2D graph = (Graphics2D) image.getGraphics();
+        graph.setRenderingHints(new RenderingHints(
+                RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON));
+
+        graph.setColor(_color);
+
+        // for the maximum 3 point change the stroke and direction
+        for (i = 0; i < pts.length - 1; i++) {
+            if (i < 3) {
+            	graph.setStroke(new BasicStroke(_width));
+            }
+            graph.drawLine((int) pts[i].getX(), (int) pts[i].getY(),
+                    (int) pts[i + 1].getX(), (int) pts[i + 1].getY());
+        }
+
+        graph.dispose();
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/NoiseProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/NoiseProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/NoiseProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,11 @@
+package nl.captcha.noise;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public interface NoiseProducer {
+    public void makeNoise(BufferedImage image);
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/StraightLineNoiseProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/StraightLineNoiseProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/StraightLineNoiseProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,78 @@
+package nl.captcha.noise;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+
+/**
+ * Draws a 4-pixel thick straight red line through the given image.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class StraightLineNoiseProducer implements NoiseProducer {
+
+    private final Color _color;
+    private final int _thickness;
+    private final SecureRandom _gen = new SecureRandom();
+
+    /**
+     * Default constructor creates a 4-pixel wide red line.
+     */
+    public StraightLineNoiseProducer() {
+        this(Color.RED, 4);
+    }
+
+    public StraightLineNoiseProducer(Color color, int thickness) {
+        _color = color;
+        _thickness = thickness;
+    }
+
+    public void makeNoise(BufferedImage image) {
+        Graphics2D graphics = image.createGraphics();
+        int height = image.getHeight();
+        int width = image.getWidth();
+        int y1 = _gen.nextInt(height) + 1;
+        int y2 = _gen.nextInt(height) + 1;
+        drawLine(graphics, y1, width, y2);
+    }
+
+    private void drawLine(Graphics g, int y1, int x2, int y2) {
+        int X1 = 0;
+
+        // The thick line is in fact a filled polygon
+        g.setColor(_color);
+        int dX = x2 - X1;
+        int dY = y2 - y1;
+        // line length
+        double lineLength = Math.sqrt(dX * dX + dY * dY);
+
+        double scale = _thickness / (2 * lineLength);
+
+        // The x and y increments from an endpoint needed to create a
+        // rectangle...
+        double ddx = -scale * dY;
+        double ddy = scale * dX;
+        ddx += (ddx > 0) ? 0.5 : -0.5;
+        ddy += (ddy > 0) ? 0.5 : -0.5;
+        int dx = (int) ddx;
+        int dy = (int) ddy;
+
+        // Now we can compute the corner points...
+        int xPoints[] = new int[4];
+        int yPoints[] = new int[4];
+
+        xPoints[0] = X1 + dx;
+        yPoints[0] = y1 + dy;
+        xPoints[1] = X1 - dx;
+        yPoints[1] = y1 - dy;
+        xPoints[2] = x2 - dx;
+        yPoints[2] = y2 - dy;
+        xPoints[3] = x2 + dx;
+        yPoints[3] = y2 + dy;
+
+        g.fillPolygon(xPoints, yPoints, 4);
+    }
+}
\ No newline at end of file

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,30 @@
+package nl.captcha.servlet;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletResponse;
+
+public final class CaptchaServletUtil {
+
+    public static void writeImage(HttpServletResponse response, BufferedImage bi) {
+        response.setHeader("Cache-Control", "private,no-cache,no-store");
+        response.setContentType("image/png");	// PNGs allow for transparency. JPGs do not.
+        try {
+            writeImage(response.getOutputStream(), bi);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void writeImage(OutputStream os, BufferedImage bi) {
+    	try {
+			ImageIO.write(bi, "png", os);
+			os.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/ChineseCaptchaServlet.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/ChineseCaptchaServlet.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/ChineseCaptchaServlet.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,49 @@
+package nl.captcha.servlet;
+
+import static nl.captcha.Captcha.NAME;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import nl.captcha.Captcha;
+import nl.captcha.backgrounds.GradiatedBackgroundProducer;
+import nl.captcha.text.producer.ChineseTextProducer;
+
+/**
+ * Generate a CAPTCHA image/answer pair using Chinese characters.
+ * 
+ * @author <a href="james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class ChineseCaptchaServlet extends SimpleCaptchaServlet {
+
+	private static final long serialVersionUID = -66324012009340831L;
+
+	@Override
+    public void doGet(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, IOException {
+        HttpSession session = req.getSession();
+        Captcha captcha;
+        if (session.getAttribute(NAME) == null) {
+	        captcha = new Captcha.Builder(_width, _height)
+	            	.addText(new ChineseTextProducer())
+	            	.gimp()
+	            	.addBorder()
+	                .addNoise()
+	                .addBackground(new GradiatedBackgroundProducer())
+	                .build();
+
+	        session.setAttribute(NAME, captcha);
+	        CaptchaServletUtil.writeImage(resp, captcha.getImage());
+	        
+	        return;
+        }
+
+        captcha = (Captcha) session.getAttribute(NAME);
+        CaptchaServletUtil.writeImage(resp, captcha.getImage());
+    }
+}
\ No newline at end of file

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/SimpleCaptchaServlet.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/SimpleCaptchaServlet.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/SimpleCaptchaServlet.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,58 @@
+package nl.captcha.servlet;
+
+import static nl.captcha.Captcha.NAME;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import nl.captcha.Captcha;
+import nl.captcha.backgrounds.GradiatedBackgroundProducer;
+
+
+/**
+ * Generates, displays, and stores in session a 200x50 CAPTCHA image with sheared black text, 
+ * a solid dark grey background, and a straight, slanted red line through the text.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ */
+public class SimpleCaptchaServlet extends HttpServlet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String PARAM_HEIGHT = "height";
+    private static final String PARAM_WIDTH = "width";
+
+    protected int _width = 200;
+    protected int _height = 50;
+
+    @Override
+    public void init() throws ServletException {
+    	if (getInitParameter(PARAM_HEIGHT) != null) {
+    		_height = Integer.valueOf(getInitParameter(PARAM_HEIGHT));
+    	}
+    	
+    	if (getInitParameter(PARAM_WIDTH) != null) {
+    		_width = Integer.valueOf(getInitParameter(PARAM_WIDTH));
+    	}
+    }
+    
+    @Override
+    public void doGet(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, IOException {
+
+        Captcha captcha = new Captcha.Builder(_width, _height)
+        	.addText()
+        	.addBackground(new GradiatedBackgroundProducer())
+            .gimp()
+            .addNoise()
+            .addBorder()
+            .build();
+
+        CaptchaServletUtil.writeImage(resp, captcha.getImage());
+        req.getSession().setAttribute(NAME, captcha);
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/StickyCaptchaServlet.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/StickyCaptchaServlet.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/StickyCaptchaServlet.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,74 @@
+package nl.captcha.servlet;
+
+import static nl.captcha.Captcha.NAME;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import nl.captcha.Captcha;
+
+
+/**
+ * Builds a 200x50 (default) CAPTCHA and attaches it to the session. This is intended to help prevent
+ * bots from simply reloading the page and getting new images until one is
+ * generated which they can successfully parse. Removal of the session attribute
+ * <code>CaptchaServletUtil.NAME</code> will force a new <code>Captcha</code>
+ * to be added to the session.
+ * 
+ * <p>Image height and width may be customized by adding the "heigh" and "width" init-params to
+ * web.xml. For example:</p>
+ * <p><pre>    &lt;servlet&gt;        
+  	&lt;servlet-name&gt;StickyCaptcha&lt;/servlet-name&gt;
+        &lt;servlet-class&gt;nl.captcha.servlet.StickyCaptchaServlet&lt;/servlet-class&gt;
+        &lt;init-param&gt;
+            &lt;param-name&gt;width&lt;/param-name&gt;
+            &lt;param-value&gt;250&lt;/param-value&gt;
+        &lt;/init-param&gt;
+        &lt;init-param&gt;
+            &lt;param-name&gt;height&lt;/param-name&gt;
+            &lt;param-value&gt;75&lt;/param-value&gt;
+        &lt;/init-param&gt;
+    &lt;/servlet&gt;
+</pre></p>
+
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class StickyCaptchaServlet extends SimpleCaptchaServlet {
+
+    private static final long serialVersionUID = 40913456229L;
+    
+    /**
+     * Write out the CAPTCHA image stored in the session. If not present,
+     * generate a new <code>Captcha</code> and write out its image.
+     * 
+     */
+    @Override
+    public void doGet(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, IOException {
+        HttpSession session = req.getSession();
+        Captcha captcha;
+        if (session.getAttribute(NAME) == null) {
+            captcha = new Captcha.Builder(_width, _height)
+            	.addText()
+            	.gimp()
+            	.addBorder()
+                .addNoise()
+                .addBackground()
+                .build();
+
+            session.setAttribute(NAME, captcha);
+            CaptchaServletUtil.writeImage(resp, captcha.getImage());
+
+            return;
+        }
+
+        captcha = (Captcha) session.getAttribute(NAME);
+        CaptchaServletUtil.writeImage(resp, captcha.getImage());
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,43 @@
+package nl.captcha.text.producer;
+
+/**
+ * TextProducer implementation that will return Chinese characters.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class ChineseTextProducer implements TextProducer {
+    
+	static final int DEFAULT_LENGTH = 5;    
+    // Here's hoping none of the characters in this range are offensive.
+    static final int CODE_POINT_START = 0x4E00;
+    static final int CODE_POINT_END = 0x4F6F;
+    private static final int NUM_CHARS = CODE_POINT_END - CODE_POINT_START;
+
+    private final TextProducer _txtProd;	// Decorator
+    
+    /**
+     * The default constructor will generate five Chinese characters.
+     * 
+     */
+    public ChineseTextProducer() {
+    	this(DEFAULT_LENGTH);
+    }
+    
+    /**
+     * Generate <code>length</code> number of Chinese characters.
+     * 
+     * @param length
+     */
+    public ChineseTextProducer(int length) {
+    	char[] chars = new char[NUM_CHARS];
+    	for (char c = CODE_POINT_START, i = 0; c < CODE_POINT_END; c++, i++) {
+    		chars[i] = Character.valueOf(c);
+    	}
+    	_txtProd = new DefaultTextProducer(length, chars);
+    }
+
+    public String getText() {
+    	return _txtProd.getText();
+    }
+}


Property changes on: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java
___________________________________________________________________
Name: svn:executable
   + *

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/DefaultTextProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/DefaultTextProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/DefaultTextProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,57 @@
+package nl.captcha.text.producer;
+
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Produces text of a given length from a given array of characters. The default (no-args)
+ * constructor produces five Latin characters from a specific set of alphanumerics. Characters
+ * such as "1" (one) and "l" (lower-case 'ell') have been removed to reduce ambiguity in the
+ * generated CAPTCHA.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class DefaultTextProducer implements TextProducer {
+
+    private static final Random _gen = new SecureRandom();
+    private static final int DEFAULT_LENGTH = 5;
+    private static final char[] DEFAULT_CHARS = new char[] { 'a', 'b', 'c', 'd',
+            'e', 'f', 'g', 'h', 'k', 'm', 'n', 'p', 'r', 'w', 'x', 'y',
+            '2', '3', '4', '5', '6', '7', '8', };
+    
+    private final int _length;
+    private final char[] _srcChars;
+
+    public DefaultTextProducer() {
+    	this(DEFAULT_LENGTH, DEFAULT_CHARS);
+    }
+    
+    public DefaultTextProducer(int length) {
+    	this(length, DEFAULT_CHARS);
+    }
+    
+    public DefaultTextProducer(int length, char[] srcChars) {
+    	_length = length;
+    	_srcChars = srcChars != null ? copyOf(srcChars, srcChars.length) : DEFAULT_CHARS;
+    }
+    
+    public String getText() {
+        int car = _srcChars.length - 1;
+
+        String capText = "";
+        for (int i = 0; i < _length; i++) {
+            capText += _srcChars[_gen.nextInt(car) + 1];
+        }
+
+        return capText;
+    }
+    
+    public static char[] copyOf(char[] original, int newLength) {
+        char[] copy = new char[newLength];
+        System.arraycopy(original, 0, copy, 0,
+                         Math.min(original.length, newLength));
+        return copy;
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/FiveLetterFirstNameTextProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/FiveLetterFirstNameTextProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/FiveLetterFirstNameTextProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,1054 @@
+package nl.captcha.text.producer;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public class FiveLetterFirstNameTextProducer implements TextProducer {
+
+    private static final Random GENERATOR = new SecureRandom();
+    private static final String[] FIRST_NAMES = new String[] { "jomah",
+            "yanae", "dagna", "aadel", "aaden", "aafia", "aamir", "aaran",
+            "aaren", "aaric", "aarin", "aarle", "aaron", "aarti", "aaryn",
+            "aasia", "aasif", "aasim", "abame", "abani", "abasi", "abbah",
+            "abban", "abbia", "abbie", "abbud", "abbye", "abdel", "abdou",
+            "abdul", "abdur", "abdus", "abebe", "abebi", "abeer", "abeli",
+            "abena", "abeni", "abhay", "abias", "abida", "abiel", "abija",
+            "abina", "abira", "abnar", "abner", "abnor", "aboor", "abott",
+            "abram", "abran", "abree", "abril", "abuid", "aceng", "achal",
+            "achaz", "achim", "achin", "acima", "ackim", "acree", "adala",
+            "adali", "adaly", "adama", "adamo", "adamu", "adara", "addal",
+            "addam", "addar", "addey", "addia", "addie", "addis", "adeen",
+            "adela", "adele", "adell", "adena", "adene", "adham", "adiah",
+            "adiba", "adiel", "adika", "adila", "adima", "adina", "adine",
+            "adira", "aditi", "adiva", "adjoa", "adlai", "adlan", "adlar",
+            "adler", "adley", "adlin", "adlyn", "admad", "admir", "admon",
+            "adnah", "adnan", "adnet", "adney", "adnot", "adola", "adolf",
+            "adoum", "adrea", "adrie", "adrik", "adron", "aemon", "aeric",
+            "aerin", "aesha", "afemo", "afeni", "affan", "affra", "afida",
+            "afsar", "aftan", "aftyn", "agace", "agafi", "agapi", "agata",
+            "aggye", "aghar", "aghna", "agias", "agnar", "agota", "agote",
+            "agoti", "agron", "ahanu", "ahava", "ahdaf", "ahern", "ahiva",
+            "ahlam", "ahley", "ahmad", "ahman", "ahmed", "ahmet", "ahran",
+            "ahren", "ahrin", "ahsan", "ahuda", "ahuva", "ahvie", "aidah",
+            "aidan", "aiden", "aidya", "aiken", "aikin", "ailee", "ailey",
+            "ailie", "ailin", "ailis", "ailli", "ailsa", "ailse", "aimal",
+            "aimee", "aimey", "aimia", "aimie", "aimil", "aimon", "ainah",
+            "ainka", "ainur", "airat", "airel", "airic", "airle", "aisha",
+            "aisia", "aitan", "aitor", "aizik", "ajaib", "ajali", "ajani",
+            "ajaya", "ajeya", "ajhon", "ajith", "ajmal", "ajsha", "akako",
+            "akara", "akash", "akati", "akbar", "akeam", "akeel", "akeem",
+            "akemi", "akhil", "akiba", "akiel", "akiem", "akiko", "akila",
+            "akili", "akima", "akins", "akira", "akiva", "akiyo", "akmal",
+            "akono", "akram", "aksel", "alade", "alaen", "alaia", "alain",
+            "alair", "alaka", "alana", "alani", "alann", "alano", "alard",
+            "alayn", "alban", "alben", "alber", "albie", "albis", "alcot",
+            "aldas", "aldea", "alden", "aldie", "aldin", "aldis", "aldon",
+            "aldus", "aldya", "aleah", "aleco", "aleda", "aleea", "aleen",
+            "aleia", "aleix", "alejo", "aleka", "aleki", "aleks", "alena",
+            "alene", "aleni", "aleta", "alexa", "alexi", "alexx", "alexy",
+            "aleya", "alfeo", "alfie", "alfio", "alfre", "alfri", "algar",
+            "algey", "algie", "algis", "algon", "alica", "alice", "alick",
+            "alida", "alies", "alija", "alika", "alina", "alisa", "alise",
+            "alisz", "alita", "alixe", "aliye", "aliza", "alize", "alkis",
+            "alkot", "allam", "allan", "allax", "allda", "allea", "allen",
+            "alles", "allex", "allfy", "allie", "allin", "allix", "allma",
+            "allon", "allta", "allyn", "allys", "almaz", "almil", "almir",
+            "alois", "alojz", "aloke", "alona", "aloni", "aloys", "alphy",
+            "alpin", "alred", "alric", "alrik", "alroy", "altaf", "alten",
+            "aluin", "aluki", "aluna", "alura", "aluse", "alvah", "alvan",
+            "alven", "alves", "alvie", "alvin", "alvis", "alvyn", "alvys",
+            "alwan", "alwin", "alwyn", "alyce", "alyda", "alyma", "alyna",
+            "alyne", "alynn", "alysa", "alyse", "alyso", "alyss", "amada",
+            "amado", "amadu", "amahd", "amahl", "amaka", "amaly", "amare",
+            "amary", "amasa", "amata", "amato", "amaui", "amaya", "ambie",
+            "ambra", "ambur", "amela", "amena", "amery", "amiah", "amica",
+            "amiel", "amiet", "amijo", "amiko", "amina", "amira", "amirh",
+            "amiri", "amisa", "amita", "amjad", "ammar", "ammer", "ammie",
+            "amneh", "amnon", "amona", "amory", "amrit", "amyas", "amyot",
+            "amyra", "amzie", "anais", "anaka", "anand", "anant", "ancel",
+            "andee", "ander", "andie", "andis", "andje", "andon", "andor",
+            "andra", "andre", "andri", "andru", "andry", "aneel", "aneka",
+            "anela", "aneta", "anete", "anett", "aneva", "angee", "angen",
+            "angey", "angie", "angil", "aniah", "anica", "anice", "anida",
+            "aniel", "anier", "anika", "aniko", "anina", "anisa", "anita",
+            "aniya", "anjel", "anjil", "ankie", "annee", "annes", "anney",
+            "annia", "annie", "annik", "annis", "annot", "annus", "annys",
+            "annza", "anoki", "anoop", "anora", "anouk", "anour", "ansam",
+            "ansel", "ansly", "anson", "ansor", "anssi", "ansun", "antaw",
+            "antha", "anthe", "antia", "antin", "antje", "anton", "antos",
+            "antti", "anuja", "anwar", "anwel", "anwen", "anwil", "anwyl",
+            "anwyn", "anyes", "aoife", "aphra", "apolo", "aponi", "apryl",
+            "aquil", "aralt", "arash", "arata", "arati", "arbel", "arben",
+            "archy", "ardah", "ardal", "ardia", "ardie", "ardin", "ardis",
+            "ardly", "ardon", "ardra", "ardys", "areck", "areen", "arela",
+            "areli", "arese", "areta", "argeo", "arial", "arick", "arics",
+            "arieh", "arien", "ariez", "arija", "arika", "arild", "arina",
+            "arinn", "arisa", "ariya", "ariza", "arize", "arjen", "arkan",
+            "arkin", "arkyn", "arlan", "arlea", "arlee", "arlen", "arlet",
+            "arley", "arlie", "arlin", "arlis", "arlyn", "armad", "arman",
+            "armin", "armon", "arnat", "arndt", "arnel", "arnet", "arney",
+            "arnie", "arnis", "arnny", "arnoe", "arnon", "arnou", "aroni",
+            "arren", "arria", "arric", "arrik", "arrio", "arron", "arryo",
+            "arsen", "artek", "artha", "arthi", "artie", "artin", "artis",
+            "artor", "artur", "artus", "aruna", "aruns", "arvah", "arvid",
+            "arvie", "arvon", "arwel", "arwen", "arwin", "arwyn", "aryeh",
+            "aryel", "asaad", "asafa", "asano", "asaph", "aseel", "ashah",
+            "ashar", "ashby", "ashia", "ashis", "ashla", "ashli", "ashly",
+            "ashon", "ashor", "asiah", "asiak", "asier", "asifa", "asiff",
+            "asima", "asiri", "asish", "asius", "aslak", "aslan", "aslin",
+            "asmaa", "asmus", "asoke", "asoma", "aspar", "asril", "asror",
+            "assad", "assaf", "assem", "assia", "assie", "asten", "astin",
+            "astra", "astri", "aswin", "aswyn", "atala", "atara", "atera",
+            "athan", "athie", "athol", "athra", "atida", "atifa", "atila",
+            "atima", "atina", "atiya", "atlea", "atley", "atner", "atrie",
+            "attie", "atyaf", "auban", "auben", "aubra", "aubre", "aubri",
+            "aubry", "audon", "audra", "audre", "audri", "audry", "audun",
+            "audun", "auggy", "augie", "aukai", "aulii", "aurea", "aurek",
+            "aurel", "aurey", "auria", "aurie", "ausaf", "ausra", "autry",
+            "autum", "auvit", "avada", "avais", "avari", "avary", "aveen",
+            "avent", "avern", "avery", "avice", "aviel", "aviva", "avivi",
+            "aviya", "avner", "avnit", "avram", "avrel", "avril", "avrim",
+            "avrit", "avrom", "avrum", "avtar", "awani", "axell", "axill",
+            "axton", "ayaan", "ayaaz", "ayako", "ayala", "ayame", "ayana",
+            "aydan", "ayden", "ayers", "ayham", "ayhan", "ayisa", "ayken",
+            "aykin", "aylee", "aylie", "aymen", "aymer", "aymil", "aymon",
+            "aynor", "ayoka", "ayrel", "ayres", "aysel", "aysha", "ayshe",
+            "aysia", "ayson", "aytac", "aytza", "ayubu", "ayumi", "ayzan",
+            "azael", "azami", "azaya", "azhar", "azibo", "azita", "aziza",
+            "azize", "azizi", "azmat", "azora", "azuba", "azura", "azwar",
+            "azzam", "babak", "babek", "babet", "babsy", "badal", "badih",
+            "badja", "badra", "badri", "bagot", "bahaa", "baher", "bahni",
+            "bahri", "baila", "baily", "baird", "bakri", "balak", "balal",
+            "balin", "bamby", "bandi", "banky", "bantz", "baqir", "barba",
+            "barbi", "barby", "barie", "barna", "barri", "barrt", "barta",
+            "barto", "bartt", "barty", "bartz", "barun", "baryn", "basak",
+            "basam", "basem", "basia", "basir", "basma", "basob", "basya",
+            "batia", "batya", "bauby", "baxie", "baxty", "bayly", "bayne",
+            "bayrd", "bazek", "bazel", "bazil", "beale", "beall", "beals",
+            "beann", "beate", "beaty", "beavo", "bebba", "bebel", "becca",
+            "becka", "becki", "becky", "bejun", "bekka", "bekki", "belal",
+            "belia", "bella", "bello", "belva", "beman", "benay", "benci",
+            "benek", "bengt", "benio", "benja", "benji", "benke", "benna",
+            "benno", "bennt", "benon", "bente", "bentz", "benyu", "benzi",
+            "beppe", "beppo", "berdj", "berdy", "beren", "bergh", "beril",
+            "berit", "berje", "berke", "berky", "berla", "berly", "berna",
+            "bernd", "berni", "berno", "bernt", "berny", "berte", "berti",
+            "berto", "berty", "besse", "bessi", "bessy", "betha", "bethe",
+            "betia", "betka", "betsi", "betsy", "bette", "betti", "betto",
+            "betul", "beula", "bevan", "beven", "bevin", "bevis", "bevon",
+            "bevys", "beyla", "beyle", "bheki", "biago", "biala", "biana",
+            "bibha", "bijan", "bikas", "bilal", "bilee", "billa", "bille",
+            "billi", "bimia", "bimla", "binah", "bindo", "bindu", "bingu",
+            "binky", "binni", "binod", "binta", "birdi", "biren", "birge",
+            "birky", "birly", "birny", "birol", "biron", "birte", "birty",
+            "biswa", "bitta", "bitya", "bjorn", "blaed", "blasi", "blayr",
+            "blaza", "bleda", "bledi", "blima", "blime", "blixa", "bluma",
+            "blyss", "boase", "bobbe", "bobbi", "bobek", "bobie", "bodan",
+            "bodee", "bodey", "bodie", "bodil", "bodin", "bogna", "boice",
+            "bojan", "bonar", "bondy", "bonie", "bonka", "bonni", "boona",
+            "boony", "boote", "bordy", "boris", "borja", "borka", "borya",
+            "borys", "boski", "botan", "bowen", "boxin", "boyce", "bozze",
+            "bradd", "brade", "brady", "brahm", "bramm", "brana", "brani",
+            "brann", "braun", "breah", "brear", "breay", "bredo", "breea",
+            "brena", "brenn", "breno", "breon", "breza", "briah", "brian",
+            "brice", "bridd", "bridi", "bridy", "brien", "briet", "brina",
+            "brinn", "brion", "brisa", "brita", "brodi", "brona", "broox",
+            "bruce", "brucy", "bruis", "bruna", "bruno", "bruns", "bryan",
+            "bryar", "bryce", "bryen", "bryga", "bryna", "brynn", "bryon",
+            "bubsy", "buchi", "bucky", "budde", "buell", "buena", "bugsy",
+            "bunky", "bunni", "burak", "burch", "burne", "burrt", "burtt",
+            "burty", "busse", "buzby", "byram", "byran", "byrdy", "byren",
+            "byrie", "byrle", "byrne", "byrom", "byron", "cacey", "cachi",
+            "cacia", "cacie", "cadao", "cadby", "cadel", "caden", "cadye",
+            "caeli", "cahan", "cahil", "cahit", "caily", "caira", "caisi",
+            "caity", "caius", "calab", "calah", "calan", "calee", "calem",
+            "caley", "calia", "calie", "calli", "cally", "calum", "calym",
+            "calyn", "camar", "camey", "camia", "cammi", "canda", "candi",
+            "cappi", "capys", "carah", "caree", "carel", "caren", "carew",
+            "carie", "caril", "carin", "caris", "carla", "carli", "carlo",
+            "carly", "carma", "carmi", "carmy", "carna", "carra", "carri",
+            "caryl", "caryn", "carys", "casar", "casca", "cascy", "casee",
+            "cashe", "cashi", "casia", "casie", "cassi", "casta", "catey",
+            "cathe", "cathi", "cathy", "catia", "catie", "cavas", "caven",
+            "cayce", "cayci", "cayla", "cayli", "cayly", "cayse", "caysi",
+            "cayte", "cazzi", "ceadd", "cecil", "cecyl", "ceila", "cejay",
+            "celes", "celia", "celie", "celio", "celka", "celly", "celso",
+            "cemal", "cenex", "cerea", "cerek", "cerel", "ceril", "cerys",
+            "cesar", "cesha", "cesia", "cesso", "cesur", "cesya", "cetta",
+            "cevan", "cezar", "chaad", "chadd", "chade", "chady", "chago",
+            "chaim", "chaka", "chamy", "chana", "chanc", "chand", "chane",
+            "chani", "chann", "charl", "charo", "charu", "chass", "chava",
+            "chavi", "chavo", "chayo", "chazz", "cheli", "chelo", "chene",
+            "chere", "chery", "chesa", "chevi", "cheyn", "chido", "chika",
+            "chike", "chiko", "chiku", "chilo", "chilt", "chimo", "chiyo",
+            "chloe", "chofa", "chona", "choni", "chope", "chris", "chrys",
+            "chuan", "chuki", "chuma", "chumo", "chung", "chyld", "chyna",
+            "ciana", "ciara", "cicek", "cidne", "cielo", "ciera", "cijay",
+            "cilka", "cilla", "cille", "cilly", "cinda", "cindi", "cindy",
+            "cinny", "cione", "ciril", "cirse", "ciske", "cissi", "clail",
+            "clair", "clari", "claud", "clell", "cleme", "clerc", "cleta",
+            "clete", "cleva", "clive", "cloda", "cloey", "clyff", "clyph",
+            "clyve", "clywd", "cnute", "coady", "cobey", "cobie", "coday",
+            "codee", "codey", "codie", "coedy", "cofer", "colan", "colbi",
+            "colen", "colis", "colum", "colyn", "conan", "condi", "conni",
+            "conny", "conon", "conor", "conry", "conso", "cooke", "coran",
+            "corbi", "cordi", "coren", "corey", "corie", "corin", "corio",
+            "corly", "corra", "corri", "corry", "corty", "coryn", "cosma",
+            "cosme", "cosmo", "cotey", "cowey", "cowie", "coyne", "cozmo",
+            "creag", "cregg", "creig", "criag", "crina", "crish", "crito",
+            "croix", "csaba", "csuba", "curan", "cyann", "cybel", "cybil",
+            "cydne", "cylin", "cynan", "cynda", "cynde", "cyndi", "cyndy",
+            "cynie", "cynth", "cyrah", "cyrel", "cyril", "cyris", "cyros",
+            "dabbs", "dabir", "dacee", "dacey", "dache", "dacie", "dacio",
+            "dacso", "dadie", "daffi", "dafna", "dafne", "dafny", "dagen",
+            "dagne", "dagny", "dahir", "dahud", "dahut", "daicy", "daija",
+            "daile", "daimi", "daina", "daine", "daire", "daisi", "dajan",
+            "dakim", "dakin", "dalal", "dalen", "daley", "dalia", "dalil",
+            "dalin", "dalma", "dalva", "dalya", "dalyn", "dalys", "damba",
+            "damee", "damek", "damen", "damia", "damie", "damir", "damya",
+            "danah", "danai", "danal", "danay", "danea", "danee", "danek",
+            "danel", "danen", "danet", "daney", "danfy", "dania", "danie",
+            "danis", "danit", "daniz", "danja", "danka", "danne", "danni",
+            "danno", "danny", "danon", "dante", "danya", "danyl", "danys",
+            "danzy", "daoud", "darab", "darah", "daran", "daray", "darbi",
+            "darce", "darci", "darda", "dareh", "darek", "daren", "daria",
+            "darik", "daril", "darin", "dario", "darja", "darko", "darla",
+            "darli", "darly", "daron", "darry", "darse", "darsi", "darsy",
+            "darun", "darva", "darya", "daryl", "daryn", "dasan", "dasco",
+            "dasey", "dasha", "dashi", "dasie", "datha", "datus", "daudi",
+            "dauid", "dause", "daved", "davee", "davey", "david", "davie",
+            "davin", "davis", "davon", "davor", "dawan", "dawid", "dawin",
+            "dawit", "dawne", "dawnn", "dawon", "dawud", "daycy", "dayle",
+            "dayma", "dayna", "dayne", "dayse", "daysi", "daysy", "deana",
+            "deane", "deann", "debbi", "debby", "debee", "debie", "debor",
+            "debre", "decca", "decha", "decia", "decka", "dedee", "dedie",
+            "dedra", "deeda", "deena", "deepa", "deept", "deeyn", "deion",
+            "dejah", "dejan", "dejon", "dekah", "dekel", "dekka", "delan",
+            "delea", "delia", "delie", "delle", "delli", "delma", "delon",
+            "deloy", "delra", "delsy", "delte", "delya", "delys", "deman",
+            "demas", "dembe", "demps", "denae", "denah", "denby", "denea",
+            "denee", "deney", "denie", "denis", "deniz", "denly", "denna",
+            "denni", "denny", "denya", "denys", "deona", "deone", "derak",
+            "deran", "derec", "derek", "deren", "derie", "derik", "deril",
+            "derin", "derit", "derke", "deron", "derth", "deryk", "deryl",
+            "deryn", "deshi", "desie", "desir", "dessi", "desta", "deste",
+            "desty", "detta", "deune", "devah", "deval", "devan", "deven",
+            "devin", "devoe", "devra", "devri", "devyn", "dewei", "dewie",
+            "dewon", "dexin", "deyda", "dezia", "dezra", "dhana", "dhane",
+            "dhani", "dhari", "dhary", "dheva", "diane", "diann", "dicko",
+            "didar", "didra", "diego", "dietz", "digby", "digna", "dikla",
+            "dilan", "dilip", "dilla", "dilon", "dilyn", "dilys", "dimas",
+            "dimon", "dimos", "dinah", "dinaz", "dinco", "dinis", "dinko",
+            "dinny", "dinse", "dinya", "diogo", "diona", "dioni", "dionn",
+            "diora", "diore", "diosa", "dipti", "dirce", "dirck", "dirke",
+            "diron", "ditta", "ditte", "diuan", "divam", "divya", "dixee",
+            "dixon", "djari", "djimi", "djuna", "djuro", "doane", "dobry",
+            "docie", "dodee", "dodek", "dodey", "dodie", "dodya", "doeda",
+            "dolan", "dolat", "dolen", "dolfe", "dolfi", "dolin", "dolli",
+            "dolph", "dolyn", "domek", "domka", "donal", "dondi", "donek",
+            "donia", "donni", "donny", "donta", "donya", "dorah", "dordi",
+            "dorie", "dorin", "dorit", "dorka", "dorle", "dorna", "dorne",
+            "dorri", "dorry", "dorte", "doryn", "dorys", "dosha", "dosia",
+            "dosta", "dosya", "dotan", "dotti", "dougy", "douta", "dovid",
+            "dowid", "doyal", "doyel", "doyin", "doyle", "doyne", "draga",
+            "draxy", "dreda", "drenk", "drewe", "dreya", "driss", "druan",
+            "druce", "druci", "drucy", "drugi", "drumi", "drusi", "drusy",
+            "duain", "duana", "duane", "dudly", "dugal", "dugan", "dugey",
+            "dulan", "dulci", "dulcy", "dulie", "dunja", "dunta", "duong",
+            "duran", "durel", "durko", "duron", "dusan", "dusav", "dusha",
+            "dusti", "duval", "duwan", "dvora", "dwain", "dwana", "dwane",
+            "dwaun", "dwawn", "dwora", "dyami", "dyana", "dyane", "dyani",
+            "dyann", "dyese", "dylan", "dylis", "dylon", "dylys", "dymas",
+            "dymek", "dynah", "dyolf", "dyron", "dysen", "dyske", "dyson",
+            "dyvon", "eaden", "eadie", "eadin", "eagan", "eagon", "eames",
+            "eamon", "eanid", "earla", "earld", "earle", "easha", "eason",
+            "eaton", "eavan", "ebany", "ebbie", "ebert", "ebner", "ebone",
+            "eboni", "edana", "eddee", "eddie", "eddna", "eddra", "eddye",
+            "edeet", "edena", "edene", "edgar", "edina", "edisa", "edita",
+            "edite", "edith", "ediva", "edlin", "edlyn", "edmar", "edmon",
+            "ednah", "edney", "edolf", "edrea", "edred", "edric", "edris",
+            "edrys", "edson", "edvig", "edwig", "edwin", "edwyn", "edyna",
+            "edyta", "edyth", "edzio", "eefje", "eefke", "effam", "effia",
+            "efram", "efrat", "efrem", "efren", "efrim", "efrum", "egann",
+            "egeus", "egide", "ehren", "ehsan", "ehsin", "eikki", "eiley",
+            "eilif", "eilis", "eilsa", "eilyn", "einar", "einat", "einav",
+            "eiren", "eirin", "eiryn", "eitan", "eival", "ejnar", "ekene",
+            "ekraj", "elama", "elana", "elane", "elani", "elann", "elasa",
+            "elata", "elayn", "elbio", "eldad", "eldar", "elden", "eldin",
+            "eldon", "eleen", "elene", "eleni", "eleny", "eleph", "eleri",
+            "elers", "elery", "elesa", "elese", "eleta", "elexa", "elfie",
+            "elfre", "elgan", "elgar", "elgen", "elger", "elham", "eliam",
+            "elias", "elice", "elida", "elidi", "eliel", "elier", "eliga",
+            "elihu", "elija", "elika", "elimu", "elina", "eline", "eliot",
+            "elise", "elish", "elita", "eliud", "eliut", "eliza", "elize",
+            "elkan", "elkin", "ellan", "ellee", "ellen", "elley", "ellia",
+            "ellie", "ellin", "ellis", "ellma", "ellsa", "ellse", "ellsi",
+            "ellsy", "ellyn", "elman", "elmar", "elmaz", "elmer", "elmir",
+            "elmyr", "eloda", "elodi", "elois", "elora", "elrad", "elric",
+            "elroi", "elroy", "elsee", "elsey", "elsha", "elshe", "elsie",
+            "elsje", "eltan", "eltha", "elvah", "elvia", "elvie", "elvin",
+            "elvio", "elvis", "elvyn", "elvys", "elwin", "elwyn", "elxis",
+            "elyas", "elyce", "elyci", "elyot", "elysa", "elyse", "elyza",
+            "elyze", "emaan", "emani", "emari", "emeka", "emeli", "emely",
+            "emera", "emeri", "emiko", "emila", "emile", "emili", "emill",
+            "emilo", "emils", "emily", "emina", "emine", "emira", "emitt",
+            "emlen", "emlin", "emlou", "emlyn", "emmey", "emmie", "emmit",
+            "emmot", "emmye", "emory", "emrah", "emryk", "emrys", "emyle",
+            "encke", "endre", "engie", "enidd", "ennea", "ennio", "enock",
+            "enoka", "enora", "enosh", "enria", "enric", "enver", "enydd",
+            "eocha", "ephan", "ephie", "eppia", "eppie", "epsey", "eraca",
+            "erast", "erdne", "ereck", "erena", "erene", "ereni", "erhan",
+            "erich", "erico", "eriel", "erika", "eriko", "eriks", "erina",
+            "erine", "erinn", "erino", "eriqa", "erkan", "erkki", "erlan",
+            "erlin", "ermis", "erney", "ernie", "ernst", "erold", "erric",
+            "errol", "erryl", "ersin", "ertha", "ervin", "ervyn", "erwan",
+            "erwin", "erwyn", "eryan", "eryka", "erynn", "esben", "esera",
+            "eskil", "esmat", "esmie", "espen", "esref", "essad", "essae",
+            "essam", "essan", "essey", "essie", "essom", "essop", "estee",
+            "estel", "estie", "eston", "eszti", "etain", "eteri", "etgar",
+            "ethan", "ethel", "ethem", "ethna", "ethne", "ethyn", "etina",
+            "etore", "ettey", "ettie", "etyen", "etzio", "eubie", "eudel",
+            "eudes", "euell", "eugen", "eulia", "evald", "evana", "evann",
+            "evany", "evard", "eveny", "evett", "evike", "evita", "evlin",
+            "evlyn", "evony", "evvie", "evyan", "ewald", "eward", "ewart",
+            "ewert", "ewing", "ewynn", "eydie", "eytan", "eyton", "ezeck",
+            "ezell", "ezera", "ezhno", "ezola", "ezrah", "ezvan", "ezzat",
+            "ezzie", "faada", "fabek", "fabia", "fabio", "fabra", "fabre",
+            "fadal", "fadel", "fadey", "fadil", "fadwa", "fahad", "faida",
+            "faiga", "faina", "faisl", "faiza", "fakih", "fakri", "falah",
+            "falan", "falau", "faleh", "falen", "falin", "falke", "falyn",
+            "famke", "fanci", "fania", "fanis", "fanni", "fanus", "fanya",
+            "farai", "faran", "faren", "farid", "farin", "fario", "fariq",
+            "faroh", "farok", "faron", "farqy", "farra", "faruk", "faruq",
+            "farye", "faryn", "fasil", "faten", "fathi", "fatih", "fatil",
+            "fatin", "fatma", "fatos", "fatur", "faune", "faure", "fawna",
+            "fawne", "fawzi", "fawzy", "faxon", "fayda", "fayez", "fayik",
+            "fayla", "fayme", "fayne", "fayth", "fazel", "fazil", "fedja",
+            "fedor", "fedya", "feena", "fekri", "felcy", "felda", "felia",
+            "felic", "felim", "felix", "feliz", "felka", "felyx", "femie",
+            "femmi", "feran", "feras", "ferda", "ferde", "ferdo", "ferdy",
+            "ferin", "ferne", "ferni", "feron", "feroz", "feste", "feyla",
+            "ffion", "fiach", "fiala", "fidel", "filia", "filma", "filya",
+            "finan", "finly", "finty", "fiona", "fionn", "fiora", "fiore",
+            "fioza", "firaq", "firas", "firat", "firuz", "fiske", "flana",
+            "flann", "fleda", "fleta", "flinn", "flody", "flois", "flori",
+            "floyd", "flynn", "flynt", "foard", "folke", "fonso", "fonta",
+            "fonya", "fonzo", "forbe", "forey", "forry", "fosca", "fosco",
+            "fouad", "frang", "franh", "frani", "frann", "frano", "frans",
+            "franz", "fraya", "frean", "freda", "fredd", "fredi", "fredo",
+            "fredy", "freek", "freen", "freja", "freny", "friba", "frici",
+            "frick", "frida", "frode", "froma", "fryda", "fuaad", "fujio",
+            "fulla", "fumio", "furio", "fyffe", "fyodr", "gabbe", "gabbi",
+            "gabie", "gabin", "gabko", "gabor", "gabri", "gabys", "gaddy",
+            "gaela", "gagan", "gahan", "gaiea", "gaila", "gaile", "gaill",
+            "gaius", "galan", "galia", "galib", "galin", "galit", "galya",
+            "galyn", "gamal", "gamid", "gamil", "ganit", "ganna", "ganya",
+            "gareb", "gared", "garek", "garen", "garet", "garey", "gargi",
+            "garie", "garik", "garri", "garvy", "garyn", "gasha", "gaute",
+            "gavan", "gaven", "gavin", "gavra", "gavri", "gavyn", "gawen",
+            "gayel", "gayil", "gayla", "gayle", "gayna", "gazit", "geane",
+            "geany", "gearr", "geber", "geela", "geena", "geert", "geeta",
+            "geina", "gelda", "gelya", "genah", "genay", "genea", "genek",
+            "genia", "genna", "genni", "geoff", "geona", "georg", "gerad",
+            "geran", "gerco", "gerda", "gerdi", "gerdy", "gerek", "gergo",
+            "gerik", "gerre", "gerri", "gerry", "gerta", "gerte", "gerti",
+            "gerty", "geula", "gevin", "ghada", "ghaib", "ghatu", "ghena",
+            "ghian", "ghino", "ghita", "ghlam", "giamo", "giana", "giann",
+            "gibbs", "gibor", "gidey", "gidon", "giesa", "giffy", "gifty",
+            "gigia", "gihan", "gilad", "gilah", "gilby", "gilda", "gilde",
+            "gildy", "gilen", "giles", "gilie", "gilli", "gillo", "gilon",
+            "ginia", "ginna", "ginni", "gints", "ginya", "giona", "giray",
+            "giric", "girod", "gitel", "githa", "gitle", "gitta", "gitte",
+            "giula", "giuma", "giusy", "gizat", "gjorg", "gleda", "glena",
+            "glenn", "gleny", "glori", "gojko", "golda", "goldi", "gonza",
+            "gordy", "gorje", "gorya", "gosia", "gough", "gower", "gowon",
+            "gozal", "graca", "graci", "gracy", "grady", "graef", "graem",
+            "graig", "grear", "greer", "gregg", "greig", "greil", "greta",
+            "gretl", "greye", "grier", "gries", "gryta", "guido", "guila",
+            "gulam", "gulay", "gunar", "gunay", "gunda", "guram", "gurit",
+            "gussi", "gusta", "gusti", "guyan", "guyon", "guyte", "gwayn",
+            "gwenn", "gwinn", "gwynn", "gyasi", "gylla", "gytha", "gyuri",
+            "habib", "hacib", "hadas", "haden", "hadia", "hadja", "hadly",
+            "hadon", "hadyn", "hafed", "hafid", "hafsa", "hagai", "hagan",
+            "hagit", "hagly", "hagop", "haiko", "haila", "haili", "hajar",
+            "hajim", "hajna", "hakan", "hakon", "halbe", "halen", "haley",
+            "halie", "halla", "halli", "hally", "halsy", "haluk", "halya",
+            "halye", "hamar", "hamdi", "hamel", "hamer", "hamet", "hamif",
+            "hamil", "hamin", "hamit", "hanaa", "hanae", "hanah", "hanan",
+            "hanef", "hanik", "hanim", "hanin", "hanja", "hanka", "hanly",
+            "hanna", "hanne", "hanni", "hannu", "hanny", "hansh", "hansl",
+            "hantz", "hanus", "haona", "harah", "harbi", "harel", "harin",
+            "harla", "harli", "harly", "haron", "harri", "harro", "harun",
+            "harve", "hasad", "hasan", "hasen", "hasib", "hasil", "hasin",
+            "hason", "hasse", "hasso", "hatem", "hatim", "hatsy", "hatti",
+            "hauke", "havah", "havin", "havis", "haviv", "hawes", "hawly",
+            "hayah", "hayam", "hayat", "hayde", "haydn", "hayfa", "hayim",
+            "hayli", "hayly", "hayne", "hayse", "hazal", "hazem", "hazim",
+            "hazra", "hazyl", "heall", "hearn", "hedda", "heddi", "heddy",
+            "hedia", "hedir", "hedly", "hedva", "heida", "heide", "heidi",
+            "heike", "heiko", "heimo", "heinz", "heith", "helah", "helen",
+            "helga", "helge", "helki", "helli", "helma", "helmi", "helmy",
+            "helon", "helsa", "helyn", "hendl", "henia", "henie", "henka",
+            "henni", "henny", "henri", "henya", "herin", "hermy", "hersh",
+            "hersz", "herta", "herva", "hervy", "herzl", "hesam", "heshu",
+            "hesky", "hesti", "hesty", "hetal", "hetta", "hetti", "hetty",
+            "heven", "hewet", "hewie", "hewit", "hiatt", "hibah", "hidee",
+            "hideo", "hieda", "hiede", "hilda", "hilde", "hildi", "hildo",
+            "hildy", "hilel", "hilia", "hilit", "hille", "hilma", "hilmi",
+            "himan", "hinda", "hindy", "hiner", "hinju", "hinke", "hinto",
+            "hinun", "hiram", "hirem", "hirji", "hirom", "hirov", "hirsh",
+            "hisao", "hitka", "hitty", "hivet", "hiwot", "hoang", "hobey",
+            "holda", "holde", "holic", "holic", "holle", "holli", "holub",
+            "homan", "honna", "honon", "honza", "hopey", "hopie", "horaz",
+            "hosea", "hoshi", "hosni", "hosny", "houda", "houry", "hovan",
+            "howey", "howie", "howin", "hrank", "hrolf", "huber", "hubey",
+            "hubie", "hughy", "hulda", "humam", "hunny", "huong", "huram",
+            "husam", "husnu", "huxly", "hyatt", "hyder", "hydie", "hylda",
+            "hyman", "hymie", "hynda", "hynee", "hyram", "hyrum", "hywel",
+            "iakob", "iakov", "ianna", "ianos", "ibbie", "ibram", "idaia",
+            "idaya", "idell", "idina", "idrys", "idwal", "iesha", "ifrah",
+            "ifraz", "iggie", "ignac", "ignaz", "ignes", "ihsan", "ikemi",
+            "ikkei", "iklas", "ikram", "ikuko", "ilana", "ilani", "ilean",
+            "ileen", "ilena", "ilene", "ilese", "ilham", "ilhan", "ilias",
+            "ilich", "ilida", "ilina", "iline", "ilisa", "ilise", "ilita",
+            "ilker", "ilkka", "illan", "illia", "illya", "ilona", "ilone",
+            "ilsey", "ilyas", "ilyaz", "ilyna", "ilysa", "ilyse", "imani",
+            "imany", "imena", "imran", "inaki", "inbal", "indya", "ineke",
+            "inela", "inell", "ingar", "inger", "iniga", "iniki", "iniko",
+            "innes", "innis", "ioana", "ioann", "iolee", "iolia", "ionel",
+            "ioney", "ionie", "ionut", "ioseb", "iosep", "iosif", "iosua",
+            "iouri", "iqbal", "iradj", "irana", "ireen", "irena", "irfan",
+            "irien", "irina", "irini", "irisa", "irita", "irona", "irven",
+            "irvin", "irwin", "irwyn", "iryna", "isaac", "isaak", "isack",
+            "isaia", "isaid", "isaih", "isais", "isamu", "isbel", "isela",
+            "iseut", "isham", "ishaq", "isiah", "isild", "isman", "ismar",
+            "ismet", "isoka", "isold", "isolt", "issac", "issai", "issam",
+            "issca", "isser", "issey", "issia", "issie", "issur", "istar",
+            "italo", "ithel", "ittai", "itzak", "itzik", "iulia", "ivana",
+            "ivann", "ivano", "iveta", "ivete", "iveth", "ivett", "ivica",
+            "ivona", "ivone", "ivori", "ivree", "ivria", "iwona", "ixaka",
+            "iyabo", "iyapo", "iyari", "iyman", "iyoka", "izaac", "izaak",
+            "izbul", "izeke", "izhar", "izola", "izora", "izsak", "iztok",
+            "izzak", "izzet", "izzie", "jaali", "jaber", "jabes", "jabin",
+            "jabir", "jacan", "jacee", "jacek", "jacen", "jacey", "jacia",
+            "jacie", "jacki", "jacob", "jacsi", "jadah", "jadda", "jadea",
+            "jadee", "jadel", "jaden", "jader", "jadey", "jadie", "jadin",
+            "jadon", "jadyn", "jaeda", "jaela", "jaeli", "jafar", "jafit",
+            "jafra", "jaggi", "jagur", "jahan", "jahel", "jahja", "jahla",
+            "jahna", "jaicy", "jaida", "jaide", "jaima", "jaime", "jaimi",
+            "jaimy", "jaine", "jaira", "jairo", "jairy", "jakab", "jakea",
+            "jakia", "jakiv", "jakki", "jakob", "jakov", "jakub", "jakup",
+            "jalal", "jaleh", "jalen", "jalil", "jalin", "jamaa", "jamal",
+            "jamar", "jamay", "jamea", "jamee", "jamel", "jamey", "jamia",
+            "jamie", "jamil", "jamin", "jamis", "jamod", "jamon", "jamya",
+            "jamye", "jamyi", "janae", "janah", "janai", "janak", "janan",
+            "janay", "janco", "jando", "jandy", "janea", "janee", "janei",
+            "janek", "janel", "janet", "janey", "janez", "jania", "janie",
+            "janis", "janit", "janka", "janko", "janna", "janne", "janos",
+            "janot", "janou", "janse", "jante", "janvi", "jaqui", "jarad",
+            "jarah", "jarda", "jareb", "jared", "jarek", "jarel", "jaren",
+            "jaret", "jaria", "jarib", "jaric", "jarid", "jaris", "jarko",
+            "jarod", "jaron", "jaryd", "jasai", "jasan", "jasek", "jasen",
+            "jasha", "jasia", "jasin", "jasma", "jasme", "jasna", "jason",
+            "jasun", "jauan", "jaume", "javad", "javar", "javed", "javen",
+            "javid", "javin", "javon", "javos", "jawon", "jaxon", "jayce",
+            "jayci", "jaycy", "jayda", "jayde", "jaydi", "jaydn", "jaydy",
+            "jayke", "jayla", "jayma", "jayme", "jaymi", "jayms", "jayna",
+            "jayne", "jayni", "jayol", "jazan", "jazze", "jazzi", "jeana",
+            "jeane", "jeani", "jeany", "jeays", "jecho", "jecis", "jeddy",
+            "jeeda", "jeena", "jeffe", "jeffy", "jefre", "jefri", "jefry",
+            "jegar", "jehan", "jehmu", "jehna", "jehri", "jeisa", "jelle",
+            "jemal", "jemar", "jemel", "jemes", "jemie", "jemma", "jemon",
+            "jenae", "jenah", "jenai", "jenal", "jenan", "jenay", "jenda",
+            "jendy", "jenee", "jenel", "jenet", "jenie", "jenik", "jenis",
+            "jenji", "jenka", "jenna", "jenni", "jenno", "jensy", "jeorg",
+            "jeppe", "jerad", "jerae", "jerah", "jerai", "jered", "jeree",
+            "jerel", "jeret", "jeric", "jerie", "jerik", "jeril", "jerin",
+            "jeris", "jerme", "jerod", "jerom", "jeron", "jerre", "jerri",
+            "jeryl", "jerzy", "jesca", "jesee", "jesey", "jeska", "jessa",
+            "jessi", "jessy", "jesus", "jetje", "jetro", "jetta", "jevan",
+            "jevin", "jevon", "jeyes", "jhona", "jiana", "jicky", "jihan",
+            "jijun", "jilan", "jilli", "jilly", "jimae", "jimar", "jimbo",
+            "jimel", "jimly", "jimoh", "jinae", "jincy", "jinda", "jinfu",
+            "jinia", "jinna", "jiske", "jitka", "jivan", "jivin", "joaby",
+            "joana", "joane", "joani", "joann", "joary", "joash", "joayn",
+            "joben", "jobey", "jobie", "jobst", "jobye", "jocek", "jocia",
+            "jodan", "jodee", "jodey", "jodhi", "jodie", "jodin", "jodon",
+            "joedy", "joela", "joeli", "joell", "joely", "joerg", "joern",
+            "jofre", "johan", "johna", "johne", "johni", "johnl", "johny",
+            "joice", "jokin", "jokla", "jolan", "jolea", "jolee", "joley",
+            "jolie", "jolin", "jolye", "jolyn", "jomei", "jonae", "jonai",
+            "jonam", "jonas", "jonay", "jonci", "jonda", "jonee", "jonel",
+            "jonie", "jonis", "jonit", "jonna", "jonni", "jonno", "jonta",
+            "jonte", "jools", "joost", "jopie", "jorah", "jorai", "joran",
+            "jordi", "jordu", "jordy", "jorea", "jorel", "jorey", "jorge",
+            "jorie", "jorik", "jorim", "jorin", "joris", "jorja", "jorma",
+            "jorry", "jorun", "josee", "josef", "josep", "joses", "joset",
+            "josey", "josha", "joshe", "joshi", "joshu", "josia", "josif",
+            "josip", "joska", "josko", "josse", "jossy", "josua", "josup",
+            "josye", "jouko", "jouni", "joval", "jovan", "jovin", "jovon",
+            "jowad", "jowie", "joxel", "joyan", "joyce", "joyia", "joyti",
+            "jozee", "jozef", "jozhe", "jozie", "jozio", "jozka", "jozsa",
+            "jozsi", "jozua", "jozus", "juana", "juann", "juaun", "jubal",
+            "juday", "judee", "judie", "judit", "judye", "jueen", "jueri",
+            "juhan", "jukie", "jukka", "julas", "julee", "julen", "jules",
+            "julet", "juley", "julia", "julie", "julka", "jumah", "juney",
+            "junia", "junie", "junji", "junot", "junya", "juraj", "jurek",
+            "jurik", "jurre", "jusak", "justa", "justi", "justo", "justy",
+            "jutta", "juval", "juvan", "juwan", "juwon", "juzef", "juziu",
+            "jyoti", "kaare", "kabir", "kacee", "kacey", "kacia", "kacie",
+            "kadar", "kaden", "kader", "kadey", "kadie", "kadin", "kadye",
+            "kaela", "kaeli", "kaely", "kaese", "kaesy", "kaffe", "kaffi",
+            "kahan", "kahil", "kahki", "kaian", "kaija", "kaila", "kaile",
+            "kaine", "kaipo", "kaira", "kaire", "kairo", "kaisa", "kaite",
+            "kaity", "kajsa", "kakha", "kakwa", "kalab", "kalea", "kaleb",
+            "kalee", "kalei", "kalel", "kalen", "kaleo", "kaleu", "kaley",
+            "kalib", "kalie", "kalil", "kalim", "kalin", "kaliq", "kalla",
+            "kalle", "kalli", "kally", "kalun", "kalye", "kalyn", "kamal",
+            "kaman", "kambo", "kamea", "kamel", "kamen", "kameo", "kamey",
+            "kamil", "kamla", "kammi", "kammy", "kamra", "kanan", "kanda",
+            "kaney", "kange", "kania", "kanny", "kanoa", "kanta", "kantu",
+            "kaomi", "kaoru", "kapil", "kapri", "kaprr", "kapua", "karah",
+            "karan", "karem", "karey", "karie", "karif", "karim", "karin",
+            "karla", "karle", "karly", "karna", "karny", "karol", "karon",
+            "karru", "karry", "karyl", "karyn", "karys", "kasci", "kascy",
+            "kasee", "kasen", "kasey", "kasho", "kasia", "kasib", "kasie",
+            "kasim", "kasin", "kasja", "kason", "kassi", "kassy", "kasya",
+            "katee", "katey", "kathi", "kathy", "katia", "katie", "katja",
+            "katka", "katla", "katri", "katti", "katus", "katya", "katye",
+            "kavai", "kavan", "kaveh", "kavin", "kayci", "kayde", "kaydi",
+            "kaydy", "kayel", "kayia", "kayin", "kayla", "kayli", "kayne",
+            "kaysi", "kaysy", "kayta", "kayte", "kazem", "kazia", "kazio",
+            "kazue", "kazuo", "keahi", "keaka", "keala", "keali", "kealy",
+            "keane", "keanu", "keara", "kearn", "keary", "keath", "kecal",
+            "kecia", "keddy", "kedem", "keder", "keefe", "keela", "keeli",
+            "keely", "keena", "keene", "keeon", "keera", "keeth", "keeya",
+            "kegan", "kegun", "keida", "keiji", "keiko", "keily", "keion",
+            "keira", "keita", "keiti", "keiwa", "kekoa", "kelan", "kelby",
+            "kelci", "kelcy", "kelda", "kelee", "kelia", "kelii", "kelle",
+            "kelli", "kelsa", "kelse", "kelsi", "kelsy", "kelye", "kemah",
+            "kemal", "kemba", "kenan", "kenda", "kendi", "kendy", "kengo",
+            "kenia", "kenja", "kenly", "kenny", "kenol", "kenon", "kenpo",
+            "kenzy", "keoki", "keola", "keone", "keoni", "keony", "kerby",
+            "keree", "kerem", "kerey", "kerim", "kermy", "kerri", "keryn",
+            "kesha", "kesia", "kesin", "kesly", "kessa", "kesse", "kessi",
+            "ketan", "keter", "ketti", "ketty", "ketul", "ketzi", "keung",
+            "keura", "kevan", "keven", "kevin", "kevis", "kevon", "kevvy",
+            "kevyn", "keyla", "keyon", "keyse", "kezia", "khaim", "khali",
+            "khanh", "khara", "khava", "kheya", "khieu", "khiri", "khiry",
+            "khleo", "khory", "khris", "khrys", "kiana", "kiane", "kiani",
+            "kiant", "kiara", "kibah", "kichi", "kidan", "kiela", "kiele",
+            "kieli", "kiely", "kiera", "kifah", "kilan", "kilda", "kilee",
+            "kilen", "kilie", "kimba", "kimee", "kimia", "kimie", "kimit",
+            "kimme", "kimmi", "kimmo", "kimmy", "kimon", "kimya", "kinan",
+            "kindi", "kinna", "kiona", "kioni", "kiral", "kiran", "kirbi",
+            "kiria", "kiril", "kirky", "kiron", "kirsi", "kirya", "kisha",
+            "kishi", "kitti", "kitts", "kivah", "kizza", "kizzy", "kjell",
+            "klaas", "klaes", "klara", "klari", "klaus", "kleef", "kleng",
+            "kleon", "kliff", "klint", "kliti", "knute", "kobet", "kobra",
+            "kodey", "kodie", "koffe", "koffi", "kohei", "kohki", "kokou",
+            "kolby", "kolia", "kolyn", "komal", "konga", "konni", "konny",
+            "kopla", "koral", "korbi", "koree", "koren", "korey", "korie",
+            "korio", "korka", "korny", "korra", "korri", "korry", "koryn",
+            "kosey", "kosma", "kosmo", "kosmy", "kosse", "kosta", "koula",
+            "kovit", "kozen", "kraig", "kreig", "krist", "kueng", "kumar",
+            "kunal", "kunio", "kunle", "kuper", "kuzih", "kwako", "kwame",
+            "kwami", "kwesi", "kyele", "kyjel", "kylah", "kylan", "kylea",
+            "kylee", "kylen", "kyler", "kylia", "kylyn", "kynan", "kynda",
+            "kyoji", "kyoko", "kyrah", "kyran", "kyria", "kyril", "kyros",
+            "labon", "lacee", "lache", "lacia", "lacie", "lacko", "ladan",
+            "ladis", "laela", "laeta", "lahea", "lahib", "laidi", "laila",
+            "laili", "laily", "laina", "lajos", "lakia", "lakva", "lalee",
+            "laleh", "lalit", "lalji", "lalka", "lalla", "lalli", "laloo",
+            "laman", "lamon", "lanae", "lanah", "lanay", "lanbo", "lancy",
+            "lando", "lanet", "lange", "lanna", "lanni", "lanny", "lantz",
+            "lanzo", "larah", "laran", "laren", "laria", "larie", "larka",
+            "larna", "laron", "larse", "lasca", "lashi", "lasho", "laslo",
+            "latai", "latau", "latea", "latha", "latia", "latif", "lauch",
+            "lauer", "lauge", "laure", "lauri", "lauro", "lauza", "lavan",
+            "lavar", "lavia", "lavon", "lawry", "laxmi", "layla", "layli",
+            "layna", "lazlo", "leala", "leana", "leane", "leann", "leasa",
+            "leavi", "lebzy", "lecia", "ledah", "ledis", "ledvi", "leeah",
+            "leean", "leeba", "leece", "leeda", "leela", "leena", "leesa",
+            "leevi", "leeza", "legra", "leial", "leian", "leiba", "leida",
+            "leidy", "leila", "leisa", "lekel", "leksi", "lelah", "lelan",
+            "lelia", "lelie", "lelio", "lella", "lelya", "lemae", "lemar",
+            "lemmy", "lenah", "lenci", "lenda", "lenea", "lenee", "lenia",
+            "lenka", "lenly", "lenna", "lenno", "lenny", "lenon", "lenor",
+            "leoda", "leola", "leoma", "leona", "leoni", "leora", "leory",
+            "leota", "lerai", "lerka", "leroi", "leron", "leroy", "lesha",
+            "lesia", "leska", "lesli", "lesly", "letha", "letif", "letta",
+            "letti", "levar", "levey", "levia", "levie", "levka", "levko",
+            "levon", "levya", "lewie", "lewin", "lewyn", "lexey", "leyla",
+            "lezli", "lezly", "libba", "libbi", "libby", "libia", "licha",
+            "licia", "lidah", "lider", "lidia", "lidio", "lidka", "lidya",
+            "liebe", "liena", "liene", "liesa", "liese", "liesl", "ligda",
+            "liisa", "lilah", "lilia", "lilie", "lilis", "lilja", "lilla",
+            "lilli", "lillo", "lilly", "lilya", "limor", "linah", "linal",
+            "linas", "linda", "lindz", "linek", "linel", "linet", "linly",
+            "linsi", "linsy", "linus", "linzi", "linzy", "liona", "liora",
+            "lippo", "liran", "liris", "liron", "lisby", "lisha", "lishe",
+            "lisia", "lison", "lissi", "lissy", "litah", "litia", "liton",
+            "litsa", "litto", "liuka", "livan", "livia", "livie", "livio",
+            "livna", "livvi", "livvy", "livya", "livye", "lizan", "lizka",
+            "lizzy", "ljube", "lloyd", "lnard", "locke", "lodie", "logen",
+            "loise", "lolee", "lolli", "loman", "lonan", "lonee", "lones",
+            "longy", "lonie", "lonna", "lonni", "lonny", "lonso", "lonzo",
+            "lorah", "loray", "loree", "loren", "lorey", "loria", "lorie",
+            "lorin", "lorna", "lorne", "lorra", "lorri", "loryn", "lotfi",
+            "lotie", "lotje", "lotti", "lotty", "louay", "loudy", "louka",
+            "loura", "lovel", "lovey", "lovie", "lowel", "loyce", "loyda",
+            "loyde", "luana", "luane", "luann", "lubba", "luben", "lubna",
+            "lubos", "lubov", "lucas", "lucho", "lucia", "lucie", "lucil",
+            "lucio", "lucus", "lucya", "lucza", "ludek", "ludie", "ludis",
+            "ludka", "ludko", "luigi", "luisa", "luise", "luiza", "lujza",
+            "lukas", "luken", "lukes", "lukus", "lulie", "lulla", "luray",
+            "lusia", "lusio", "luvvy", "luzca", "luzia", "lyall", "lycon",
+            "lydah", "lydie", "lydon", "lyell", "lygia", "lylah", "lyman",
+            "lynaa", "lynae", "lynah", "lynda", "lyndy", "lynea", "lynna",
+            "lynne", "lynsy", "lynzi", "lynzy", "lypsy", "lyris", "lyron",
+            "lysle", "lyssi", "lytie", "lyuba", "lyvon", "maaja", "mabel",
+            "mable", "mabry", "mabyn", "macey", "macha", "macia", "macie",
+            "macke", "madan", "maddi", "madea", "madee", "madel", "maden",
+            "madgi", "madhu", "madna", "madoc", "madog", "madox", "madra",
+            "maeko", "maels", "maemi", "maeve", "maevi", "maevy", "maffy",
+            "magan", "magda", "magdy", "maged", "magee", "magge", "maggi",
+            "maggy", "magid", "maglo", "magui", "maguy", "mahda", "maher",
+            "mahir", "mahsi", "maiah", "maida", "maiga", "maija", "maika",
+            "maina", "maira", "maire", "mairi", "maisa", "maisy", "maita",
+            "maite", "maive", "maiya", "maiza", "majdi", "majed", "majel",
+            "majer", "makda", "makey", "makie", "makin", "makoa", "maksa",
+            "malak", "malav", "malea", "malee", "maley", "malha", "malie",
+            "maliq", "maliz", "malka", "malki", "malle", "malli", "malte",
+            "malur", "malye", "mamed", "mamta", "manci", "manco", "mandi",
+            "mando", "mandy", "manee", "manel", "manfo", "manie", "manin",
+            "manka", "manni", "manno", "manoj", "manon", "mansy", "manue",
+            "manya", "manzi", "manzo", "marar", "marca", "marce", "marci",
+            "marcy", "marda", "marea", "maree", "marek", "maren", "marga",
+            "margo", "margy", "marie", "marii", "marin", "mario", "maris",
+            "marit", "marje", "marji", "marjy", "marke", "marko", "marla",
+            "marlo", "marna", "marni", "marny", "marra", "marsy", "marta",
+            "marth", "marti", "marty", "marva", "marve", "marvi", "marya",
+            "maryk", "maryl", "masae", "masao", "masia", "masim", "masna",
+            "masou", "massi", "masud", "matak", "matea", "matei", "matek",
+            "matel", "mateo", "mathe", "mathi", "mathu", "matia", "matis",
+            "matti", "matty", "matuq", "matus", "matya", "maude", "maudy",
+            "mauli", "mauni", "maura", "maure", "mauro", "maury", "mausi",
+            "mavon", "mavra", "maxey", "maxie", "maxna", "maxon", "mayam",
+            "mayim", "mayin", "mayme", "mayne", "mayra", "maysa", "mayte",
+            "mayur", "mayve", "mazal", "mazen", "mazie", "mazin", "mcgee",
+            "meade", "meara", "meari", "meave", "mechi", "mecki", "medel",
+            "medie", "meeka", "meeku", "meema", "meera", "megan", "megen",
+            "meggi", "meggy", "megha", "megyn", "mehdi", "mehta", "mehti",
+            "mehul", "meier", "meika", "meike", "meiko", "meila", "meilo",
+            "mekal", "melak", "melan", "melby", "melda", "melea", "melie",
+            "mella", "melli", "melva", "melya", "melyn", "mendy", "menes",
+            "menke", "menna", "menno", "menon", "menza", "merah", "meral",
+            "merce", "merci", "mered", "merek", "meric", "merie", "meril",
+            "merja", "merka", "merla", "merna", "meron", "merri", "merta",
+            "merti", "merva", "meryl", "mesum", "mesut", "metin", "metka",
+            "metsy", "metta", "mette", "meyer", "meyta", "mhari", "mhina",
+            "miata", "micah", "mical", "micci", "miccy", "micha", "michi",
+            "micho", "micki", "micol", "mieke", "mieko", "migel", "miggi",
+            "migul", "mihai", "miiko", "mikah", "mikal", "mikee", "mikel",
+            "miken", "mikey", "mikia", "mikie", "mikio", "mikis", "mikka",
+            "mikki", "mikko", "mikol", "miksa", "milah", "milda", "milek",
+            "miley", "milka", "milli", "milne", "milya", "mimma", "mimzy",
+            "minal", "minda", "mindi", "mindy", "minel", "minhy", "minik",
+            "minka", "minna", "minne", "minoo", "minta", "minya", "mique",
+            "mirae", "mirah", "miram", "miran", "mirar", "mirav", "mirek",
+            "mirel", "miren", "mirit", "mirja", "mirko", "mirna", "miron",
+            "mirra", "mirsa", "mirta", "mirto", "misha", "misho", "miska",
+            "missi", "mitch", "mitio", "mitja", "mitul", "mitya", "mitzi",
+            "miura", "mlada", "moala", "mohan", "mohen", "mohja", "moico",
+            "moien", "moina", "moise", "molia", "molli", "momoe", "monae",
+            "monah", "monay", "monca", "mondy", "monea", "monee", "monia",
+            "monna", "monro", "monti", "montu", "monty", "monya", "moore",
+            "mooro", "mopsa", "morad", "mordi", "mordy", "morey", "moria",
+            "morie", "morio", "moris", "morit", "moriz", "morla", "morly",
+            "morna", "morry", "morty", "mosha", "moshe", "mosie", "mosya",
+            "mosze", "motoo", "motti", "mouki", "mouna", "mousa", "moyna",
+            "moyra", "muffy", "mufid", "muire", "mujab", "mukta", "mukul",
+            "mundo", "mundy", "munib", "munio", "munir", "munna", "munny",
+            "murad", "murfy", "murti", "musin", "mussa", "muzzi", "mwaka",
+            "myarn", "mycah", "mykal", "mykel", "mylan", "mylee", "mylen",
+            "myles", "mylon", "myndy", "mynga", "mynor", "myrah", "myran",
+            "myria", "myrle", "myrna", "myrta", "myrth", "mysti", "mytch",
+            "myzel", "mzuzi", "nabih", "nabil", "nacia", "nacim", "nadav",
+            "nadea", "nader", "nadia", "nadim", "nadja", "nadya", "naeem",
+            "nafas", "nagib", "nagji", "nagla", "nahda", "nahid", "nahit",
+            "nahla", "naida", "naide", "naila", "naima", "naina", "nairm",
+            "naiym", "najah", "najai", "najam", "najat", "najee", "najia",
+            "najib", "najja", "najji", "najla", "najma", "najwa", "nakea",
+            "nakia", "nakos", "naldo", "namal", "namia", "namid", "namir",
+            "nance", "nanci", "nanda", "nando", "nanni", "nannu", "nanon",
+            "nanor", "nansi", "nanuk", "naoko", "naoma", "naomy", "naoto",
+            "naoya", "napea", "narah", "narda", "naren", "naser", "nasha",
+            "nasia", "nasim", "nasir", "nasit", "nasry", "nasya", "natan",
+            "natia", "natia", "natie", "natja", "natka", "natka", "natti",
+            "natya", "nauns", "navek", "navia", "navid", "navin", "navit",
+            "nawaf", "nawal", "nawaq", "nawat", "nayad", "nayan", "nayef",
+            "nayla", "nazar", "nazih", "nazli", "nazmi", "nazyf", "ndudi",
+            "neala", "neale", "neall", "nealy", "neary", "necha", "necia",
+            "necie", "necip", "nedda", "neddi", "nedra", "neefy", "neeka",
+            "neela", "neeli", "neely", "neema", "neeme", "neena", "neera",
+            "neeru", "neeta", "neeti", "nefen", "negla", "neicy", "neihl",
+            "neila", "neile", "neili", "neill", "neils", "nejib", "nelda",
+            "neleh", "nelek", "nelia", "nelie", "nelja", "nelka", "nella",
+            "nelle", "nelli", "nelse", "nelva", "nenad", "neneh", "nenet",
+            "nenno", "neola", "neoma", "neomi", "neomy", "neona", "nephi",
+            "neria", "nerin", "nerly", "neron", "nerys", "nesha", "nesia",
+            "nesim", "nesma", "nessa", "nessi", "nesta", "netia", "netie",
+            "netis", "netta", "netti", "nevan", "neven", "nevia", "nevil",
+            "nevin", "nevra", "nevsa", "nexcy", "neyla", "neyra", "neysa",
+            "neyva", "nezha", "nfana", "ngave", "ngila", "ngugi", "nhean",
+            "nhork", "niabi", "niall", "niamh", "niara", "nibaw", "nicci",
+            "niccy", "nicia", "nicki", "nicky", "nicos", "nidia", "nidya",
+            "nieca", "niecy", "nieem", "niele", "niels", "nigal", "nigel",
+            "nigil", "nigle", "nihad", "nihat", "nijel", "niket", "nikia",
+            "nikka", "nikky", "nikos", "niksa", "nilas", "nilce", "nilda",
+            "niles", "nilos", "niloy", "nilya", "nimaa", "nimah", "nimai",
+            "nimal", "nimmy", "ninia", "ninna", "ninor", "ninya", "niraj",
+            "niran", "nirav", "nirel", "nirin", "nirit", "nisao", "nisha",
+            "nissa", "nissi", "nisso", "nissy", "nitin", "nitis", "nitsa",
+            "nitza", "niura", "niuta", "niven", "nivia", "niyal", "nizah",
+            "noach", "noady", "noami", "nobie", "nobuo", "nodin", "noela",
+            "noell", "noemi", "nolan", "nolen", "nolia", "nolin", "nolly",
+            "nolyn", "nomar", "nonah", "nonia", "nonie", "nonna", "nonso",
+            "nonya", "noola", "noori", "norah", "norby", "noren", "normi",
+            "normy", "norna", "norri", "norty", "noson", "noton", "notra",
+            "nouni", "noura", "novia", "novka", "ntare", "nuala", "nubar",
+            "nucci", "nuela", "nuhra", "numan", "nupur", "nuran", "nuria",
+            "nurin", "nuris", "nurit", "nurul", "nutsa", "nuvia", "nyama",
+            "nydia", "nygel", "nyiko", "nyire", "nyoia", "nyoko", "nyome",
+            "nyomi", "nyree", "nyrie", "oakes", "oakly", "oates", "obbie",
+            "obert", "obery", "obrad", "oceon", "odair", "odall", "odela",
+            "odele", "odell", "odera", "odila", "odile", "odili", "odion",
+            "odolf", "odran", "ofrat", "ogdan", "ogdon", "ogier", "ogisi",
+            "ojana", "ojara", "ojars", "okbar", "okeke", "okley", "okoth",
+            "oktay", "olaff", "olafs", "olaus", "olave", "olavi", "oleda",
+            "olena", "olene", "oleta", "oleus", "olgen", "oliff", "olina",
+            "oline", "olisa", "olley", "ollye", "olner", "olrik", "olvan",
+            "olwen", "olwin", "olwyn", "omair", "omara", "omari", "omarr",
+            "ombra", "omero", "oneal", "oneil", "oneka", "onene", "onfre",
+            "onida", "oniel", "onnie", "onora", "onyda", "oonah", "oonie",
+            "opale", "ophra", "oprah", "orali", "orane", "orbel", "orela",
+            "orene", "orest", "oreta", "orhan", "orian", "orien", "orina",
+            "orino", "orlan", "orlee", "orlie", "orlin", "orman", "ormon",
+            "ornan", "ornia", "orono", "orpah", "orpha", "orran", "orrea",
+            "orren", "orrey", "orric", "orrie", "orsel", "orsen", "orsin",
+            "ortis", "orvie", "orvil", "orvin", "orwin", "osama", "osbon",
+            "oseye", "oshai", "oshay", "oshea", "osiel", "oskar", "osker",
+            "osmar", "osmel", "osmen", "osmer", "osner", "osred", "osric",
+            "ostad", "ostap", "osten", "ostin", "ostyn", "osvin", "oswin",
+            "oswyn", "osyth", "otess", "othon", "othor", "otila", "otman",
+            "otmar", "ottah", "ottey", "ottie", "ottla", "otton", "ouida",
+            "oveta", "owain", "owena", "owens", "owney", "owuor", "owynn",
+            "oxana", "ozara", "ozcan", "ozell", "ozgur", "ozias", "ozker",
+            "ozlem", "ozora", "ozrad", "ozzie", "paani", "paata", "paavo",
+            "pable", "pablo", "pachy", "pagen", "paget", "paige", "paili",
+            "paine", "paley", "palle", "palvi", "pammi", "pammy", "panas",
+            "pandi", "panom", "panos", "paola", "papni", "pappu", "parag",
+            "parke", "parys", "pasko", "patek", "patia", "paton", "patsi",
+            "patti", "patzi", "paula", "paule", "pauli", "paulo", "pauly",
+            "pavel", "pavit", "pavla", "pavle", "pavol", "pawel", "paxon",
+            "payal", "payam", "payat", "payge", "payne", "pazia", "pazit",
+            "pearu", "pecha", "peder", "peggi", "pejan", "pekah", "pekka",
+            "peleg", "pelin", "pello", "penee", "penly", "pepes", "peppe",
+            "peppi", "peral", "peran", "perce", "percy", "perec", "perka",
+            "perli", "perly", "perri", "persi", "petah", "petey", "petie",
+            "petru", "petta", "petur", "petya", "pheba", "pheby", "pheof",
+            "phila", "phili", "phill", "philo", "phoef", "phool", "phred",
+            "phuoc", "phuok", "phyfe", "phyll", "piedy", "piero", "pikke",
+            "pilan", "pilib", "pimen", "pimmi", "piotr", "pippa", "pippi",
+            "pippo", "pirjo", "pirro", "pista", "piter", "pitin", "pitte",
+            "pjotr", "plien", "pnina", "pohla", "poldi", "polla", "polli",
+            "popie", "poppi", "pouya", "powel", "premo", "prent", "priit",
+            "prinz", "prisi", "priti", "priya", "prudi", "prudy", "pruit",
+            "pryce", "pryor", "pucho", "pulak", "punyo", "purly", "purna",
+            "purvi", "puspa", "pyhis", "pyotr", "qabil", "qadim", "qadir",
+            "qadri", "qamar", "qamra", "qayum", "qiana", "qimat", "quent",
+            "queta", "quian", "quico", "quinn", "quita", "quock", "qusai",
+            "qusay", "quyen", "qwinn", "rabaa", "rabah", "rabee", "rabei",
+            "rabih", "rabri", "racel", "racha", "raddy", "radey", "radha",
+            "radik", "radim", "radly", "radue", "raeda", "raede", "raeed",
+            "raela", "raena", "raene", "rafal", "rafat", "rafee", "rafel",
+            "rafer", "raffi", "raffy", "rafic", "rafiq", "raful", "ragan",
+            "rageh", "raghd", "raghu", "ragna", "rahab", "raham", "rahel",
+            "rahil", "rahim", "rahna", "rahni", "rahul", "raiah", "raila",
+            "raina", "raine", "raini", "rainn", "raiph", "raisa", "raiza",
+            "rajaa", "rajai", "rajat", "rajiv", "rajni", "rakaa", "rakel",
+            "rakin", "ralee", "raley", "ralna", "ramaz", "ramey", "ramez",
+            "ramin", "ramos", "ramsy", "ramza", "ramzi", "ranae", "ranci",
+            "rancy", "randa", "rande", "randi", "ranen", "rania", "ranie",
+            "ranit", "ranji", "ranko", "ranna", "ranon", "raouf", "raoul",
+            "raphy", "rasha", "rasho", "rasia", "rasim", "rasja", "rasul",
+            "rasya", "rathi", "ratik", "ratip", "ratka", "ratna", "ratul",
+            "raula", "raulo", "ravan", "ravee", "ravia", "ravid", "raviv",
+            "ravon", "rawan", "rawhi", "rawia", "rawna", "rayan", "rayel",
+            "rayma", "rayna", "rayne", "rayya", "razel", "razia", "raziq",
+            "razzy", "reaad", "reade", "reamy", "reana", "rebah", "rebba",
+            "reeba", "reece", "reeda", "reema", "reena", "reeny", "reese",
+            "reeta", "reeva", "reggi", "reggy", "regia", "regin", "regis",
+            "rehna", "reida", "reide", "reijo", "reiko", "reine", "reino",
+            "reiny", "rekha", "remah", "remee", "remie", "remmy", "remzi",
+            "renae", "renan", "renat", "renee", "renia", "renie", "renke",
+            "renna", "renne", "renny", "renos", "renzo", "retha", "retta",
+            "revia", "rexan", "reyba", "reyde", "reyna", "reyne", "rezin",
+            "rezso", "rhawn", "rheba", "rheta", "rhett", "rhian", "rhoan",
+            "rhoda", "rhona", "rhyan", "riana", "riane", "riann", "riayn",
+            "ricca", "ricci", "ricco", "riccy", "richi", "richy", "ricka",
+            "ricke", "ricki", "ricky", "ricou", "riczi", "ridar", "ridha",
+            "ridly", "rieca", "rieka", "rieko", "riesa", "riess", "rieta",
+            "rifai", "rifha", "rifka", "rifki", "rigby", "rihab", "rihat",
+            "rikia", "rikki", "rikky", "riley", "rilie", "rilla", "rilya",
+            "rilye", "rinah", "rinat", "rinna", "riona", "riply", "riqua",
+            "riqui", "risha", "risly", "risto", "ritch", "ritha", "rithy",
+            "ritsa", "ritsi", "ritsy", "ritta", "rivah", "rivca", "rivka",
+            "rivvy", "riyad", "riyaz", "rizal", "rizus", "rizza", "roald",
+            "roana", "roann", "roark", "robbi", "robby", "robee", "roben",
+            "robhy", "robie", "rocco", "rocio", "rodas", "rodey", "rodgy",
+            "rodie", "rohin", "rohit", "roice", "rojay", "rolah", "rolan",
+            "roldy", "rolek", "roley", "rolfe", "rolle", "rollo", "rolon",
+            "rolph", "romel", "romen", "romie", "romke", "ronak", "ronal",
+            "ronan", "ronat", "rondi", "rondy", "ronee", "ronel", "ronen",
+            "ronia", "ronie", "ronit", "ronli", "ronna", "ronne", "ronni",
+            "ronny", "ronsy", "ronte", "roone", "roopa", "rorey", "rorie",
+            "rorke", "rorry", "rosan", "rosby", "rosco", "rosie", "rosio",
+            "rosle", "rosli", "rosse", "rossi", "rossy", "rotem", "rouda",
+            "rouza", "rowdi", "rowly", "roxcy", "roxey", "roxie", "royce",
+            "rozsa", "rozsi", "rozzi", "rozzy", "ruark", "rubee", "rubem",
+            "ruben", "rubey", "rubie", "rubin", "rubye", "ruchi", "ruddi",
+            "rudee", "rudek", "rudey", "rudin", "rufin", "ruhal", "rulan",
+            "rulon", "rumer", "ruppa", "rurik", "rusha", "rushi", "rusti",
+            "rutha", "ruthe", "ruthi", "ruthy", "ruven", "ruvim", "ruzha",
+            "ruzia", "ruzsa", "ruzya", "ryaad", "ryale", "ryana", "ryane",
+            "ryann", "rycca", "rylan", "rylee", "ryley", "rylie", "rylin",
+            "rylly", "rylyn", "ryman", "ryoji", "ryoko", "ryota", "ryozo",
+            "rysio", "ryssa", "ryuan", "saadi", "saamy", "saara", "sabel",
+            "saben", "sabit", "sabri", "sacha", "sachi", "sadad", "sadaf",
+            "sadah", "sadee", "sadek", "sadeq", "sadia", "sadie", "sadiq",
+            "sadja", "sadra", "sadri", "sadye", "sadyk", "saeed", "saeid",
+            "saemi", "safet", "saffi", "safia", "safra", "sagar", "sagia",
+            "sagit", "sahag", "sahan", "sahar", "sahen", "sahim", "sahir",
+            "sahla", "sahmi", "sahra", "saige", "saira", "sajad", "sajed",
+            "sajid", "sajit", "sakda", "salah", "saleh", "salil", "salim",
+            "salka", "salli", "salva", "salwa", "salye", "samad", "samah",
+            "sameh", "samet", "samie", "samil", "samir", "sammi", "samya",
+            "sanah", "sanat", "sande", "sandi", "sanja", "sanna", "sanne",
+            "sante", "sanyu", "saori", "sarad", "saraf", "sarah", "saral",
+            "sarey", "sarie", "sarit", "sarka", "sarog", "saroj", "sarri",
+            "saryn", "sasan", "sasha", "sasho", "sasie", "sason", "saulo",
+            "sauro", "savas", "savil", "savva", "sawad", "sawna", "saxbe",
+            "saxby", "saxen", "sayed", "sayge", "sayma", "scama", "scota",
+            "scott", "seana", "seane", "seann", "seany", "seara", "sebra",
+            "sedat", "seema", "seena", "seera", "seger", "seham", "sehba",
+            "sehed", "seidy", "seiji", "seila", "seira", "sekka", "sekou",
+            "selam", "selda", "selde", "selen", "selia", "selie", "selig",
+            "selim", "selin", "sello", "selwa", "semer", "semie", "semir",
+            "semon", "semra", "senad", "senay", "sener", "senga", "senia",
+            "senka", "senon", "senta", "seodi", "seppi", "seref", "seret",
+            "sergi", "sergo", "serko", "serle", "serug", "seryl", "serzh",
+            "sesar", "sesto", "sethe", "seula", "sevag", "sevgi", "seyed",
+            "seyla", "sezar", "shaan", "shabo", "shada", "shadd", "shadi",
+            "shaia", "shaka", "shana", "shane", "shani", "shann", "shary",
+            "shaud", "shaun", "shaye", "shayn", "shean", "sheff", "shela",
+            "sheli", "shems", "shena", "shene", "shepp", "shera", "sherb",
+            "shere", "sheri", "sherm", "sheye", "shiba", "shiek", "shifa",
+            "shika", "shila", "shile", "shilo", "shing", "shipp", "shiri",
+            "shiro", "shizu", "shoko", "shoma", "shoni", "shoun", "shree",
+            "shuka", "shuki", "shula", "shuma", "shyam", "shyan", "shyla",
+            "shyra", "siaka", "siana", "siara", "sibai", "sibby", "sibel",
+            "sibie", "siddy", "siegi", "siera", "sigal", "siggi", "siggy",
+            "signe", "signy", "siham", "sihem", "sihon", "silas", "silja",
+            "silka", "silke", "silvi", "silvy", "simah", "simao", "simba",
+            "simen", "simma", "simmi", "simms", "simmy", "simon", "sinae",
+            "sinan", "sinda", "sindi", "sindy", "siona", "sipho", "siraj",
+            "sirio", "sishi", "sissi", "sitah", "sitha", "sivia", "sivie",
+            "siwei", "sixta", "sixto", "sjaak", "sjohn", "sjure", "skeat",
+            "skila", "skipp", "skott", "skule", "skyla", "skyra", "slava",
+            "smeet", "smidt", "smita", "smyth", "sobhi", "sodek", "soffi",
+            "sofie", "sofka", "sofya", "sohar", "soile", "soley", "solje",
+            "solly", "solow", "somak", "somer", "sonal", "sonam", "sonay",
+            "sonei", "sonia", "sonja", "sonke", "sonni", "sonya", "sooki",
+            "sooze", "sophe", "sorah", "sorca", "soren", "sorin", "sosia",
+            "souad", "souza", "soyeb", "spero", "spiro", "spyke", "staas",
+            "stace", "staci", "stacy", "stana", "stano", "stasa", "stasy",
+            "stefa", "stefi", "steny", "steph", "steva", "stevi", "stevo",
+            "stevy", "stian", "stina", "stine", "storr", "strom", "studd",
+            "stuey", "suada", "suann", "subir", "sudeb", "sudha", "sudie",
+            "suela", "suely", "sueva", "sujal", "sujin", "sukee", "sulia",
+            "sulma", "sumed", "sumia", "sumie", "sumil", "sumio", "sumir",
+            "sumit", "sumon", "sumya", "sundi", "sundy", "sunee", "sunil",
+            "sunit", "sunne", "sunta", "sunya", "suphi", "suree", "susan",
+            "susen", "susey", "susie", "susil", "suson", "sussi", "sussy",
+            "sutan", "sutki", "suyen", "suzan", "suzie", "suzon", "suzue",
+            "suzyn", "svein", "svend", "sveva", "swane", "sybel", "sybil",
+            "syble", "sybyl", "sydel", "sydna", "sydni", "sydny", "sying",
+            "sylas", "sylke", "sylvi", "syman", "symia", "symin", "symms",
+            "symmy", "symon", "syndi", "syndy", "syrie", "syril", "syrus",
+            "sysky", "syver", "taavo", "tabbi", "tabea", "tabia", "tabib",
+            "tacey", "tacha", "tacia", "tacie", "tacye", "tadan", "tadao",
+            "taddy", "tadek", "tadeo", "tades", "tadey", "tadhg", "tadio",
+            "tadra", "tadzi", "taeke", "taghi", "taher", "tahir", "tahji",
+            "tahni", "taieb", "taija", "taika", "taimy", "taina", "taipa",
+            "taisa", "taite", "taitt", "taiva", "taiwo", "tajma", "takao",
+            "takis", "takra", "talad", "talal", "talan", "talat", "talea",
+            "talei", "talia", "talin", "talli", "tallu", "talna", "talor",
+            "talya", "talye", "tamaa", "tamah", "tamam", "taman", "tamia",
+            "tamie", "tamma", "tammi", "tamor", "tamra", "tamur", "tamya",
+            "tamye", "tanae", "tanaz", "tancy", "tandi", "tandy", "tanea",
+            "tanee", "tanek", "taner", "taney", "tanie", "tanja", "tanji",
+            "tanno", "tanny", "tansu", "tanun", "tanya", "tapio", "tarah",
+            "tarai", "tarak", "taran", "tarea", "taree", "tarek", "tareq",
+            "tarha", "taria", "tarif", "tarik", "tariq", "tarir", "taris",
+            "tarra", "tarun", "taryl", "taryn", "tasha", "tashi", "tasho",
+            "tasia", "tasja", "taska", "tasos", "tassi", "tasya", "tateo",
+            "tatia", "tatum", "tauna", "tauni", "tauno", "tavah", "tavey",
+            "tavia", "tavie", "tavis", "tawia", "tawni", "tawno", "tayah",
+            "tayib", "tayla", "tayna", "tayte", "tayva", "tazio", "teala",
+            "teale", "teana", "teann", "teara", "teata", "tecca", "techi",
+            "tecla", "tedda", "tedde", "teddi", "tedek", "tedik", "tedor",
+            "tedra", "teedy", "teena", "teeya", "tegan", "tegin", "tehar",
+            "tehra", "teige", "teiji", "teina", "teira", "tejah", "tejal",
+            "tejan", "tejas", "tekla", "tekle", "tekli", "telca", "telek",
+            "telem", "telka", "telle", "telmo", "telsa", "tembo", "temma",
+            "tenae", "tenea", "teney", "teral", "teran", "terel", "teren",
+            "terez", "teria", "terie", "teris", "terje", "terre", "tersa",
+            "terun", "teruo", "teryl", "teryn", "terza", "tesha", "tesia",
+            "tessa", "tessi", "tessy", "tetsu", "tetsy", "tetty", "teuku",
+            "teuvo", "tevel", "tevin", "tevis", "tevya", "tevye", "teyna",
+            "tezia", "thabo", "thada", "thadd", "thady", "thain", "thama",
+            "thanh", "thavi", "theda", "theia", "theon", "theys", "thiab",
+            "thian", "thien", "thilo", "thoma", "thomi", "thomy", "thora",
+            "thord", "thyra", "tiago", "tiana", "tiaon", "tiaya", "tibor",
+            "tichi", "ticho", "tiege", "tiena", "tiffi", "tifni", "tigan",
+            "tijan", "tijeh", "tikia", "tilar", "tilda", "tildi", "tildy",
+            "tilli", "tilly", "timae", "timie", "timin", "timka", "timmi",
+            "timmy", "timna", "timok", "timot", "timur", "tinai", "tiney",
+            "tinho", "tinka", "tippi", "tiqua", "tirah", "tirea", "tirel",
+            "tirsa", "tirza", "tisah", "tisha", "tison", "tissa", "titek",
+            "titia", "titos", "titus", "tivon", "tiyah", "toaha", "tobal",
+            "tobar", "tobby", "tobee", "tobey", "tobia", "tobie", "tobin",
+            "tobye", "todor", "tofer", "tofik", "tofiq", "tohon", "tohti",
+            "tokio", "tolek", "tolga", "tolia", "tomar", "tomas", "tomaz",
+            "tomcy", "tomek", "tomer", "tomey", "tomie", "tomik", "tomio",
+            "tomma", "tomme", "tommi", "tonda", "tonee", "tonek", "tonia",
+            "tonie", "tonik", "tonio", "tonis", "tonja", "tonni", "tonse",
+            "tonya", "tonye", "toren", "torey", "toria", "torie", "torin",
+            "torio", "torre", "torri", "torry", "torya", "torye", "tosha",
+            "toshi", "tosia", "tosin", "toska", "totsi", "totti", "tovah",
+            "tovia", "tovya", "traci", "tracy", "trava", "tresa", "trese",
+            "treva", "treve", "treza", "tribi", "tricy", "trigg", "trina",
+            "trini", "trink", "tripp", "trisa", "trish", "trixi", "trixy",
+            "troia", "trola", "trond", "troya", "troye", "truby", "truda",
+            "trude", "trudi", "trudy", "trula", "tryna", "tsend", "tsion",
+            "tsvia", "tuari", "tuffy", "tuija", "tukie", "tukun", "tulah",
+            "tulio", "tully", "tuluy", "tunde", "tuula", "tuvia", "tuvya",
+            "tuyen", "twayn", "twila", "twyla", "tyann", "tyara", "tybie",
+            "tycho", "tyesn", "tykia", "tylar", "tylda", "tyldy", "tylea",
+            "tylee", "tylia", "tylor", "tymon", "tynan", "tynka", "tyraa",
+            "tyrae", "tyrah", "tyray", "tyrea", "tyree", "tyrel", "tyria",
+            "tyrik", "tyriq", "tyron", "tysha", "tysie", "tysne", "tyson",
+            "tyssa", "tytan", "tytus", "tywan", "tywon", "tzahi", "tzevi",
+            "tzion", "uaine", "udale", "udall", "udele", "udell", "udolf",
+            "uford", "ugutz", "ujjal", "ukasz", "ulana", "ulane", "ulane",
+            "ulani", "ulger", "ulick", "ulima", "ullah", "ullas", "ulmar",
+            "ulmer", "ulrik", "ultan", "umang", "umarr", "umaru", "umayr",
+            "umeko", "umesh", "umeyo", "unica", "unice", "unika", "uniss",
+            "unita", "unsun", "unwin", "unwyn", "ureli", "uriah", "urian",
+            "urias", "uriel", "urien", "urika", "urmas", "ursei", "ursel",
+            "ursey", "ursie", "urtzi", "urvan", "usama", "ushma", "ustad",
+            "ustin", "utako", "utibe", "utina", "uttam", "uttra", "uzair",
+            "uziel", "uzzah", "vadim", "vadin", "vadit", "vadym", "vagit",
+            "vahan", "vaidy", "vaile", "vaill", "vaira", "vaiva", "valda",
+            "valen", "valia", "valin", "valle", "valli", "valma", "valry",
+            "valya", "valyn", "vanae", "vance", "vandi", "vanek", "vangy",
+            "vania", "vanko", "vanna", "vanni", "vanno", "vanny", "vanya",
+            "varel", "varga", "varro", "varun", "varya", "vasco", "vasek",
+            "vasil", "vasin", "vasko", "vasos", "vasti", "vasya", "vasyl",
+            "vayle", "vazul", "vedad", "vedis", "veeda", "veera", "veeta",
+            "veeva", "veida", "veiko", "veira", "velda", "velma", "vence",
+            "venis", "venna", "venya", "veola", "veran", "verda", "verdi",
+            "vered", "veria", "verka", "verla", "verly", "verna", "verne",
+            "veron", "verta", "veryl", "vesna", "vessy", "vesty", "vetha",
+            "veton", "viana", "viann", "vibhu", "vicci", "viccy", "viciu",
+            "vicke", "vicki", "vicky", "victa", "videl", "vidia", "vidor",
+            "vieda", "viera", "vieva", "viggo", "vijai", "vijay", "vikas",
+            "vikie", "vikki", "vikky", "vilay", "vilek", "vilem", "vilen",
+            "vilis", "viliy", "viljo", "vilma", "vimka", "vimla", "vinay",
+            "vince", "vinci", "vinco", "vincy", "vinia", "vinko", "vinna",
+            "vinni", "vinod", "viole", "viona", "vipin", "vipul", "virge",
+            "virgy", "virna", "vitel", "vitia", "vitin", "vitka", "vitke",
+            "vitus", "vitya", "vivan", "vivee", "vivek", "vivia", "vivie",
+            "vivva", "vivvy", "vizma", "vlade", "vlado", "volya", "vonda",
+            "vonna", "vonni", "vonny", "vraja", "vytas", "waban", "wadie",
+            "wadly", "wafik", "wafiq", "wahbi", "waide", "waiel", "waite",
+            "wakil", "walda", "waldi", "waldy", "walid", "walie", "walli",
+            "wally", "walon", "walsh", "waltr", "wamid", "wanda", "wandi",
+            "wanja", "wanye", "waqar", "warda", "warde", "waris", "warny",
+            "wasim", "wayan", "wayde", "wayne", "wayte", "webly", "wedad",
+            "weeko", "welby", "welda", "welti", "wenda", "wendi", "wendy",
+            "werth", "wesam", "wesla", "wesly", "whitt", "whoda", "whyte",
+            "wiatt", "widad", "wikie", "wilba", "wilda", "wildy", "wilek",
+            "wiley", "willa", "wille", "willi", "willo", "wilma", "wilna",
+            "wimar", "winda", "windi", "winne", "winni", "winny", "wintr",
+            "wisia", "witek", "witha", "woana", "wolfe", "wolff", "wolfy",
+            "wonda", "woney", "woolf", "worie", "worom", "wudeh", "wyant",
+            "wyatt", "wyche", "wyeth", "wylda", "wylie", "wylma", "wyman",
+            "wymer", "wyndi", "wyndy", "wynny", "xandy", "xanne", "xaver",
+            "xavia", "xavon", "xever", "xiang", "xylon", "yaani", "yacef",
+            "yachi", "yacov", "yaeko", "yaeli", "yaffa", "yafit", "yagel",
+            "yagil", "yahia", "yahir", "yahya", "yaile", "yaima", "yaisy",
+            "yajur", "yakez", "yakob", "yakov", "yamie", "yamka", "yanah",
+            "yanar", "yance", "yanci", "yancy", "yanet", "yaney", "yania",
+            "yanik", "yanis", "yaniv", "yanka", "yanna", "yanni", "yanno",
+            "yanti", "yarek", "yarey", "yariv", "yaron", "yasar", "yaser",
+            "yasha", "yasir", "yasma", "yasuo", "yatin", "yavin", "yazan",
+            "yazen", "yazid", "yeala", "yeats", "yefat", "yefim", "yegor",
+            "yehed", "yehor", "yehua", "yeira", "yelba", "yenih", "yenni",
+            "yenny", "yensy", "yeshi", "yesim", "yeska", "yetta", "yetty",
+            "yevno", "yezad", "yezzy", "yhaya", "yhuda", "yifan", "yigel",
+            "yihye", "yinka", "yipsi", "yitro", "yitta", "ylana", "yngve",
+            "yoana", "yoash", "yobie", "yodit", "yohji", "yokie", "yoley",
+            "yolie", "yolly", "yonah", "yonas", "yonat", "yonca", "yonit",
+            "yonna", "yoram", "yorga", "yorgo", "yorke", "yosef", "yoshi",
+            "yosif", "yosik", "yosor", "yosri", "yossi", "yosyf", "yotam",
+            "youri", "yovan", "ysann", "ysbel", "yseut", "ysolt", "ystad",
+            "yuana", "yuber", "yubin", "yucel", "yudah", "yudel", "yudit",
+            "yuiki", "yukie", "yulia", "yulie", "yulla", "yunas", "yunus",
+            "yuria", "yurii", "yurij", "yuriy", "yurko", "yurri", "yusef",
+            "yusha", "yusif", "yusri", "yusuf", "yusup", "yuuki", "yuval",
+            "yvana", "yvens", "yvone", "zabit", "zacha", "zachy", "zacky",
+            "zadie", "zadik", "zadoc", "zafar", "zafir", "zaher", "zahik",
+            "zahir", "zahra", "zahur", "zaiba", "zaide", "zaira", "zakes",
+            "zakey", "zakia", "zakir", "zakri", "zakry", "zaleh", "zalfa",
+            "zamah", "zamir", "zanda", "zandy", "zaned", "zanna", "zanne",
+            "zanny", "zanth", "zarai", "zareb", "zared", "zaree", "zarek",
+            "zarin", "zarko", "zarya", "zasha", "zayda", "zayed", "zayit",
+            "zayle", "zayna", "zayne", "zayta", "zazai", "zazie", "zealy",
+            "zeeba", "zeena", "zeeta", "zeeva", "zeevi", "zefir", "zeheb",
+            "zeina", "zelah", "zelda", "zelde", "zelia", "zelie", "zelig",
+            "zelik", "zella", "zelma", "zemah", "zemar", "zenab", "zenah",
+            "zenan", "zenas", "zenea", "zenia", "zenna", "zenon", "zenos",
+            "zenya", "zerah", "zerla", "zerom", "zetes", "zetta", "zevie",
+            "zeyno", "zhana", "zhora", "zhvie", "zibby", "zidan", "ziggy",
+            "zigor", "zihna", "zilah", "zilla", "zilya", "zimra", "zimri",
+            "zinah", "zinia", "zinka", "zinna", "zinny", "zinon", "zinya",
+            "ziral", "zirel", "zishe", "ziska", "ziven", "zivia", "zivie",
+            "zivit", "zivka", "zivko", "zivon", "zizou", "zocha", "zoela",
+            "zofer", "zofia", "zofka", "zohra", "zoila", "zoilo", "zolly",
+            "zonia", "zoran", "zorba", "zorie", "zorna", "zorya", "zouri",
+            "zoyya", "zsolt", "zubah", "zubin", "zulay", "zulma", "zurab",
+            "zuria", "zviad", "zylla"
+    };
+
+    public String getText() {
+        int car = FIRST_NAMES.length - 1;
+        return FIRST_NAMES[GENERATOR.nextInt(car) + 1];
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/TextProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/TextProducer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/TextProducer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,16 @@
+package nl.captcha.text.producer;
+
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public interface TextProducer {
+
+    /**
+     * Generate a series of characters.
+     * 
+     * @return
+     */
+    public String getText();
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/ColoredEdgesWordRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/ColoredEdgesWordRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/ColoredEdgesWordRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,103 @@
+package nl.captcha.text.renderer;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextAttribute;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Creates an outlined version of the answer using the given colors and fonts.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class ColoredEdgesWordRenderer implements WordRenderer {
+
+	private static final List<Color> DEFAULT_COLORS = new ArrayList<Color>();
+	private static final List<Font> DEFAULT_FONTS = new ArrayList<Font>();
+	private static final float DEFAULT_STROKE_WIDTH = 0.5f;
+	// The text will be rendered 25%/5% of the image height/width from the X and Y axes
+	private static final double YOFFSET = 0.25;
+	private static final double XOFFSET = 0.05;
+	
+	private final List<Font> _fonts;
+	private final List<Color> _colors;
+	private final float _strokeWidth;
+	
+	static {
+		DEFAULT_FONTS.add(new Font("Arial", Font.BOLD, 40));
+		DEFAULT_COLORS.add(Color.BLUE);
+	}
+
+	public ColoredEdgesWordRenderer() {
+		this(DEFAULT_COLORS, DEFAULT_FONTS, DEFAULT_STROKE_WIDTH);
+	}
+	
+	public ColoredEdgesWordRenderer(List<Color> colors, List<Font> fonts) {
+		this(colors, fonts, DEFAULT_STROKE_WIDTH);
+	}
+	
+	public ColoredEdgesWordRenderer(List<Color> colors, List<Font> fonts, float strokeWidth) {
+		_colors = colors != null ? colors : DEFAULT_COLORS;
+		_fonts = fonts != null ? fonts : DEFAULT_FONTS;
+		_strokeWidth = strokeWidth < 0 ? DEFAULT_STROKE_WIDTH : strokeWidth;
+	}
+
+	public void render(final String word, BufferedImage image) {
+		Graphics2D g = image.createGraphics();
+		
+        RenderingHints hints = new RenderingHints(
+                RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+        hints.add(new RenderingHints(RenderingHints.KEY_RENDERING,
+                RenderingHints.VALUE_RENDER_QUALITY));
+        g.setRenderingHints(hints);
+
+		AttributedString as = new AttributedString(word);
+		as.addAttribute(TextAttribute.FONT, getRandomFont());
+
+		FontRenderContext frc = g.getFontRenderContext();
+		AttributedCharacterIterator aci = as.getIterator();
+		
+		TextLayout tl = new TextLayout(aci, frc);
+        int xBaseline = (int) Math.round(image.getWidth() * XOFFSET);
+        int yBaseline =  image.getHeight() - (int) Math.round(image.getHeight() * YOFFSET);
+		Shape shape = tl.getOutline(AffineTransform.getTranslateInstance(xBaseline, yBaseline));
+
+		g.setColor(getRandomColor());
+		g.setStroke(new BasicStroke(_strokeWidth));
+		
+		g.draw(shape);
+	}
+	
+	private Color getRandomColor() {
+		return (Color) getRandomObject(_colors);
+	}
+	
+	private Font getRandomFont() {
+		return (Font) getRandomObject(_fonts);
+	}
+	
+	private Object getRandomObject(List<? extends Object> objs) {
+		if (objs.size() == 1) {
+			return objs.get(0);
+		}
+		
+		Random gen = new SecureRandom();
+		int i = gen.nextInt(objs.size());
+		return objs.get(i);
+	}
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/DefaultWordRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/DefaultWordRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/DefaultWordRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,79 @@
+package nl.captcha.text.renderer;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Render a word using the given color and from a randomly selected font chosen from 
+ * a list of fonts given in the constructor.
+ * 
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ */
+public class DefaultWordRenderer implements WordRenderer {
+
+	private static final Color DEFAULT_COLOR = Color.BLACK;
+	private static final List<Font> DEFAULT_FONTS = new ArrayList<Font>();
+    
+    private final Color _color;
+    private final List<Font> _fonts;
+    
+    static {
+    	DEFAULT_FONTS.add(new Font("Arial", Font.BOLD, 40));
+        DEFAULT_FONTS.add(new Font("Courier", Font.BOLD, 40));	
+    }
+    
+    /**
+     * Will render the characters in black and in either 40pt Arial or Courier.
+     */
+    public DefaultWordRenderer() {
+    	this(DEFAULT_COLOR, DEFAULT_FONTS);
+    }
+    
+    public DefaultWordRenderer(Color color, List<Font> fonts) {
+    	_color = color != null ? color : DEFAULT_COLOR;
+    	_fonts = fonts != null ? fonts : DEFAULT_FONTS;
+    }
+
+    /**
+     * Render a word onto a BufferedImage.
+     * 
+     * @param word The word to be rendered.
+     * @param bi  The BufferedImage onto which the word will be painted on to
+     */
+    public void render(String word, BufferedImage image) {
+        Graphics2D g = image.createGraphics();
+
+        RenderingHints hints = new RenderingHints(
+                RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+        hints.add(new RenderingHints(RenderingHints.KEY_RENDERING,
+                RenderingHints.VALUE_RENDER_QUALITY));
+        g.setRenderingHints(hints);
+
+        g.setColor(_color);
+        FontRenderContext frc = g.getFontRenderContext();
+        int startPosX = 25;
+        char[] wc = word.toCharArray();
+        Random generator = new Random();
+        for (char element : wc) {
+            char[] itchar = new char[] { element };
+            int choiceFont = generator.nextInt(_fonts.size());
+            Font itFont = _fonts.get(choiceFont);
+            g.setFont(itFont);
+
+            GlyphVector gv = itFont.createGlyphVector(frc, itchar);
+            double charWitdth = gv.getVisualBounds().getWidth();
+
+            g.drawChars(itchar, 0, itchar.length, startPosX, 35);
+            startPosX = startPosX + (int) charWitdth;
+        }
+    }
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/WordRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/WordRenderer.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/WordRenderer.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,23 @@
+package nl.captcha.text.renderer;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * 
+ */
+public interface WordRenderer {
+    /**
+     * Render a word to a BufferedImage.
+     * 
+     * @param word
+     *            The word to be rendered.
+     * @param width
+     *            The width of the image to be created.
+     * @param height
+     *            The height of the image to be created.
+     * @return The BufferedImage created from the word.
+     */
+    public void render(String word, BufferedImage image);
+
+}

Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/util/ImageUtil.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/util/ImageUtil.java	                        (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/util/ImageUtil.java	2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,18 @@
+package nl.captcha.util;
+
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageFilter;
+
+public class ImageUtil {
+	public static final void applyFilter(BufferedImage img, ImageFilter filter) {
+//		FilteredImageSource src = new FilteredImageSource(img.getSource(), filter);
+		Image fImg = Toolkit.getDefaultToolkit().createImage(img.getSource());
+		Graphics2D g = img.createGraphics();
+		g.drawImage(fImg, 0, 0, null, null);
+		g.dispose();
+	}
+}



More information about the gatein-commits mailing list