ruby_wordcram 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.mvn/extensions.xml +8 -0
  4. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  5. data/Rakefile +28 -5
  6. data/docs/_posts/2017-03-07-getting_started.md +3 -2
  7. data/docs/_posts/2017-03-07-under_the_hood.md +33 -0
  8. data/lib/WordCram.jar +0 -0
  9. data/lib/jsoup-1.10.2.jar +0 -0
  10. data/lib/ruby_wordcram/version.rb +1 -1
  11. data/lib/ruby_wordcram.rb +1 -2
  12. data/pom.rb +53 -0
  13. data/pom.xml +87 -0
  14. data/ruby_wordcram.gemspec +1 -2
  15. data/src/cue/lang/Counter.java +141 -0
  16. data/src/cue/lang/IterableText.java +10 -0
  17. data/src/cue/lang/NGramIterator.java +151 -0
  18. data/src/cue/lang/SentenceIterator.java +86 -0
  19. data/src/cue/lang/WordIterator.java +60 -0
  20. data/src/cue/lang/stop/StopWords.java +114 -0
  21. data/src/cue/lang/stop/arabic +351 -0
  22. data/src/cue/lang/stop/armenian +45 -0
  23. data/src/cue/lang/stop/catalan +219 -0
  24. data/src/cue/lang/stop/croatian +2024 -0
  25. data/src/cue/lang/stop/czech +256 -0
  26. data/src/cue/lang/stop/danish +94 -0
  27. data/src/cue/lang/stop/dutch +107 -0
  28. data/src/cue/lang/stop/english +183 -0
  29. data/src/cue/lang/stop/esperanto +180 -0
  30. data/src/cue/lang/stop/farsi +966 -0
  31. data/src/cue/lang/stop/finnish +235 -0
  32. data/src/cue/lang/stop/french +543 -0
  33. data/src/cue/lang/stop/german +231 -0
  34. data/src/cue/lang/stop/greek +637 -0
  35. data/src/cue/lang/stop/hebrew +220 -0
  36. data/src/cue/lang/stop/hindi +97 -0
  37. data/src/cue/lang/stop/hungarian +202 -0
  38. data/src/cue/lang/stop/italian +279 -0
  39. data/src/cue/lang/stop/latin +1 -0
  40. data/src/cue/lang/stop/norwegian +176 -0
  41. data/src/cue/lang/stop/polish +138 -0
  42. data/src/cue/lang/stop/portuguese +204 -0
  43. data/src/cue/lang/stop/romanian +284 -0
  44. data/src/cue/lang/stop/russian +652 -0
  45. data/src/cue/lang/stop/slovak +110 -0
  46. data/src/cue/lang/stop/slovenian +448 -0
  47. data/src/cue/lang/stop/spanish +308 -0
  48. data/src/cue/lang/stop/swedish +114 -0
  49. data/src/cue/lang/stop/turkish +117 -0
  50. data/src/cue/lang/unicode/BlockUtil.java +103 -0
  51. data/src/cue/lang/unicode/Normalizer.java +55 -0
  52. data/src/cue/lang/unicode/Normalizer6.java +32 -0
  53. data/src/license.txt +201 -0
  54. data/src/wordcram/Anglers.java +137 -0
  55. data/src/wordcram/BBTree.java +133 -0
  56. data/src/wordcram/BBTreeBuilder.java +61 -0
  57. data/src/wordcram/Colorers.java +52 -0
  58. data/src/wordcram/EngineWord.java +73 -0
  59. data/src/wordcram/Fonters.java +17 -0
  60. data/src/wordcram/HsbWordColorer.java +28 -0
  61. data/src/wordcram/ImageShaper.java +91 -0
  62. data/src/wordcram/Observer.java +9 -0
  63. data/src/wordcram/PlacerHeatMap.java +134 -0
  64. data/src/wordcram/Placers.java +74 -0
  65. data/src/wordcram/PlottingWordNudger.java +38 -0
  66. data/src/wordcram/PlottingWordPlacer.java +36 -0
  67. data/src/wordcram/ProcessingWordRenderer.java +42 -0
  68. data/src/wordcram/RandomWordNudger.java +44 -0
  69. data/src/wordcram/RenderOptions.java +10 -0
  70. data/src/wordcram/ShapeBasedPlacer.java +66 -0
  71. data/src/wordcram/Sizers.java +54 -0
  72. data/src/wordcram/SketchCallbackObserver.java +70 -0
  73. data/src/wordcram/SpiralWordNudger.java +31 -0
  74. data/src/wordcram/SvgWordRenderer.java +110 -0
  75. data/src/wordcram/SwirlWordPlacer.java +25 -0
  76. data/src/wordcram/UpperLeftWordPlacer.java +27 -0
  77. data/src/wordcram/WaveWordPlacer.java +25 -0
  78. data/src/wordcram/Word.java +357 -0
  79. data/src/wordcram/WordAngler.java +20 -0
  80. data/src/wordcram/WordArray.java +18 -0
  81. data/src/wordcram/WordBag.java +31 -0
  82. data/src/wordcram/WordColorer.java +25 -0
  83. data/src/wordcram/WordCounter.java +96 -0
  84. data/src/wordcram/WordCram.java +920 -0
  85. data/src/wordcram/WordCramEngine.java +196 -0
  86. data/src/wordcram/WordFonter.java +24 -0
  87. data/src/wordcram/WordNudger.java +44 -0
  88. data/src/wordcram/WordPlacer.java +44 -0
  89. data/src/wordcram/WordRenderer.java +10 -0
  90. data/src/wordcram/WordShaper.java +78 -0
  91. data/src/wordcram/WordSizer.java +46 -0
  92. data/src/wordcram/WordSkipReason.java +42 -0
  93. data/src/wordcram/WordSorterAndScaler.java +31 -0
  94. data/src/wordcram/WordSource.java +5 -0
  95. data/src/wordcram/text/Html.java +15 -0
  96. data/src/wordcram/text/Html2Text.java +17 -0
  97. data/src/wordcram/text/Text.java +15 -0
  98. data/src/wordcram/text/TextFile.java +23 -0
  99. data/src/wordcram/text/TextSource.java +5 -0
  100. data/src/wordcram/text/WebPage.java +23 -0
  101. metadata +94 -5
  102. data/lib/cue.language.jar +0 -0
  103. data/lib/jsoup-1.7.2.jar +0 -0
  104. data/vendors/Rakefile +0 -51
