1 module ithox.qrcode.renderer.image.decorator.finderpattern; 2 3 import ithox.qrcode.renderer.image.decorator.decoratorinterface; 4 import ithox.qrcode.renderer.color.colorinterface; 5 import ithox.qrcode.renderer.color.gray; 6 import ithox.qrcode.encoder.qrcode; 7 import ithox.qrcode.renderer.rendererinterface; 8 9 import std.conv; 10 11 /** 12 * Finder pattern decorator. 13 */ 14 class FinderPattern : DecoratorInterface 15 { 16 17 /** 18 * @var Color\ColorInterface 19 */ 20 protected ColorInterface innerColor; 21 /** 22 * @varColor\ColorInterface 23 */ 24 protected ColorInterface outerColor; 25 /** 26 * Outer position detection pattern. 27 * 28 * @var array 29 */ 30 protected static int[][] outerPositionDetectionPattern = [ 31 [1, 1, 1, 1, 1, 1, 1], 32 [1, 0, 0, 0, 0, 0, 1], 33 [1, 0, 0, 0, 0, 0, 1], 34 [1, 0, 0, 0, 0, 0, 1], 35 [1, 0, 0, 0, 0, 0, 1], 36 [1, 0, 0, 0, 0, 0, 1], 37 [1, 1, 1, 1, 1, 1, 1], 38 ]; 39 /** 40 * Inner position detection pattern. 41 * 42 * @var array 43 */ 44 protected static int[][] innerPositionDetectionPattern = [ 45 [0, 0, 0, 0, 0, 0, 0], 46 [0, 0, 0, 0, 0, 0, 0], 47 [0, 0, 1, 1, 1, 0, 0], 48 [0, 0, 1, 1, 1, 0, 0], 49 [0, 0, 1, 1, 1, 0, 0], 50 [0, 0, 0, 0, 0, 0, 0], 51 [0, 0, 0, 0, 0, 0, 0], 52 ]; 53 /** 54 * Sets outer color. 55 * 56 * @param Color\ColorInterface color 57 * @return FinderPattern 58 */ 59 public FinderPattern setOuterColor(ColorInterface color) 60 { 61 this.outerColor = color; 62 return this; 63 } 64 /** 65 * Gets outer color. 66 * 67 * @return Color\ColorInterface 68 */ 69 public ColorInterface getOuterColor() 70 { 71 if (this.outerColor is null) { 72 this.outerColor = new Gray(100); 73 } 74 return this.outerColor; 75 } 76 /** 77 * Sets inner color. 78 * 79 * @param Color\ColorInterface color 80 * @return FinderPattern 81 */ 82 public FinderPattern setInnerColor(ColorInterface color) 83 { 84 this.innerColor = color; 85 return this; 86 } 87 /** 88 * Gets inner color. 89 * 90 * @return Color\ColorInterface 91 */ 92 public ColorInterface getInnerColor() 93 { 94 if (this.innerColor is null) { 95 this.innerColor = new Gray(0); 96 } 97 return this.innerColor; 98 } 99 /** 100 * preProcess(): defined by DecoratorInterface. 101 * 102 * @see DecoratorInterface::preProcess() 103 * @param QrCode qrCode 104 * @param RendererInterface renderer 105 * @param integer outputWidth 106 * @param integer outputHeight 107 * @param integer leftPadding 108 * @param integer topPadding 109 * @param integer multiple 110 * @return void 111 */ 112 public void preProcess( QrCode qrCode, RendererInterface renderer, int outputWidth, int outputHeight, int leftPadding, int topPadding, int multiple ) 113 { 114 auto matrix = qrCode.matrix(); 115 auto positions = [ 116 [0, 0], 117 [matrix.width() - 7, 0], 118 [0, matrix.height() - 7], 119 ]; 120 foreach ( int y, row;outerPositionDetectionPattern) { 121 foreach ( int x, isSet;row) { 122 foreach ( position; positions) { 123 matrix.set(x + position[0], y + position[1], 0); 124 } 125 } 126 } 127 } 128 /** 129 * postProcess(): defined by DecoratorInterface. 130 * 131 * @see DecoratorInterface::postProcess() 132 * 133 * @param QrCode qrCode 134 * @param RendererInterface renderer 135 * @param integer outputWidth 136 * @param integer outputHeight 137 * @param integer leftPadding 138 * @param integer topPadding 139 * @param integer multiple 140 * @return void 141 */ 142 public void postProcess( QrCode qrCode, RendererInterface renderer, int outputWidth, int outputHeight, int leftPadding, int topPadding, int multiple ) 143 { 144 auto matrix = qrCode.matrix(); 145 auto positions = [ 146 [0, 0], 147 [matrix.width() - 7, 0], 148 [0, matrix.height() - 7], 149 ]; 150 renderer.addColor("finder-outer", this.getOuterColor()); 151 renderer.addColor("finder-inner", this.getInnerColor()); 152 foreach ( y, row;outerPositionDetectionPattern) { 153 foreach ( x,isOuterSet;row) { 154 auto isInnerSet = innerPositionDetectionPattern[y][x]; 155 if (isOuterSet) { 156 foreach ( position;positions) { 157 renderer.drawBlock( 158 to!int(leftPadding + x * multiple + position[0] * multiple), 159 to!int(topPadding + y * multiple + position[1] * multiple), 160 "finder-outer" 161 ); 162 } 163 } 164 if (isInnerSet) { 165 foreach ( position;positions) { 166 renderer.drawBlock( 167 to!int(leftPadding + x * multiple + position[0] * multiple), 168 to!int(topPadding + y * multiple + position[1] * multiple), 169 "finder-inner" 170 ); 171 } 172 } 173 } 174 } 175 } 176 }