@@ -0,0 +1,9 @@
1
+ package wordcram;
2
+
3
+ public interface Observer {
4
+ public void wordsCounted(Word[] words);
5
+ public void beginDraw();
6
+ public void wordDrawn(Word word);
7
+ public void wordSkipped(Word word);
8
+ public void endDraw();
9
+ }
@@ -0,0 +1,134 @@
1
+ package wordcram;
2
+
3
+ import java.awt.Shape; // awt: word->shape->rect
4
+ import java.awt.geom.Rectangle2D; // awt: intersects(box), x-y-w-h, bounds
5
+ import java.util.ArrayList;
6
+ import java.util.HashMap;
7
+
8
+ import processing.core.PApplet;
9
+ import processing.core.PFont;
10
+ import processing.core.PVector;
11
+
12
+ public class PlacerHeatMap {
13
+
14
+ private final Word[] words;
15
+ private final WordFonter fonter;
16
+ private final WordSizer sizer;
17
+ private final WordAngler angler;
18
+ private final WordPlacer placer;
19
+ private final WordNudger nudger;
20
+ private final WordShaper shaper;
21
+
22
+ PlacerHeatMap(Word[] words, WordFonter fonter, WordSizer sizer, WordAngler angler, WordPlacer placer, WordNudger nudger, WordShaper shaper) {
23
+
24
+ this.fonter = fonter;
25
+ this.sizer = sizer;
26
+ this.angler = angler;
27
+ this.placer = placer;
28
+ this.nudger = nudger;
29
+ this.shaper = shaper;
30
+ this.words = words;
31
+ }
32
+
33
+ class RectStack {
34
+ ArrayList<Rectangle2D> rects = new ArrayList<>();
35
+
36
+ void add(int x, int y, int w, int h) {
37
+ rects.add(new Rectangle2D.Float(x, y, w, h));
38
+ }
39
+
40
+ int howManyIntersect(int x, int y, int w, int h) {
41
+ int sum = 0;
42
+
43
+ sum = rects.stream().filter((r) -> (r.intersects(x, y, w, h))).map((_item) -> 1).reduce(sum, Integer::sum);
44
+
45
+ return sum;
46
+ }
47
+ }
48
+
49
+ class RectGrid {
50
+ RectStack stack;
51
+ HashMap<Rectangle2D, Integer> levels = new HashMap<>();
52
+
53
+ RectGrid(RectStack stack) {
54
+ this.stack = stack;
55
+ }
56
+
57
+ void measure(int x, int y, int w, int h) {
58
+ Rectangle2D plot = new Rectangle2D.Float(x, y, w, h);
59
+ int level = stack.howManyIntersect(x, y, w, h);
60
+ levels.put(plot, level);
61
+ }
62
+
63
+ int maxLevel() {
64
+ int maxLevel = 0;
65
+ for (Integer level : levels.values()) {
66
+ if (level > maxLevel) {
67
+ maxLevel = level;
68
+ }
69
+ }
70
+ return maxLevel;
71
+ }
72
+
73
+ void draw(PApplet sketch) {
74
+ int rowHeight = 10;
75
+ int colWidth = 10;
76
+ int rows = (int)(sketch.height / (float)rowHeight);
77
+ int cols = (int)(sketch.width / (float)colWidth);
78
+
79
+ for (int i = 0; i < rows; i++) {
80
+ int y = i * rowHeight;
81
+ for (int j = 0; j < cols; j++) {
82
+ int x = j * colWidth;
83
+
84
+ measure(x, y, colWidth, rowHeight);
85
+ }
86
+ }
87
+
88
+ sketch.colorMode(PApplet.HSB);
89
+
90
+ int max = maxLevel();
91
+ levels.keySet().forEach((rect) -> {
92
+ Integer level = levels.get(rect);
93
+
94
+ int c = sketch.color(0);
95
+ if (level > 0) {
96
+ float scaled = (float)level / 8;
97
+ int hue = (int)PApplet.map(scaled, 0, 1, 85, 0); // 85 = pure green
98
+ c = sketch.color(hue, 255, 255);
99
+ }
100
+
101
+ sketch.fill(c);
102
+ sketch.rect((float)rect.getX(), (float)rect.getY(), (float)rect.getWidth(), (float)rect.getHeight());
103
+ });
104
+ }
105
+ }
106
+
107
+ public void draw(PApplet sketch) {
108
+ RectStack rectStack = new RectStack();
109
+
110
+ for (int i = 0; i < words.length; i++) {
111
+ Word word = words[i];
112
+ PFont wordFont = word.getFont(fonter);
113
+ float wordSize = word.getSize(sizer, i, words.length);
114
+ float wordAngle = word.getAngle(angler);
115
+
116
+ Shape shape = shaper.getShapeFor(word.word, wordFont, wordSize, wordAngle);
117
+ Rectangle2D rect = shape.getBounds2D();
118
+ //return r.getHeight() < minShapeSize || r.getWidth() < minShapeSize;
119
+
120
+ int wordImageWidth = (int)rect.getWidth();
121
+ int wordImageHeight = (int)rect.getHeight();
122
+
123
+ PVector desiredLocation = word.getTargetPlace(placer, i, words.length,
124
+ wordImageWidth, wordImageHeight, sketch.width, sketch.height);
125
+
126
+ //sketch.rect(desiredLocation.x, desiredLocation.y, wordImageWidth, wordImageHeight);
127
+ rectStack.add((int)desiredLocation.x, (int)desiredLocation.y,
128
+ wordImageWidth, wordImageHeight);
129
+ }
130
+
131
+ RectGrid grid = new RectGrid(rectStack);
132
+ grid.draw(sketch);
133
+ }
134
+ }
@@ -0,0 +1,74 @@
1
+ package wordcram;
2
+
3
+ import java.util.Random;
4
+
5
+ import processing.core.PApplet;
6
+ import processing.core.PVector;
7
+
8
+ public class Placers {
9
+
10
+ public static WordPlacer horizLine() {
11
+ final Random r = new Random();
12
+
13
+ return (Word word, int wordIndex, int wordsCount, int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) -> {
14
+ int centerHorizLine = (int) ((fieldHeight - wordImageHeight) * 0.5);
15
+ int centerVertLine = (int) ((fieldWidth - wordImageWidth) * 0.5);
16
+
17
+ float xOff = (float) r.nextGaussian() * ((fieldWidth - wordImageWidth) * 0.2f);
18
+ float yOff = (float) r.nextGaussian() * 50;
19
+
20
+ return new PVector(centerVertLine + xOff, centerHorizLine + yOff);
21
+ /*
22
+ int adjFieldWidth = fieldWidth - wordImageWidth;
23
+ int adjFieldHeight = fieldHeight - wordImageHeight;
24
+
25
+ float xOff = (float) r.nextGaussian();// * 0.2f;
26
+ float yOff = (float) r.nextGaussian();// * 0.5f;
27
+ yOff = (float)Math.pow(yOff, 3) * 1.5f;
28
+
29
+ return new PVector(PApplet.map(xOff, -2, 2, 0, adjFieldWidth),
30
+ PApplet.map(yOff, -2, 2, 0, adjFieldHeight));
31
+ */ };
32
+ }
33
+
34
+ public static WordPlacer centerClump() {
35
+ final Random r = new Random();
36
+ final float stdev = 0.4f;
37
+
38
+ return new WordPlacer() {
39
+
40
+ @Override
41
+ public PVector place(Word word, int wordIndex, int wordsCount,
42
+ int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) {
43
+ return new PVector(getOneUnder(fieldWidth - wordImageWidth),
44
+ getOneUnder(fieldHeight - wordImageHeight));
45
+ }
46
+
47
+ private int getOneUnder(float upperLimit) {
48
+ return PApplet.round(PApplet.map((float) r.nextGaussian()
49
+ * stdev, -2, 2, 0, upperLimit));
50
+ }
51
+ };
52
+ }
53
+
54
+ public static WordPlacer horizBandAnchoredLeft() {
55
+ final Random r = new Random();
56
+ return (Word word, int wordIndex, int wordsCount, int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) -> {
57
+ float x = (1 - word.weight) * fieldWidth * r.nextFloat(); // big=left, small=right
58
+ float y = ((float) fieldHeight) * 0.5f;
59
+ return new PVector(x, y);
60
+ };
61
+ }
62
+
63
+ public static WordPlacer swirl() {
64
+ return new SwirlWordPlacer();
65
+ }
66
+
67
+ public static WordPlacer upperLeft() {
68
+ return new UpperLeftWordPlacer();
69
+ }
70
+
71
+ public static WordPlacer wave() {
72
+ return new WaveWordPlacer();
73
+ }
74
+ }
@@ -0,0 +1,38 @@
1
+ package wordcram;
2
+
3
+ import processing.core.PApplet;
4
+ import processing.core.PVector;
5
+
6
+ /**
7
+ * If you're using a custom WordNudger, and having difficulty seeing
8
+ * how well it works, try wrapping it in a PlottingWordNudger. As your
9
+ * WordCram is drawn, it'll render tiny dots at each location it
10
+ * nudges your words to, so you can see how well it's working.
11
+ */
12
+ public class PlottingWordNudger implements WordNudger {
13
+
14
+ private final PApplet parent;
15
+ private final WordNudger wrappedNudger;
16
+
17
+ public PlottingWordNudger(PApplet _parent, WordNudger _wrappedNudger) {
18
+ parent = _parent;
19
+ wrappedNudger = _wrappedNudger;
20
+ }
21
+
22
+ @Override
23
+ public PVector nudgeFor(Word word, int attempt) {
24
+ PVector v = wrappedNudger.nudgeFor(word, attempt);
25
+ parent.pushStyle();
26
+ parent.noStroke();
27
+
28
+ float alpha = attempt/700f;
29
+ //alpha = (float) Math.pow(alpha, 3);
30
+ parent.fill(40, 255, 255); //, alpha * 255);
31
+
32
+ PVector wordLoc = PVector.add(v, word.getTargetPlace());
33
+ parent.ellipse(wordLoc.x, wordLoc.y, 3, 3);
34
+ parent.popStyle();
35
+ return v;
36
+ }
37
+
38
+ }
@@ -0,0 +1,36 @@
1
+ package wordcram;
2
+
3
+ import processing.core.PApplet;
4
+ import processing.core.PVector;
5
+
6
+ /**
7
+ * If you're using a custom WordPlacer, and having difficulty seeing
8
+ * how well it works, try wrapping it in a PlottingWordPlacer. As your
9
+ * WordCram is drawn, it'll render tiny dots at each word's target
10
+ * location, so you can sort-of see how far off they are when they're
11
+ * finally rendered.
12
+ */
13
+ public class PlottingWordPlacer implements WordPlacer {
14
+
15
+ private final PApplet parent;
16
+ private final WordPlacer wrappedPlacer;
17
+
18
+ public PlottingWordPlacer(PApplet _parent, WordPlacer _wrappedPlacer) {
19
+ parent = _parent;
20
+ wrappedPlacer = _wrappedPlacer;
21
+ }
22
+
23
+ @Override
24
+ public PVector place(Word word, int wordIndex, int wordsCount, int wordImageWidth, int wordImageHeight, int fieldWidth, int fieldHeight) {
25
+ PVector v = wrappedPlacer.place(word, wordIndex, wordsCount, wordImageWidth, wordImageHeight, fieldWidth, fieldHeight);
26
+ parent.pushStyle();
27
+ parent.noFill();
28
+
29
+ parent.stroke(15, 255, 255, 200);
30
+
31
+ parent.ellipse(v.x, v.y, 10, 10);
32
+ parent.popStyle();
33
+ return v;
34
+ }
35
+
36
+ }
@@ -0,0 +1,42 @@
1
+ package wordcram;
2
+
3
+ import java.awt.Color; // awt: for fill color
4
+ import java.awt.Graphics2D; // awt: draws the word to the screen
5
+ import java.awt.RenderingHints; // awt: for constants while rendering a word
6
+ import java.awt.geom.GeneralPath; // awt: Shape -> Path, fill(path)
7
+
8
+ import processing.core.PGraphics;
9
+ import processing.awt.PGraphicsJava2D;
10
+
11
+ class ProcessingWordRenderer implements WordRenderer {
12
+ PGraphics destination;
13
+
14
+ ProcessingWordRenderer(PGraphics destination) {
15
+ this.destination = destination;
16
+ }
17
+
18
+ @Override
19
+ public int getWidth() {
20
+ return destination.width;
21
+ }
22
+
23
+ @Override
24
+ public int getHeight() {
25
+ return destination.height;
26
+ }
27
+
28
+ @Override
29
+ public void drawWord(EngineWord word, Color color) {
30
+ GeneralPath path2d = new GeneralPath(word.getShape());
31
+
32
+ // Graphics2D g2 = (Graphics2D)destination.image.getGraphics();
33
+ Graphics2D g2 = ((PGraphicsJava2D)destination).g2;
34
+
35
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
36
+ g2.setPaint(color);
37
+ g2.fill(path2d);
38
+ }
39
+
40
+ @Override
41
+ public void finish() {}
42
+ }
@@ -0,0 +1,44 @@
1
+ package wordcram;
2
+
3
+ import java.util.Random;
4
+
5
+ import processing.core.PVector;
6
+
7
+ /**
8
+ * A RandomWordNudger, where each attempt's PVector has X & Y coords
9
+ * distributed randomly around the desired point, multiplied by a standard deviation,
10
+ * and multiplied by the attempt number (so it gets farther, as it gets more
11
+ * desperate).
12
+ *
13
+ * @author Dan Bernier
14
+ */
15
+ public class RandomWordNudger implements WordNudger {
16
+
17
+ private final Random r = new Random();
18
+ private float stdDev;
19
+
20
+ /**
21
+ * Create a RandomWordNudger with a standard deviation of 0.6.
22
+ */
23
+ public RandomWordNudger() {
24
+ this(0.6f);
25
+ }
26
+
27
+ /**
28
+ * Create a RandomWordNudger with your own standard deviation.
29
+ * @param stdDev
30
+ */
31
+ public RandomWordNudger(float stdDev) {
32
+ this.stdDev = stdDev;
33
+ }
34
+
35
+ @Override
36
+ public PVector nudgeFor(Word w, int attempt) {
37
+ return new PVector(next(attempt), next(attempt));
38
+ }
39
+
40
+ private float next(int attempt) {
41
+ return (float)r.nextGaussian() * attempt * stdDev;
42
+ }
43
+
44
+ }
@@ -0,0 +1,10 @@
1
+ package wordcram;
2
+
3
+ class RenderOptions {
4
+ int maxAttemptsToPlaceWord = -1; // default: based on Word weight
5
+ int maxNumberOfWordsToDraw = -1; // default: unlimited
6
+ int minShapeSize = 7;
7
+ int wordPadding = 1;
8
+
9
+ boolean rightToLeft = false;
10
+ }
@@ -0,0 +1,66 @@
1
+ package wordcram;
2
+
3
+ import java.awt.Shape; // awt: passed as arg, turned into Area
4
+ import java.awt.geom.Area; // awt: from Shape, getBounds2D(), contains(box)
5
+ import java.awt.geom.Rectangle2D; // awt: from Area, getMinX() and Y(), getMaxX() and Y()
6
+ import java.util.Random;
7
+ import processing.core.PVector;
8
+
9
+ public class ShapeBasedPlacer implements WordPlacer, WordNudger {
10
+
11
+ Area area;
12
+ float minX;
13
+ float minY;
14
+ float maxX;
15
+ float maxY;
16
+ Random random;
17
+
18
+ public ShapeBasedPlacer(Shape shape) {
19
+ this.area = new Area(shape);
20
+ random = new Random();
21
+ Rectangle2D areaBounds = area.getBounds2D();
22
+ this.minX = (float) areaBounds.getMinX();
23
+ this.minY = (float) areaBounds.getMinY();
24
+ this.maxX = (float) areaBounds.getMaxX();
25
+ this.maxY = (float) areaBounds.getMaxY();
26
+ }
27
+
28
+ @Override
29
+ public PVector place(Word w, int rank, int count, int ww, int wh, int fw,
30
+ int fh) {
31
+
32
+ for (int i = 0; i < 1000; i++) {
33
+ float newX = randomBetween(minX, maxX);
34
+ float newY = randomBetween(minY, maxY);
35
+ if (area.contains(newX, newY, ww, wh)) {
36
+ return new PVector(newX, newY);
37
+ }
38
+ }
39
+
40
+ return new PVector(-1, -1);
41
+ }
42
+
43
+ @Override
44
+ public PVector nudgeFor(Word word, int attempt) {
45
+ PVector target = word.getTargetPlace();
46
+ float wx = target.x;
47
+ float wy = target.y;
48
+ float ww = word.getRenderedWidth();
49
+ float wh = word.getRenderedHeight();
50
+
51
+ for (int i = 0; i < 1000; i++) {
52
+ float newX = randomBetween(minX, maxX);
53
+ float newY = randomBetween(minY, maxY);
54
+
55
+ if (area.contains(newX, newY, ww, wh)) {
56
+ return new PVector(newX - wx, newY - wy);
57
+ }
58
+ }
59
+
60
+ return new PVector(-1, -1);
61
+ }
62
+
63
+ float randomBetween(float a, float b) {
64
+ return a + random.nextFloat() * (b - a);
65
+ }
66
+ }