comparison dwt/graphics/ImageData.d @ 32:b9226997409c

Ported dwt.graphics.Image*
author Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com>
date Fri, 12 Sep 2008 13:44:30 +0200
parents e831403a80a9
children d8635bb48c7c
comparison
equal deleted inserted replaced
31:9a3047e87f1d 32:b9226997409c
1 /******************************************************************************* 1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 IBM Corporation and others. 2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials 3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0 4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at 5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html 6 * http://www.eclipse.org/legal/epl-v10.html
7 * 7 *
8 * Contributors: 8 * Contributors:
9 * IBM Corporation - initial API and implementation 9 * IBM Corporation - initial API and implementation
10 *
11 * Port to the D programming language:
12 * Frank Benoit <benoit@tionex.de>
13 * Jacob Carlborg <jacob.carlborg@gmail.com>
10 *******************************************************************************/ 14 *******************************************************************************/
11 module dwt.graphics.ImageData; 15 module dwt.graphics.ImageData;
12 16
13 import dwt.dwthelper.utils;
14
15
16 import java.io.InputStream;
17 17
18 import dwt.DWT; 18 import dwt.DWT;
19 import dwt.DWTException; 19 import dwt.DWTException;
20 import dwt.internal.CloneableCompatibility; 20 import dwt.internal.CloneableCompatibility;
21 21
22 public import dwt.dwthelper.InputStream;
23 import dwt.dwthelper.utils;
24 import dwt.graphics.Device;
25 import dwt.graphics.GC;
26 import dwt.graphics.Image;
27 import dwt.graphics.ImageDataLoader;
28 import dwt.graphics.PaletteData;
29 import dwt.graphics.RGB;
30
31
22 /** 32 /**
23 * Instances of this class are device-independent descriptions 33 * Instances of this class are device-independent descriptions
24 * of images. They are typically used as an intermediate format 34 * of images. They are typically used as an intermediate format
25 * between loading from or writing to streams and creating an 35 * between loading from or writing to streams and creating an
26 * <code>Image</code>. 36 * <code>Image</code>.
27 * <p> 37 * <p>
28 * Note that the public fields <code>x</code>, <code>y</code>, 38 * Note that the public fields <code>x</code>, <code>y</code>,
29 * <code>disposalMethod</code> and <code>delayTime</code> are 39 * <code>disposalMethod</code> and <code>delayTime</code> are
30 * typically only used when the image is in a set of images used 40 * typically only used when the image is in a set of images used
31 * for animation. 41 * for animation.
32 * </p> 42 * </p>
33 * 43 *
34 * @see Image 44 * @see Image
35 * @see ImageLoader 45 * @see ImageLoader
46 * @see <a href="http://www.eclipse.org/swt/snippets/#image">ImageData snippets</a>
47 * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ImageAnalyzer</a>
48 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
36 */ 49 */
37 50
38 public final class ImageData : CloneableCompatibility { 51 public final class ImageData : CloneableCompatibility {
39 52
40 /** 53 /**
41 * The width of the image, in pixels. 54 * The width of the image, in pixels.
42 */ 55 */
43 public int width; 56 public int width;
44 57
120 * multiple of this number, it will be padded with zeros until 133 * multiple of this number, it will be padded with zeros until
121 * it is. 134 * it is.
122 * </p> 135 * </p>
123 */ 136 */
124 public int maskPad; 137 public int maskPad;
125 138
126 /** 139 /**
127 * The alpha data of the image. 140 * The alpha data of the image.
128 * <p> 141 * <p>
129 * Every pixel can have an <em>alpha blending</em> value that 142 * Every pixel can have an <em>alpha blending</em> value that
130 * varies from 0, meaning fully transparent, to 255 meaning 143 * varies from 0, meaning fully transparent, to 255 meaning
131 * fully opaque. The number of bytes per scanline is 144 * fully opaque. The number of bytes per scanline is
132 * 'width'. 145 * 'width'.
133 * </p> 146 * </p>
134 */ 147 */
135 public byte[] alphaData; 148 public byte[] alphaData;
136 149
137 /** 150 /**
138 * The global alpha value to be used for every pixel. 151 * The global alpha value to be used for every pixel.
139 * <p> 152 * <p>
140 * If this value is set, the <code>alphaData</code> field 153 * If this value is set, the <code>alphaData</code> field
141 * is ignored and when the image is rendered each pixel 154 * is ignored and when the image is rendered each pixel
147 */ 160 */
148 public int alpha; 161 public int alpha;
149 162
150 /** 163 /**
151 * The type of file from which the image was read. 164 * The type of file from which the image was read.
152 * 165 *
153 * It is expressed as one of the following values: 166 * It is expressed as one of the following values:
154 * <dl> 167 * <dl>
155 * <dt><code>IMAGE_BMP</code></dt> 168 * <dt><code>IMAGE_BMP</code></dt>
156 * <dd>Windows BMP file format, no compression</dd> 169 * <dd>Windows BMP file format, no compression</dd>
157 * <dt><code>IMAGE_BMP_RLE</code></dt> 170 * <dt><code>IMAGE_BMP_RLE</code></dt>
183 public int y; 196 public int y;
184 197
185 /** 198 /**
186 * A description of how to dispose of the current image 199 * A description of how to dispose of the current image
187 * before displaying the next. 200 * before displaying the next.
188 * 201 *
189 * It is expressed as one of the following values: 202 * It is expressed as one of the following values:
190 * <dl> 203 * <dl>
191 * <dt><code>DM_UNSPECIFIED</code></dt> 204 * <dt><code>DM_UNSPECIFIED</code></dt>
192 * <dd>disposal method not specified</dd> 205 * <dd>disposal method not specified</dd>
193 * <dt><code>DM_FILL_NONE</code></dt> 206 * <dt><code>DM_FILL_NONE</code></dt>
209 public int delayTime; 222 public int delayTime;
210 223
211 /** 224 /**
212 * Arbitrary channel width data to 8-bit conversion table. 225 * Arbitrary channel width data to 8-bit conversion table.
213 */ 226 */
214 static final byte[][] ANY_TO_EIGHT = new byte[9][]; 227 private static byte[][] ANY_TO_EIGHT;
215 static { 228 private static byte[] ONE_TO_ONE_MAPPING;
216 for (int b = 0; b < 9; ++b) { 229
217 byte[] data = ANY_TO_EIGHT[b] = new byte[1 << b]; 230 private static bool static_this_completed = false;
218 if (b is 0) continue; 231 private static void static_this() {
219 int inc = 0; 232 if( static_this_completed ) return;
220 for (int bit = 0x10000; (bit >>= b) !is 0;) inc |= bit; 233 synchronized {
221 for (int v = 0, p = 0; v < 0x10000; v+= inc) data[p++] = cast(byte)(v >> 8); 234 if( static_this_completed ) return;
235 ANY_TO_EIGHT = new byte[][](9);
236 for (int b = 0; b < 9; ++b) {
237 byte[] data = ANY_TO_EIGHT[b] = new byte[1 << b];
238 if (b is 0) continue;
239 int inc = 0;
240 for (int bit = 0x10000; (bit >>= b) !is 0;) inc |= bit;
241 for (int v = 0, p = 0; v < 0x10000; v+= inc) data[p++] = cast(byte)(v >> 8);
242 }
243 ONE_TO_ONE_MAPPING = ANY_TO_EIGHT[8];
244 static_this_completed = true;
222 } 245 }
223 } 246 }
224 static final byte[] ONE_TO_ONE_MAPPING = ANY_TO_EIGHT[8];
225 247
226 /** 248 /**
227 * Scaled 8x8 Bayer dither matrix. 249 * Scaled 8x8 Bayer dither matrix.
228 */ 250 */
229 static final int[][] DITHER_MATRIX = { 251 static const int[][] DITHER_MATRIX = [
230 { 0xfc0000, 0x7c0000, 0xdc0000, 0x5c0000, 0xf40000, 0x740000, 0xd40000, 0x540000 }, 252 [ 0xfc0000, 0x7c0000, 0xdc0000, 0x5c0000, 0xf40000, 0x740000, 0xd40000, 0x540000 ],
231 { 0x3c0000, 0xbc0000, 0x1c0000, 0x9c0000, 0x340000, 0xb40000, 0x140000, 0x940000 }, 253 [ 0x3c0000, 0xbc0000, 0x1c0000, 0x9c0000, 0x340000, 0xb40000, 0x140000, 0x940000 ],
232 { 0xcc0000, 0x4c0000, 0xec0000, 0x6c0000, 0xc40000, 0x440000, 0xe40000, 0x640000 }, 254 [ 0xcc0000, 0x4c0000, 0xec0000, 0x6c0000, 0xc40000, 0x440000, 0xe40000, 0x640000 ],
233 { 0x0c0000, 0x8c0000, 0x2c0000, 0xac0000, 0x040000, 0x840000, 0x240000, 0xa40000 }, 255 [ 0x0c0000, 0x8c0000, 0x2c0000, 0xac0000, 0x040000, 0x840000, 0x240000, 0xa40000 ],
234 { 0xf00000, 0x700000, 0xd00000, 0x500000, 0xf80000, 0x780000, 0xd80000, 0x580000 }, 256 [ 0xf00000, 0x700000, 0xd00000, 0x500000, 0xf80000, 0x780000, 0xd80000, 0x580000 ],
235 { 0x300000, 0xb00000, 0x100000, 0x900000, 0x380000, 0xb80000, 0x180000, 0x980000 }, 257 [ 0x300000, 0xb00000, 0x100000, 0x900000, 0x380000, 0xb80000, 0x180000, 0x980000 ],
236 { 0xc00000, 0x400000, 0xe00000, 0x600000, 0xc80000, 0x480000, 0xe80000, 0x680000 }, 258 [ 0xc00000, 0x400000, 0xe00000, 0x600000, 0xc80000, 0x480000, 0xe80000, 0x680000 ],
237 { 0x000000, 0x800000, 0x200000, 0xa00000, 0x080000, 0x880000, 0x280000, 0xa80000 } 259 [ 0x000000, 0x800000, 0x200000, 0xa00000, 0x080000, 0x880000, 0x280000, 0xa80000 ]
238 }; 260 ];
239 261
240 /** 262 /**
241 * Constructs a new, empty ImageData with the given width, height, 263 * Constructs a new, empty ImageData with the given width, height,
242 * depth and palette. The data will be initialized to an (all zero) 264 * depth and palette. The data will be initialized to an (all zero)
243 * array of the appropriate size. 265 * array of the appropriate size.
291 * the image, or if the image has an unsupported type. Application 313 * the image, or if the image has an unsupported type. Application
292 * code is still responsible for closing the input stream. 314 * code is still responsible for closing the input stream.
293 * <p> 315 * <p>
294 * This constructor is provided for convenience when loading a single 316 * This constructor is provided for convenience when loading a single
295 * image only. If the stream contains multiple images, only the first 317 * image only. If the stream contains multiple images, only the first
296 * one will be loaded. To load multiple images, use 318 * one will be loaded. To load multiple images, use
297 * <code>ImageLoader.load()</code>. 319 * <code>ImageLoader.load()</code>.
298 * </p><p> 320 * </p><p>
299 * This constructor may be used to load a resource as follows: 321 * This constructor may be used to load a resource as follows:
300 * </p> 322 * </p>
301 * <pre> 323 * <pre>
357 * specified name. Throws an error if an error occurs loading the 379 * specified name. Throws an error if an error occurs loading the
358 * image, or if the image has an unsupported type. 380 * image, or if the image has an unsupported type.
359 * <p> 381 * <p>
360 * This constructor is provided for convenience when loading a single 382 * This constructor is provided for convenience when loading a single
361 * image only. If the file contains multiple images, only the first 383 * image only. If the file contains multiple images, only the first
362 * one will be loaded. To load multiple images, use 384 * one will be loaded. To load multiple images, use
363 * <code>ImageLoader.load()</code>. 385 * <code>ImageLoader.load()</code>.
364 * </p> 386 * </p>
365 * 387 *
366 * @param filename the name of the file to load the image from (must not be null) 388 * @param filename the name of the file to load the image from (must not be null)
367 * 389 *
399 } 421 }
400 422
401 /** 423 /**
402 * Prevents uninitialized instances from being created outside the package. 424 * Prevents uninitialized instances from being created outside the package.
403 */ 425 */
404 this() { 426 private this() {
405 } 427 }
406 428
407 /** 429 /**
408 * Constructs an image data by giving values for all non-computable fields. 430 * Constructs an image data by giving values for all non-computable fields.
409 * <p> 431 * <p>
414 int width, int height, int depth, PaletteData palette, 436 int width, int height, int depth, PaletteData palette,
415 int scanlinePad, byte[] data, int maskPad, byte[] maskData, 437 int scanlinePad, byte[] data, int maskPad, byte[] maskData,
416 byte[] alphaData, int alpha, int transparentPixel, int type, 438 byte[] alphaData, int alpha, int transparentPixel, int type,
417 int x, int y, int disposalMethod, int delayTime) 439 int x, int y, int disposalMethod, int delayTime)
418 { 440 {
419
420 if (palette is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); 441 if (palette is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
421 if (!(depth is 1 || depth is 2 || depth is 4 || depth is 8 442 if (!(depth is 1 || depth is 2 || depth is 4 || depth is 8
422 || depth is 16 || depth is 24 || depth is 32)) { 443 || depth is 16 || depth is 24 || depth is 32)) {
423 DWT.error(DWT.ERROR_INVALID_ARGUMENT); 444 DWT.error(DWT.ERROR_INVALID_ARGUMENT);
424 } 445 }
427 } 448 }
428 if (scanlinePad is 0) DWT.error (DWT.ERROR_CANNOT_BE_ZERO); 449 if (scanlinePad is 0) DWT.error (DWT.ERROR_CANNOT_BE_ZERO);
429 450
430 int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) 451 int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1))
431 / scanlinePad * scanlinePad; 452 / scanlinePad * scanlinePad;
432 453
433 /* 454 /*
434 * When the image is being loaded from a PNG, we need to use the theoretical minimum 455 * When the image is being loaded from a PNG, we need to use the theoretical minimum
435 * number of bytes per line to check whether there is enough data, because the actual 456 * number of bytes per line to check whether there is enough data, because the actual
436 * number of bytes per line is calculated based on the given depth, which may be larger 457 * number of bytes per line is calculated based on the given depth, which may be larger
437 * than the actual depth of the PNG. 458 * than the actual depth of the PNG.
491 this.y = y; 512 this.y = y;
492 this.disposalMethod = disposalMethod; 513 this.disposalMethod = disposalMethod;
493 this.delayTime = delayTime; 514 this.delayTime = delayTime;
494 } 515 }
495 516
496 /** 517 /**
497 * Invokes internal DWT functionality to create a new instance of 518 * Invokes internal DWT functionality to create a new instance of
498 * this class. 519 * this class.
499 * <p> 520 * <p>
500 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public 521 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
501 * API for <code>ImageData</code>. It is marked public only so that it 522 * API for <code>ImageData</code>. It is marked public only so that it
583 } 604 }
584 605
585 /** 606 /**
586 * Returns the alpha value at offset <code>x</code> in 607 * Returns the alpha value at offset <code>x</code> in
587 * scanline <code>y</code> in the receiver's alpha data. 608 * scanline <code>y</code> in the receiver's alpha data.
609 * The alpha value is between 0 (transparent) and
610 * 255 (opaque).
588 * 611 *
589 * @param x the x coordinate of the pixel to get the alpha value of 612 * @param x the x coordinate of the pixel to get the alpha value of
590 * @param y the y coordinate of the pixel to get the alpha value of 613 * @param y the y coordinate of the pixel to get the alpha value of
591 * @return the alpha value at the given coordinates 614 * @return the alpha value at the given coordinates
592 * 615 *
602 } 625 }
603 626
604 /** 627 /**
605 * Returns <code>getWidth</code> alpha values starting at offset 628 * Returns <code>getWidth</code> alpha values starting at offset
606 * <code>x</code> in scanline <code>y</code> in the receiver's alpha 629 * <code>x</code> in scanline <code>y</code> in the receiver's alpha
607 * data starting at <code>startIndex</code>. 630 * data starting at <code>startIndex</code>. The alpha values
631 * are unsigned, between <code>(byte)0</code> (transparent) and
632 * <code>(byte)255</code> (opaque).
608 * 633 *
609 * @param x the x position of the pixel to begin getting alpha values 634 * @param x the x position of the pixel to begin getting alpha values
610 * @param y the y position of the pixel to begin getting alpha values 635 * @param y the y position of the pixel to begin getting alpha values
611 * @param getWidth the width of the data to get 636 * @param getWidth the width of the data to get
612 * @param alphas the buffer in which to put the alpha values 637 * @param alphas the buffer in which to put the alpha values
691 if ((theByte & mask) is 0) { 716 if ((theByte & mask) is 0) {
692 return 0; 717 return 0;
693 } else { 718 } else {
694 return 1; 719 return 1;
695 } 720 }
721 default:
696 } 722 }
697 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH); 723 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH);
698 return 0; 724 return 0;
699 } 725 }
700 726
839 if (n > 0) theByte = data[index] & 0xFF; 865 if (n > 0) theByte = data[index] & 0xFF;
840 } 866 }
841 } 867 }
842 } 868 }
843 return; 869 return;
870 default:
844 } 871 }
845 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH); 872 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH);
846 } 873 }
847 874
848 /** 875 /**
1033 if (n > 0) theByte = data[index] & 0xFF; 1060 if (n > 0) theByte = data[index] & 0xFF;
1034 } 1061 }
1035 } 1062 }
1036 } 1063 }
1037 return; 1064 return;
1065 default:
1038 } 1066 }
1039 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH); 1067 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH);
1040 } 1068 }
1041 1069
1042 /** 1070 /**
1082 return DWT.TRANSPARENCY_NONE; 1110 return DWT.TRANSPARENCY_NONE;
1083 } 1111 }
1084 1112
1085 /** 1113 /**
1086 * Returns the byte order of the receiver. 1114 * Returns the byte order of the receiver.
1087 * 1115 *
1088 * @return MSB_FIRST or LSB_FIRST 1116 * @return MSB_FIRST or LSB_FIRST
1089 */ 1117 */
1090 int getByteOrder() { 1118 int getByteOrder() {
1091 return depth !is 16 ? MSB_FIRST : LSB_FIRST; 1119 return depth !is 16 ? MSB_FIRST : LSB_FIRST;
1092 } 1120 }
1101 * @param height the height of the new ImageData 1129 * @param height the height of the new ImageData
1102 * @return a scaled copy of the image 1130 * @return a scaled copy of the image
1103 */ 1131 */
1104 public ImageData scaledTo(int width, int height) { 1132 public ImageData scaledTo(int width, int height) {
1105 /* Create a destination image with no data */ 1133 /* Create a destination image with no data */
1106 final bool flipX = (width < 0); 1134 bool flipX = (width < 0);
1107 if (flipX) width = - width; 1135 if (flipX) width = - width;
1108 final bool flipY = (height < 0); 1136 bool flipY = (height < 0);
1109 if (flipY) height = - height; 1137 if (flipY) height = - height;
1110 1138
1111 ImageData dest = new ImageData( 1139 ImageData dest = new ImageData(
1112 width, height, depth, palette, 1140 width, height, depth, palette,
1113 scanlinePad, null, 0, null, 1141 scanlinePad, null, 0, null,
1123 else blit(BLIT_SRC, 1151 else blit(BLIT_SRC,
1124 this.data, this.depth, this.bytesPerLine, this.getByteOrder(), 0, 0, this.width, this.height, null, null, null, 1152 this.data, this.depth, this.bytesPerLine, this.getByteOrder(), 0, 0, this.width, this.height, null, null, null,
1125 ALPHA_OPAQUE, null, 0, 0, 0, 1153 ALPHA_OPAQUE, null, 0, 0, 0,
1126 dest.data, dest.depth, dest.bytesPerLine, dest.getByteOrder(), 0, 0, dest.width, dest.height, null, null, null, 1154 dest.data, dest.depth, dest.bytesPerLine, dest.getByteOrder(), 0, 0, dest.width, dest.height, null, null, null,
1127 flipX, flipY); 1155 flipX, flipY);
1128 1156
1129 /* Scale the image mask or alpha */ 1157 /* Scale the image mask or alpha */
1130 if (maskData !is null) { 1158 if (maskData !is null) {
1131 dest.maskPad = this.maskPad; 1159 dest.maskPad = this.maskPad;
1132 int destBpl = (dest.width + 7) / 8; 1160 int destBpl = (dest.width + 7) / 8;
1133 destBpl = (destBpl + (dest.maskPad - 1)) / dest.maskPad * dest.maskPad; 1161 destBpl = (destBpl + (dest.maskPad - 1)) / dest.maskPad * dest.maskPad;
1153 } 1181 }
1154 1182
1155 /** 1183 /**
1156 * Sets the alpha value at offset <code>x</code> in 1184 * Sets the alpha value at offset <code>x</code> in
1157 * scanline <code>y</code> in the receiver's alpha data. 1185 * scanline <code>y</code> in the receiver's alpha data.
1186 * The alpha value must be between 0 (transparent)
1187 * and 255 (opaque).
1158 * 1188 *
1159 * @param x the x coordinate of the alpha value to set 1189 * @param x the x coordinate of the alpha value to set
1160 * @param y the y coordinate of the alpha value to set 1190 * @param y the y coordinate of the alpha value to set
1161 * @param alpha the value to set the alpha to 1191 * @param alpha the value to set the alpha to
1162 * 1192 *
1165 * </ul> 1195 * </ul>
1166 */ 1196 */
1167 public void setAlpha(int x, int y, int alpha) { 1197 public void setAlpha(int x, int y, int alpha) {
1168 if (x >= width || y >= height || x < 0 || y < 0 || alpha < 0 || alpha > 255) 1198 if (x >= width || y >= height || x < 0 || y < 0 || alpha < 0 || alpha > 255)
1169 DWT.error(DWT.ERROR_INVALID_ARGUMENT); 1199 DWT.error(DWT.ERROR_INVALID_ARGUMENT);
1170 1200
1171 if (alphaData is null) alphaData = new byte[width * height]; 1201 if (alphaData is null) alphaData = new byte[width * height];
1172 alphaData[y * width + x] = cast(byte)alpha; 1202 alphaData[y * width + x] = cast(byte)alpha;
1173 } 1203 }
1174 1204
1175 /** 1205 /**
1176 * Sets the alpha values starting at offset <code>x</code> in 1206 * Sets the alpha values starting at offset <code>x</code> in
1177 * scanline <code>y</code> in the receiver's alpha data to the 1207 * scanline <code>y</code> in the receiver's alpha data to the
1178 * values from the array <code>alphas</code> starting at 1208 * values from the array <code>alphas</code> starting at
1179 * <code>startIndex</code>. 1209 * <code>startIndex</code>. The alpha values must be between
1210 * <code>(byte)0</code> (transparent) and <code>(byte)255</code> (opaque)
1180 * 1211 *
1181 * @param x the x coordinate of the pixel to being setting the alpha values 1212 * @param x the x coordinate of the pixel to being setting the alpha values
1182 * @param y the y coordinate of the pixel to being setting the alpha values 1213 * @param y the y coordinate of the pixel to being setting the alpha values
1183 * @param putWidth the width of the alpha values to set 1214 * @param putWidth the width of the alpha values to set
1184 * @param alphas the alpha values to set 1215 * @param alphas the alpha values to set
1193 */ 1224 */
1194 public void setAlphas(int x, int y, int putWidth, byte[] alphas, int startIndex) { 1225 public void setAlphas(int x, int y, int putWidth, byte[] alphas, int startIndex) {
1195 if (alphas is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); 1226 if (alphas is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
1196 if (putWidth < 0 || x >= width || y >= height || x < 0 || y < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); 1227 if (putWidth < 0 || x >= width || y >= height || x < 0 || y < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
1197 if (putWidth is 0) return; 1228 if (putWidth is 0) return;
1198 1229
1199 if (alphaData is null) alphaData = new byte[width * height]; 1230 if (alphaData is null) alphaData = new byte[width * height];
1200 // may throw an IndexOutOfBoundsException 1231 // may throw an IndexOutOfBoundsException
1201 System.arraycopy(alphas, startIndex, alphaData, y * width + x, putWidth); 1232 System.arraycopy(alphas, startIndex, alphaData, y * width + x, putWidth);
1202 } 1233 }
1203 1234
1267 data[index] = cast(byte)(theByte | mask); 1298 data[index] = cast(byte)(theByte | mask);
1268 } else { 1299 } else {
1269 data[index] = cast(byte)(theByte & (mask ^ -1)); 1300 data[index] = cast(byte)(theByte & (mask ^ -1));
1270 } 1301 }
1271 return; 1302 return;
1303 default:
1272 } 1304 }
1273 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH); 1305 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH);
1274 } 1306 }
1275 1307
1276 /** 1308 /**
1345 high = !high; 1377 high = !high;
1346 } 1378 }
1347 } 1379 }
1348 return; 1380 return;
1349 case 2: 1381 case 2:
1350 byte [] masks = { cast(byte)0xFC, cast(byte)0xF3, cast(byte)0xCF, cast(byte)0x3F }; 1382 byte [] masks = [ cast(byte)0xFC, cast(byte)0xF3, cast(byte)0xCF, cast(byte)0x3F ];
1351 index = (y * bytesPerLine) + (x >> 2); 1383 index = (y * bytesPerLine) + (x >> 2);
1352 int offset = 3 - (x % 4); 1384 int offset = 3 - (x % 4);
1353 while (n > 0) { 1385 while (n > 0) {
1354 theByte = pixels[i] & 0x3; 1386 theByte = pixels[i] & 0x3;
1355 data[index] = cast(byte)((data[index] & masks[offset]) | (theByte << (offset * 2))); 1387 data[index] = cast(byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
1392 index++; 1424 index++;
1393 } 1425 }
1394 } 1426 }
1395 } 1427 }
1396 return; 1428 return;
1429 default:
1397 } 1430 }
1398 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH); 1431 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH);
1399 } 1432 }
1400 1433
1401 /** 1434 /**
1524 high = !high; 1557 high = !high;
1525 } 1558 }
1526 } 1559 }
1527 return; 1560 return;
1528 case 2: 1561 case 2:
1529 byte [] masks = { cast(byte)0xFC, cast(byte)0xF3, cast(byte)0xCF, cast(byte)0x3F }; 1562 byte [] masks = [ cast(byte)0xFC, cast(byte)0xF3, cast(byte)0xCF, cast(byte)0x3F ];
1530 index = (y * bytesPerLine) + (x >> 2); 1563 index = (y * bytesPerLine) + (x >> 2);
1531 int offset = 3 - (x % 4); 1564 int offset = 3 - (x % 4);
1532 while (n > 0) { 1565 while (n > 0) {
1533 theByte = pixels[i] & 0x3; 1566 theByte = pixels[i] & 0x3;
1534 data[index] = cast(byte)((data[index] & masks[offset]) | (theByte << (offset * 2))); 1567 data[index] = cast(byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
1571 index++; 1604 index++;
1572 } 1605 }
1573 } 1606 }
1574 } 1607 }
1575 return; 1608 return;
1609 default:
1576 } 1610 }
1577 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH); 1611 DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH);
1578 } 1612 }
1579 1613
1580 /** 1614 /**
1581 * Returns a palette with 2 colors: black & white. 1615 * Returns a palette with 2 colors: black & white.
1582 */ 1616 */
1583 static PaletteData bwPalette() { 1617 static PaletteData bwPalette() {
1584 return new PaletteData(new RGB[] {new RGB(0, 0, 0), new RGB(255, 255, 255)}); 1618 return new PaletteData( [ new RGB(0, 0, 0), new RGB(255, 255, 255) ] );
1585 } 1619 }
1586 1620
1587 /** 1621 /**
1588 * Gets the offset of the most significant bit for 1622 * Gets the offset of the most significant bit for
1589 * the given mask. 1623 * the given mask.
1625 return nearestPixel; 1659 return nearestPixel;
1626 } 1660 }
1627 1661
1628 static final ImageData convertMask(ImageData mask) { 1662 static final ImageData convertMask(ImageData mask) {
1629 if (mask.depth is 1) return mask; 1663 if (mask.depth is 1) return mask;
1630 PaletteData palette = new PaletteData(new RGB[] {new RGB(0, 0, 0), new RGB(255,255,255)}); 1664 PaletteData palette = new PaletteData([new RGB(0, 0, 0), new RGB(255,255,255)]);
1631 ImageData newMask = new ImageData(mask.width, mask.height, 1, palette); 1665 ImageData newMask = new ImageData(mask.width, mask.height, 1, palette);
1632 /* Find index of black in mask palette */ 1666 /* Find index of black in mask palette */
1633 int blackIndex = 0; 1667 int blackIndex = 0;
1634 RGB[] rgbs = mask.getRGBs(); 1668 RGB[] rgbs = mask.getRGBs();
1635 if (rgbs !is null) { 1669 if (rgbs !is null) {
1636 while (blackIndex < rgbs.length) { 1670 while (blackIndex < rgbs.length) {
1637 if (rgbs[blackIndex].equals(palette.colors[0])) break; 1671 if (rgbs[blackIndex] is palette.colors[0] ) break;
1638 blackIndex++; 1672 blackIndex++;
1639 } 1673 }
1640 } 1674 }
1641 int[] pixels = new int[mask.width]; 1675 int[] pixels = new int[mask.width];
1642 for (int y = 0; y < mask.height; y++) { 1676 for (int y = 0; y < mask.height; y++) {
1654 } 1688 }
1655 1689
1656 static final byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) { 1690 static final byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) {
1657 if (pad is newPad) return data; 1691 if (pad is newPad) return data;
1658 int stride = (width * depth + 7) / 8; 1692 int stride = (width * depth + 7) / 8;
1659 int bpl = (stride + (pad - 1)) / pad * pad; 1693 int bpl = (stride + (pad - 1)) / pad * pad;
1660 int newBpl = (stride + (newPad - 1)) / newPad * newPad; 1694 int newBpl = (stride + (newPad - 1)) / newPad * newPad;
1661 byte[] newData = new byte[height * newBpl]; 1695 byte[] newData = new byte[height * newBpl];
1662 int srcIndex = 0, destIndex = 0; 1696 int srcIndex = 0, destIndex = 0;
1663 for (int y = 0; y < height; y++) { 1697 for (int y = 0; y < height; y++) {
1664 System.arraycopy(data, srcIndex, newData, destIndex, stride); 1698 System.arraycopy(data, srcIndex, newData, destIndex, stride);
1669 } 1703 }
1670 1704
1671 /** 1705 /**
1672 * Blit operation bits to be OR'ed together to specify the desired operation. 1706 * Blit operation bits to be OR'ed together to specify the desired operation.
1673 */ 1707 */
1674 static final int 1708 static const int
1675 BLIT_SRC = 1, // copy source directly, else applies logic operations 1709 BLIT_SRC = 1, // copy source directly, else applies logic operations
1676 BLIT_ALPHA = 2, // enable alpha blending 1710 BLIT_ALPHA = 2, // enable alpha blending
1677 BLIT_DITHER = 4; // enable dithering in low color modes 1711 BLIT_DITHER = 4; // enable dithering in low color modes
1678 1712
1679 /** 1713 /**
1680 * Alpha mode, values 0 - 255 specify global alpha level 1714 * Alpha mode, values 0 - 255 specify global alpha level
1681 */ 1715 */
1682 static final int 1716 static const int
1683 ALPHA_OPAQUE = 255, // Fully opaque (ignores any alpha data) 1717 ALPHA_OPAQUE = 255, // Fully opaque (ignores any alpha data)
1684 ALPHA_TRANSPARENT = 0, // Fully transparent (ignores any alpha data) 1718 ALPHA_TRANSPARENT = 0, // Fully transparent (ignores any alpha data)
1685 ALPHA_CHANNEL_SEPARATE = -1, // Use alpha channel from separate alphaData 1719 ALPHA_CHANNEL_SEPARATE = -1, // Use alpha channel from separate alphaData
1686 ALPHA_CHANNEL_SOURCE = -2, // Use alpha channel embedded in sourceData 1720 ALPHA_CHANNEL_SOURCE = -2, // Use alpha channel embedded in sourceData
1687 ALPHA_MASK_UNPACKED = -3, // Use transparency mask formed by bytes in alphaData (non-zero is opaque) 1721 ALPHA_MASK_UNPACKED = -3, // Use transparency mask formed by bytes in alphaData (non-zero is opaque)
1690 ALPHA_MASK_RGB = -6; // Consider source RGBs transparent if in RGB888 format alphaData array 1724 ALPHA_MASK_RGB = -6; // Consider source RGBs transparent if in RGB888 format alphaData array
1691 1725
1692 /** 1726 /**
1693 * Byte and bit order constants. 1727 * Byte and bit order constants.
1694 */ 1728 */
1695 static final int LSB_FIRST = 0; 1729 static const int LSB_FIRST = 0;
1696 static final int MSB_FIRST = 1; 1730 static const int MSB_FIRST = 1;
1697 1731
1698 /** 1732 /**
1699 * Data types (internal) 1733 * Data types (internal)
1700 */ 1734 */
1701 private static final int 1735 private static const int
1702 // direct / true color formats with arbitrary masks & shifts 1736 // direct / true color formats with arbitrary masks & shifts
1703 TYPE_GENERIC_8 = 0, 1737 TYPE_GENERIC_8 = 0,
1704 TYPE_GENERIC_16_MSB = 1, 1738 TYPE_GENERIC_16_MSB = 1,
1705 TYPE_GENERIC_16_LSB = 2, 1739 TYPE_GENERIC_16_LSB = 2,
1706 TYPE_GENERIC_24 = 3, 1740 TYPE_GENERIC_24 = 3,
1719 * Note: When the source and destination depth, order and masks 1753 * Note: When the source and destination depth, order and masks
1720 * are pairwise equal and the blitter operation is BLIT_SRC, 1754 * are pairwise equal and the blitter operation is BLIT_SRC,
1721 * the masks are ignored. Hence when not changing the image 1755 * the masks are ignored. Hence when not changing the image
1722 * data format, 0 may be specified for the masks. 1756 * data format, 0 may be specified for the masks.
1723 * </p> 1757 * </p>
1724 * 1758 *
1725 * @param op the blitter operation: a combination of BLIT_xxx flags 1759 * @param op the blitter operation: a combination of BLIT_xxx flags
1726 * (see BLIT_xxx constants) 1760 * (see BLIT_xxx constants)
1727 * @param srcData the source byte array containing image data 1761 * @param srcData the source byte array containing image data
1728 * @param srcDepth the source depth: one of 8, 16, 24, 32 1762 * @param srcDepth the source depth: one of 8, 16, 24, 32
1729 * @param srcStride the source number of bytes per line 1763 * @param srcStride the source number of bytes per line
1767 int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY, 1801 int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
1768 byte[] destData, int destDepth, int destStride, int destOrder, 1802 byte[] destData, int destDepth, int destStride, int destOrder,
1769 int destX, int destY, int destWidth, int destHeight, 1803 int destX, int destY, int destWidth, int destHeight,
1770 int destRedMask, int destGreenMask, int destBlueMask, 1804 int destRedMask, int destGreenMask, int destBlueMask,
1771 bool flipX, bool flipY) { 1805 bool flipX, bool flipY) {
1806
1807 static_this();
1808
1772 if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; 1809 if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return;
1773 1810
1774 // these should be supplied as params later 1811 // these should be supplied as params later
1775 final int srcAlphaMask = 0, destAlphaMask = 0; 1812 const int srcAlphaMask = 0, destAlphaMask = 0;
1776 1813
1777 /*** Prepare scaling data ***/ 1814 /*** Prepare scaling data ***/
1778 final int dwm1 = destWidth - 1; 1815 int dwm1 = destWidth - 1;
1779 final int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0; 1816 int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0;
1780 final int dhm1 = destHeight - 1; 1817 int dhm1 = destHeight - 1;
1781 final int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0; 1818 int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0;
1782 1819
1783 /*** Prepare source-related data ***/ 1820 /*** Prepare source-related data ***/
1784 final int sbpp, stype; 1821 int sbpp, stype;
1785 switch (srcDepth) { 1822 switch (srcDepth) {
1786 case 8: 1823 case 8:
1787 sbpp = 1; 1824 sbpp = 1;
1788 stype = TYPE_GENERIC_8; 1825 stype = TYPE_GENERIC_8;
1789 break; 1826 break;
1800 stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; 1837 stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
1801 break; 1838 break;
1802 default: 1839 default:
1803 //throw new IllegalArgumentException("Invalid source type"); 1840 //throw new IllegalArgumentException("Invalid source type");
1804 return; 1841 return;
1805 } 1842 }
1806 int spr = srcY * srcStride + srcX * sbpp; 1843 int spr = srcY * srcStride + srcX * sbpp;
1807 1844
1808 /*** Prepare destination-related data ***/ 1845 /*** Prepare destination-related data ***/
1809 final int dbpp, dtype; 1846 int dbpp, dtype;
1810 switch (destDepth) { 1847 switch (destDepth) {
1811 case 8: 1848 case 8:
1812 dbpp = 1; 1849 dbpp = 1;
1813 dtype = TYPE_GENERIC_8; 1850 dtype = TYPE_GENERIC_8;
1814 break; 1851 break;
1825 dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; 1862 dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
1826 break; 1863 break;
1827 default: 1864 default:
1828 //throw new IllegalArgumentException("Invalid destination type"); 1865 //throw new IllegalArgumentException("Invalid destination type");
1829 return; 1866 return;
1830 } 1867 }
1831 int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp; 1868 int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp;
1832 final int dprxi = (flipX) ? -dbpp : dbpp; 1869 int dprxi = (flipX) ? -dbpp : dbpp;
1833 final int dpryi = (flipY) ? -destStride : destStride; 1870 int dpryi = (flipY) ? -destStride : destStride;
1834 1871
1835 /*** Prepare special processing data ***/ 1872 /*** Prepare special processing data ***/
1836 int apr; 1873 int apr;
1837 if ((op & BLIT_ALPHA) !is 0) { 1874 if ((op & BLIT_ALPHA) !is 0) {
1838 switch (alphaMode) { 1875 switch (alphaMode) {
1877 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { 1914 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
1878 destData[dp] = srcData[sp]; 1915 destData[dp] = srcData[sp];
1879 sp += (sfx >>> 16); 1916 sp += (sfx >>> 16);
1880 } 1917 }
1881 } 1918 }
1882 break; 1919 break;
1883 case 2: 1920 case 2:
1884 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { 1921 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
1885 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { 1922 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
1886 destData[dp] = srcData[sp]; 1923 destData[dp] = srcData[sp];
1887 destData[dp + 1] = srcData[sp + 1]; 1924 destData[dp + 1] = srcData[sp + 1];
1908 destData[dp + 3] = srcData[sp + 3]; 1945 destData[dp + 3] = srcData[sp + 3];
1909 sp += (sfx >>> 16) * 4; 1946 sp += (sfx >>> 16) * 4;
1910 } 1947 }
1911 } 1948 }
1912 break; 1949 break;
1950 default:
1913 } 1951 }
1914 return; 1952 return;
1915 } 1953 }
1916 /*** Comprehensive blit (apply transformations) ***/ 1954 /*** Comprehensive blit (apply transformations) ***/
1917 final int srcRedShift = getChannelShift(srcRedMask); 1955 int srcRedShift = getChannelShift(srcRedMask);
1918 final byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)]; 1956 byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)];
1919 final int srcGreenShift = getChannelShift(srcGreenMask); 1957 int srcGreenShift = getChannelShift(srcGreenMask);
1920 final byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)]; 1958 byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)];
1921 final int srcBlueShift = getChannelShift(srcBlueMask); 1959 int srcBlueShift = getChannelShift(srcBlueMask);
1922 final byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)]; 1960 byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)];
1923 final int srcAlphaShift = getChannelShift(srcAlphaMask); 1961 int srcAlphaShift = getChannelShift(srcAlphaMask);
1924 final byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)]; 1962 byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)];
1925 1963
1926 final int destRedShift = getChannelShift(destRedMask); 1964 int destRedShift = getChannelShift(destRedMask);
1927 final int destRedWidth = getChannelWidth(destRedMask, destRedShift); 1965 int destRedWidth = getChannelWidth(destRedMask, destRedShift);
1928 final byte[] destReds = ANY_TO_EIGHT[destRedWidth]; 1966 byte[] destReds = ANY_TO_EIGHT[destRedWidth];
1929 final int destRedPreShift = 8 - destRedWidth; 1967 int destRedPreShift = 8 - destRedWidth;
1930 final int destGreenShift = getChannelShift(destGreenMask); 1968 int destGreenShift = getChannelShift(destGreenMask);
1931 final int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift); 1969 int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift);
1932 final byte[] destGreens = ANY_TO_EIGHT[destGreenWidth]; 1970 byte[] destGreens = ANY_TO_EIGHT[destGreenWidth];
1933 final int destGreenPreShift = 8 - destGreenWidth; 1971 int destGreenPreShift = 8 - destGreenWidth;
1934 final int destBlueShift = getChannelShift(destBlueMask); 1972 int destBlueShift = getChannelShift(destBlueMask);
1935 final int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift); 1973 int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift);
1936 final byte[] destBlues = ANY_TO_EIGHT[destBlueWidth]; 1974 byte[] destBlues = ANY_TO_EIGHT[destBlueWidth];
1937 final int destBluePreShift = 8 - destBlueWidth; 1975 int destBluePreShift = 8 - destBlueWidth;
1938 final int destAlphaShift = getChannelShift(destAlphaMask); 1976 int destAlphaShift = getChannelShift(destAlphaMask);
1939 final int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift); 1977 int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift);
1940 final byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth]; 1978 byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth];
1941 final int destAlphaPreShift = 8 - destAlphaWidth; 1979 int destAlphaPreShift = 8 - destAlphaWidth;
1942 1980
1943 int ap = apr, alpha = alphaMode; 1981 int ap = apr, alpha = alphaMode;
1944 int r = 0, g = 0, b = 0, a = 0; 1982 int r = 0, g = 0, b = 0, a = 0;
1945 int rq = 0, gq = 0, bq = 0, aq = 0; 1983 int rq = 0, gq = 0, bq = 0, aq = 0;
1946 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, 1984 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy,
1952 dp += dprxi, 1990 dp += dprxi,
1953 sfx = (sfx & 0xffff) + sfxi) { 1991 sfx = (sfx & 0xffff) + sfxi) {
1954 /*** READ NEXT PIXEL ***/ 1992 /*** READ NEXT PIXEL ***/
1955 switch (stype) { 1993 switch (stype) {
1956 case TYPE_GENERIC_8: { 1994 case TYPE_GENERIC_8: {
1957 final int data = srcData[sp] & 0xff; 1995 int data = srcData[sp] & 0xff;
1958 sp += (sfx >>> 16); 1996 sp += (sfx >>> 16);
1959 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 1997 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
1960 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 1998 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
1961 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 1999 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
1962 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 2000 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
1963 } break; 2001 } break;
1964 case TYPE_GENERIC_16_MSB: { 2002 case TYPE_GENERIC_16_MSB: {
1965 final int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff); 2003 int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff);
1966 sp += (sfx >>> 16) * 2; 2004 sp += (sfx >>> 16) * 2;
1967 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 2005 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
1968 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 2006 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
1969 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 2007 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
1970 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 2008 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
1971 } break; 2009 } break;
1972 case TYPE_GENERIC_16_LSB: { 2010 case TYPE_GENERIC_16_LSB: {
1973 final int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff); 2011 int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff);
1974 sp += (sfx >>> 16) * 2; 2012 sp += (sfx >>> 16) * 2;
1975 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 2013 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
1976 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 2014 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
1977 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 2015 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
1978 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 2016 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
1979 } break; 2017 } break;
1980 case TYPE_GENERIC_24: { 2018 case TYPE_GENERIC_24: {
1981 final int data = (( ((srcData[sp] & 0xff) << 8) | 2019 int data = (( ((srcData[sp] & 0xff) << 8) |
1982 (srcData[sp + 1] & 0xff)) << 8) | 2020 (srcData[sp + 1] & 0xff)) << 8) |
1983 (srcData[sp + 2] & 0xff); 2021 (srcData[sp + 2] & 0xff);
1984 sp += (sfx >>> 16) * 3; 2022 sp += (sfx >>> 16) * 3;
1985 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 2023 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
1986 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 2024 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
1987 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 2025 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
1988 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 2026 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
1989 } break; 2027 } break;
1990 case TYPE_GENERIC_32_MSB: { 2028 case TYPE_GENERIC_32_MSB: {
1991 final int data = (( (( ((srcData[sp] & 0xff) << 8) | 2029 int data = (( (( ((srcData[sp] & 0xff) << 8) |
1992 (srcData[sp + 1] & 0xff)) << 8) | 2030 (srcData[sp + 1] & 0xff)) << 8) |
1993 (srcData[sp + 2] & 0xff)) << 8) | 2031 (srcData[sp + 2] & 0xff)) << 8) |
1994 (srcData[sp + 3] & 0xff); 2032 (srcData[sp + 3] & 0xff);
1995 sp += (sfx >>> 16) * 4; 2033 sp += (sfx >>> 16) * 4;
1996 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 2034 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
1997 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 2035 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
1998 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 2036 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
1999 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 2037 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
2000 } break; 2038 } break;
2001 case TYPE_GENERIC_32_LSB: { 2039 case TYPE_GENERIC_32_LSB: {
2002 final int data = (( (( ((srcData[sp + 3] & 0xff) << 8) | 2040 int data = (( (( ((srcData[sp + 3] & 0xff) << 8) |
2003 (srcData[sp + 2] & 0xff)) << 8) | 2041 (srcData[sp + 2] & 0xff)) << 8) |
2004 (srcData[sp + 1] & 0xff)) << 8) | 2042 (srcData[sp + 1] & 0xff)) << 8) |
2005 (srcData[sp] & 0xff); 2043 (srcData[sp] & 0xff);
2006 sp += (sfx >>> 16) * 4; 2044 sp += (sfx >>> 16) * 4;
2007 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 2045 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
2008 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 2046 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
2009 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 2047 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
2010 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 2048 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
2011 } break; 2049 } break;
2050 default:
2012 } 2051 }
2013 2052
2014 /*** DO SPECIAL PROCESSING IF REQUIRED ***/ 2053 /*** DO SPECIAL PROCESSING IF REQUIRED ***/
2015 switch (alphaMode) { 2054 switch (alphaMode) {
2016 case ALPHA_CHANNEL_SEPARATE: 2055 case ALPHA_CHANNEL_SEPARATE:
2021 alpha = (a << 16) / 255; 2060 alpha = (a << 16) / 255;
2022 break; 2061 break;
2023 case ALPHA_MASK_UNPACKED: 2062 case ALPHA_MASK_UNPACKED:
2024 alpha = (alphaData[ap] !is 0) ? 0x10000 : 0; 2063 alpha = (alphaData[ap] !is 0) ? 0x10000 : 0;
2025 ap += (sfx >> 16); 2064 ap += (sfx >> 16);
2026 break; 2065 break;
2027 case ALPHA_MASK_PACKED: 2066 case ALPHA_MASK_PACKED:
2028 alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000; 2067 alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
2029 ap += (sfx >> 16); 2068 ap += (sfx >> 16);
2030 break; 2069 break;
2031 case ALPHA_MASK_RGB: 2070 case ALPHA_MASK_RGB:
2035 alpha = 0x0000; 2074 alpha = 0x0000;
2036 break; 2075 break;
2037 } 2076 }
2038 } 2077 }
2039 break; 2078 break;
2079 default:
2040 } 2080 }
2041 if (alpha !is 0x10000) { 2081 if (alpha !is 0x10000) {
2042 if (alpha is 0x0000) continue; 2082 if (alpha is 0x0000) continue;
2043 switch (dtype) { 2083 switch (dtype) {
2044 case TYPE_GENERIC_8: { 2084 case TYPE_GENERIC_8: {
2045 final int data = destData[dp] & 0xff; 2085 int data = destData[dp] & 0xff;
2046 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2086 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2047 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2087 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2048 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2088 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2049 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2089 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2050 } break; 2090 } break;
2051 case TYPE_GENERIC_16_MSB: { 2091 case TYPE_GENERIC_16_MSB: {
2052 final int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff); 2092 int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff);
2053 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2093 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2054 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2094 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2055 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2095 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2056 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2096 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2057 } break; 2097 } break;
2058 case TYPE_GENERIC_16_LSB: { 2098 case TYPE_GENERIC_16_LSB: {
2059 final int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff); 2099 int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff);
2060 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2100 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2061 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2101 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2062 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2102 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2063 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2103 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2064 } break; 2104 } break;
2065 case TYPE_GENERIC_24: { 2105 case TYPE_GENERIC_24: {
2066 final int data = (( ((destData[dp] & 0xff) << 8) | 2106 int data = (( ((destData[dp] & 0xff) << 8) |
2067 (destData[dp + 1] & 0xff)) << 8) | 2107 (destData[dp + 1] & 0xff)) << 8) |
2068 (destData[dp + 2] & 0xff); 2108 (destData[dp + 2] & 0xff);
2069 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2109 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2070 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2110 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2071 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2111 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2072 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2112 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2073 } break; 2113 } break;
2074 case TYPE_GENERIC_32_MSB: { 2114 case TYPE_GENERIC_32_MSB: {
2075 final int data = (( (( ((destData[dp] & 0xff) << 8) | 2115 int data = (( (( ((destData[dp] & 0xff) << 8) |
2076 (destData[dp + 1] & 0xff)) << 8) | 2116 (destData[dp + 1] & 0xff)) << 8) |
2077 (destData[dp + 2] & 0xff)) << 8) | 2117 (destData[dp + 2] & 0xff)) << 8) |
2078 (destData[dp + 3] & 0xff); 2118 (destData[dp + 3] & 0xff);
2079 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2119 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2080 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2120 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2081 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2121 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2082 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2122 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2083 } break; 2123 } break;
2084 case TYPE_GENERIC_32_LSB: { 2124 case TYPE_GENERIC_32_LSB: {
2085 final int data = (( (( ((destData[dp + 3] & 0xff) << 8) | 2125 int data = (( (( ((destData[dp + 3] & 0xff) << 8) |
2086 (destData[dp + 2] & 0xff)) << 8) | 2126 (destData[dp + 2] & 0xff)) << 8) |
2087 (destData[dp + 1] & 0xff)) << 8) | 2127 (destData[dp + 1] & 0xff)) << 8) |
2088 (destData[dp] & 0xff); 2128 (destData[dp] & 0xff);
2089 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2129 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2090 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2130 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2091 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2131 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2092 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2132 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2093 } break; 2133 } break;
2134 default:
2094 } 2135 }
2095 // Perform alpha blending 2136 // Perform alpha blending
2096 a = aq + ((a - aq) * alpha >> 16); 2137 a = aq + ((a - aq) * alpha >> 16);
2097 r = rq + ((r - rq) * alpha >> 16); 2138 r = rq + ((r - rq) * alpha >> 16);
2098 g = gq + ((g - gq) * alpha >> 16); 2139 g = gq + ((g - gq) * alpha >> 16);
2099 b = bq + ((b - bq) * alpha >> 16); 2140 b = bq + ((b - bq) * alpha >> 16);
2100 } 2141 }
2101 2142
2102 /*** WRITE NEXT PIXEL ***/ 2143 /*** WRITE NEXT PIXEL ***/
2103 final int data = 2144 int data =
2104 (r >>> destRedPreShift << destRedShift) | 2145 (r >>> destRedPreShift << destRedShift) |
2105 (g >>> destGreenPreShift << destGreenShift) | 2146 (g >>> destGreenPreShift << destGreenShift) |
2106 (b >>> destBluePreShift << destBlueShift) | 2147 (b >>> destBluePreShift << destBlueShift) |
2107 (a >>> destAlphaPreShift << destAlphaShift); 2148 (a >>> destAlphaPreShift << destAlphaShift);
2108 switch (dtype) { 2149 switch (dtype) {
2132 destData[dp] = cast(byte) (data & 0xff); 2173 destData[dp] = cast(byte) (data & 0xff);
2133 destData[dp + 1] = cast(byte) (data >>> 8); 2174 destData[dp + 1] = cast(byte) (data >>> 8);
2134 destData[dp + 2] = cast(byte) (data >>> 16); 2175 destData[dp + 2] = cast(byte) (data >>> 16);
2135 destData[dp + 3] = cast(byte) (data >>> 24); 2176 destData[dp + 3] = cast(byte) (data >>> 24);
2136 } break; 2177 } break;
2178 default:
2137 } 2179 }
2138 } 2180 }
2139 } 2181 }
2140 } 2182 }
2141 2183
2142 /** 2184 /**
2143 * Blits an index palette image into an index palette image. 2185 * Blits an index palette image into an index palette image.
2144 * <p> 2186 * <p>
2145 * Note: The source and destination red, green, and blue 2187 * Note: The source and destination red, green, and blue
2146 * arrays may be null if no alpha blending or dither is to be 2188 * arrays may be null if no alpha blending or dither is to be
2147 * performed. 2189 * performed.
2148 * </p> 2190 * </p>
2149 * 2191 *
2150 * @param op the blitter operation: a combination of BLIT_xxx flags 2192 * @param op the blitter operation: a combination of BLIT_xxx flags
2151 * (see BLIT_xxx constants) 2193 * (see BLIT_xxx constants)
2152 * @param srcData the source byte array containing image data 2194 * @param srcData the source byte array containing image data
2153 * @param srcDepth the source depth: one of 1, 2, 4, 8 2195 * @param srcDepth the source depth: one of 1, 2, 4, 8
2154 * @param srcStride the source number of bytes per line 2196 * @param srcStride the source number of bytes per line
2192 int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY, 2234 int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
2193 byte[] destData, int destDepth, int destStride, int destOrder, 2235 byte[] destData, int destDepth, int destStride, int destOrder,
2194 int destX, int destY, int destWidth, int destHeight, 2236 int destX, int destY, int destWidth, int destHeight,
2195 byte[] destReds, byte[] destGreens, byte[] destBlues, 2237 byte[] destReds, byte[] destGreens, byte[] destBlues,
2196 bool flipX, bool flipY) { 2238 bool flipX, bool flipY) {
2239
2240 static_this();
2241
2197 if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; 2242 if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return;
2198 2243
2199 /*** Prepare scaling data ***/ 2244 /*** Prepare scaling data ***/
2200 final int dwm1 = destWidth - 1; 2245 int dwm1 = destWidth - 1;
2201 final int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0; 2246 int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0;
2202 final int dhm1 = destHeight - 1; 2247 int dhm1 = destHeight - 1;
2203 final int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0; 2248 int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0;
2204 2249
2205 /*** Prepare source-related data ***/ 2250 /*** Prepare source-related data ***/
2206 final int stype; 2251 int stype;
2207 switch (srcDepth) { 2252 switch (srcDepth) {
2208 case 8: 2253 case 8:
2209 stype = TYPE_INDEX_8; 2254 stype = TYPE_INDEX_8;
2210 break; 2255 break;
2211 case 4: 2256 case 4:
2220 srcStride <<= 3; 2265 srcStride <<= 3;
2221 stype = (srcOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; 2266 stype = (srcOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
2222 break; 2267 break;
2223 default: 2268 default:
2224 //throw new IllegalArgumentException("Invalid source type"); 2269 //throw new IllegalArgumentException("Invalid source type");
2225 return; 2270 return;
2226 } 2271 }
2227 int spr = srcY * srcStride + srcX; 2272 int spr = srcY * srcStride + srcX;
2228 2273
2229 /*** Prepare destination-related data ***/ 2274 /*** Prepare destination-related data ***/
2230 final int dtype; 2275 int dtype;
2231 switch (destDepth) { 2276 switch (destDepth) {
2232 case 8: 2277 case 8:
2233 dtype = TYPE_INDEX_8; 2278 dtype = TYPE_INDEX_8;
2234 break; 2279 break;
2235 case 4: 2280 case 4:
2245 dtype = (destOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; 2290 dtype = (destOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
2246 break; 2291 break;
2247 default: 2292 default:
2248 //throw new IllegalArgumentException("Invalid source type"); 2293 //throw new IllegalArgumentException("Invalid source type");
2249 return; 2294 return;
2250 } 2295 }
2251 int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX); 2296 int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX);
2252 final int dprxi = (flipX) ? -1 : 1; 2297 int dprxi = (flipX) ? -1 : 1;
2253 final int dpryi = (flipY) ? -destStride : destStride; 2298 int dpryi = (flipY) ? -destStride : destStride;
2254 2299
2255 /*** Prepare special processing data ***/ 2300 /*** Prepare special processing data ***/
2256 int apr; 2301 int apr;
2257 if ((op & BLIT_ALPHA) !is 0) { 2302 if ((op & BLIT_ALPHA) !is 0) {
2258 switch (alphaMode) { 2303 switch (alphaMode) {
2279 } 2324 }
2280 } else { 2325 } else {
2281 alphaMode = 0x10000; 2326 alphaMode = 0x10000;
2282 apr = 0; 2327 apr = 0;
2283 } 2328 }
2284 final bool ditherEnabled = (op & BLIT_DITHER) !is 0; 2329 bool ditherEnabled = (op & BLIT_DITHER) !is 0;
2285 2330
2286 /*** Blit ***/ 2331 /*** Blit ***/
2287 int dp = dpr; 2332 int dp = dpr;
2288 int sp = spr; 2333 int sp = spr;
2289 int ap = apr; 2334 int ap = apr;
2336 } 2381 }
2337 paletteMapping[i] = cast(byte)index; 2382 paletteMapping[i] = cast(byte)index;
2338 if (minDistance !is 0) isExactPaletteMapping = false; 2383 if (minDistance !is 0) isExactPaletteMapping = false;
2339 } 2384 }
2340 break; 2385 break;
2386 default:
2341 } 2387 }
2342 if ((paletteMapping !is null) && (isExactPaletteMapping || ! ditherEnabled)) { 2388 if ((paletteMapping !is null) && (isExactPaletteMapping || ! ditherEnabled)) {
2343 if ((stype is dtype) && (alphaMode is 0x10000)) { 2389 if ((stype is dtype) && (alphaMode is 0x10000)) {
2344 /*** Fast blit (copy w/ mapping) ***/ 2390 /*** Fast blit (copy w/ mapping) ***/
2345 switch (stype) { 2391 switch (stype) {
2348 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { 2394 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
2349 destData[dp] = paletteMapping[srcData[sp] & 0xff]; 2395 destData[dp] = paletteMapping[srcData[sp] & 0xff];
2350 sp += (sfx >>> 16); 2396 sp += (sfx >>> 16);
2351 } 2397 }
2352 } 2398 }
2353 break; 2399 break;
2354 case TYPE_INDEX_4: 2400 case TYPE_INDEX_4:
2355 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { 2401 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
2356 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { 2402 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
2357 final int v; 2403 int v;
2358 if ((sp & 1) !is 0) v = paletteMapping[srcData[sp >> 1] & 0x0f]; 2404 if ((sp & 1) !is 0) v = paletteMapping[srcData[sp >> 1] & 0x0f];
2359 else v = (srcData[sp >> 1] >>> 4) & 0x0f; 2405 else v = (srcData[sp >> 1] >>> 4) & 0x0f;
2360 sp += (sfx >>> 16); 2406 sp += (sfx >>> 16);
2361 if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | v); 2407 if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | v);
2362 else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (v << 4)); 2408 else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (v << 4));
2364 } 2410 }
2365 break; 2411 break;
2366 case TYPE_INDEX_2: 2412 case TYPE_INDEX_2:
2367 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { 2413 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
2368 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { 2414 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
2369 final int index = paletteMapping[(srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03]; 2415 int index = paletteMapping[(srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03];
2370 sp += (sfx >>> 16); 2416 sp += (sfx >>> 16);
2371 final int shift = 6 - (dp & 3) * 2; 2417 int shift = 6 - (dp & 3) * 2;
2372 destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift)); 2418 destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift));
2373 } 2419 }
2374 } 2420 }
2375 break; 2421 break;
2376 case TYPE_INDEX_1_MSB: 2422 case TYPE_INDEX_1_MSB:
2377 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) { 2423 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
2378 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) { 2424 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
2379 final int index = paletteMapping[(srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01]; 2425 int index = paletteMapping[(srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01];
2380 sp += (sfx >>> 16); 2426 sp += (sfx >>> 16);
2381 final int shift = 7 - (dp & 7); 2427 int shift = 7 - (dp & 7);
2382 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
2383 }
2384 }
2385 break;
2386 case TYPE_INDEX_1_LSB:
2387 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
2388 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
2389 final int index = paletteMapping[(srcData[sp >> 3] >>> (sp & 7)) & 0x01];
2390 sp += (sfx >>> 16);
2391 final int shift = dp & 7;
2392 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); 2428 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
2393 } 2429 }
2394 } 2430 }
2395 break; 2431 break;
2432 case TYPE_INDEX_1_LSB:
2433 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
2434 for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
2435 int index = paletteMapping[(srcData[sp >> 3] >>> (sp & 7)) & 0x01];
2436 sp += (sfx >>> 16);
2437 int shift = dp & 7;
2438 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
2439 }
2440 }
2441 break;
2442 default:
2396 } 2443 }
2397 } else { 2444 } else {
2398 /*** Convert between indexed modes using mapping and mask ***/ 2445 /*** Convert between indexed modes using mapping and mask ***/
2399 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, 2446 for (int dy = destHeight, sfy = sfyi; dy > 0; --dy,
2400 sp = spr += (sfy >>> 16) * srcStride, 2447 sp = spr += (sfy >>> 16) * srcStride,
2407 /*** READ NEXT PIXEL ***/ 2454 /*** READ NEXT PIXEL ***/
2408 switch (stype) { 2455 switch (stype) {
2409 case TYPE_INDEX_8: 2456 case TYPE_INDEX_8:
2410 index = srcData[sp] & 0xff; 2457 index = srcData[sp] & 0xff;
2411 sp += (sfx >>> 16); 2458 sp += (sfx >>> 16);
2412 break; 2459 break;
2413 case TYPE_INDEX_4: 2460 case TYPE_INDEX_4:
2414 if ((sp & 1) !is 0) index = srcData[sp >> 1] & 0x0f; 2461 if ((sp & 1) !is 0) index = srcData[sp >> 1] & 0x0f;
2415 else index = (srcData[sp >> 1] >>> 4) & 0x0f; 2462 else index = (srcData[sp >> 1] >>> 4) & 0x0f;
2416 sp += (sfx >>> 16); 2463 sp += (sfx >>> 16);
2417 break; 2464 break;
2418 case TYPE_INDEX_2: 2465 case TYPE_INDEX_2:
2419 index = (srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03; 2466 index = (srcData[sp >> 2] >>> (6 - (sp & 3) * 2)) & 0x03;
2420 sp += (sfx >>> 16); 2467 sp += (sfx >>> 16);
2421 break; 2468 break;
2422 case TYPE_INDEX_1_MSB: 2469 case TYPE_INDEX_1_MSB:
2423 index = (srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01; 2470 index = (srcData[sp >> 3] >>> (7 - (sp & 7))) & 0x01;
2424 sp += (sfx >>> 16); 2471 sp += (sfx >>> 16);
2425 break; 2472 break;
2426 case TYPE_INDEX_1_LSB: 2473 case TYPE_INDEX_1_LSB:
2427 index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01; 2474 index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01;
2428 sp += (sfx >>> 16); 2475 sp += (sfx >>> 16);
2429 break; 2476 break;
2430 default: 2477 default:
2431 return; 2478 return;
2432 } 2479 }
2433 /*** APPLY MASK ***/ 2480 /*** APPLY MASK ***/
2434 switch (alphaMode) { 2481 switch (alphaMode) {
2435 case ALPHA_MASK_UNPACKED: { 2482 case ALPHA_MASK_UNPACKED: {
2436 final byte mask = alphaData[ap]; 2483 byte mask = alphaData[ap];
2437 ap += (sfx >> 16); 2484 ap += (sfx >> 16);
2438 if (mask is 0) continue; 2485 if (mask is 0) continue;
2439 } break; 2486 } break;
2440 case ALPHA_MASK_PACKED: { 2487 case ALPHA_MASK_PACKED: {
2441 final int mask = alphaData[ap >> 3] & (1 << (ap & 7)); 2488 int mask = alphaData[ap >> 3] & (1 << (ap & 7));
2442 ap += (sfx >> 16); 2489 ap += (sfx >> 16);
2443 if (mask is 0) continue; 2490 if (mask is 0) continue;
2444 } break; 2491 } break;
2445 case ALPHA_MASK_INDEX: { 2492 case ALPHA_MASK_INDEX: {
2446 int i = 0; 2493 int i = 0;
2448 if (index is (alphaData[i] & 0xff)) break; 2495 if (index is (alphaData[i] & 0xff)) break;
2449 } 2496 }
2450 if (i < alphaData.length) continue; 2497 if (i < alphaData.length) continue;
2451 } break; 2498 } break;
2452 case ALPHA_MASK_RGB: { 2499 case ALPHA_MASK_RGB: {
2453 final byte r = srcReds[index], g = srcGreens[index], b = srcBlues[index]; 2500 byte r = srcReds[index], g = srcGreens[index], b = srcBlues[index];
2454 int i = 0; 2501 int i = 0;
2455 while (i < alphaData.length) { 2502 while (i < alphaData.length) {
2456 if ((r is alphaData[i]) && (g is alphaData[i + 1]) && (b is alphaData[i + 2])) break; 2503 if ((r is alphaData[i]) && (g is alphaData[i + 1]) && (b is alphaData[i + 2])) break;
2457 i += 3; 2504 i += 3;
2458 } 2505 }
2459 if (i < alphaData.length) continue; 2506 if (i < alphaData.length) continue;
2460 } break; 2507 } break;
2508 default:
2461 } 2509 }
2462 index = paletteMapping[index] & 0xff; 2510 index = paletteMapping[index] & 0xff;
2463 2511
2464 /*** WRITE NEXT PIXEL ***/ 2512 /*** WRITE NEXT PIXEL ***/
2465 switch (dtype) { 2513 switch (dtype) {
2466 case TYPE_INDEX_8: 2514 case TYPE_INDEX_8:
2467 destData[dp] = cast(byte) index; 2515 destData[dp] = cast(byte) index;
2468 break; 2516 break;
2469 case TYPE_INDEX_4: 2517 case TYPE_INDEX_4:
2470 if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | index); 2518 if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | index);
2471 else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (index << 4)); 2519 else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (index << 4));
2472 break; 2520 break;
2473 case TYPE_INDEX_2: { 2521 case TYPE_INDEX_2: {
2474 final int shift = 6 - (dp & 3) * 2; 2522 int shift = 6 - (dp & 3) * 2;
2475 destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift)); 2523 destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (index << shift));
2476 } break; 2524 } break;
2477 case TYPE_INDEX_1_MSB: { 2525 case TYPE_INDEX_1_MSB: {
2478 final int shift = 7 - (dp & 7); 2526 int shift = 7 - (dp & 7);
2479 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); 2527 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
2480 } break; 2528 } break;
2481 case TYPE_INDEX_1_LSB: { 2529 case TYPE_INDEX_1_LSB: {
2482 final int shift = dp & 7; 2530 int shift = dp & 7;
2483 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift)); 2531 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (index << shift));
2484 } break; 2532 } break;
2533 default:
2485 } 2534 }
2486 } 2535 }
2487 } 2536 }
2488 } 2537 }
2489 return; 2538 return;
2490 } 2539 }
2491 2540
2492 /*** Comprehensive blit (apply transformations) ***/ 2541 /*** Comprehensive blit (apply transformations) ***/
2493 int alpha = alphaMode; 2542 int alpha = alphaMode;
2494 int index = 0; 2543 int index = 0;
2495 int indexq = 0; 2544 int indexq = 0;
2496 int lastindex = 0, lastr = -1, lastg = -1, lastb = -1; 2545 int lastindex = 0, lastr = -1, lastg = -1, lastb = -1;
2497 final int[] rerr, gerr, berr; 2546 int[] rerr, gerr, berr;
2498 if (ditherEnabled) { 2547 if (ditherEnabled) {
2499 rerr = new int[destWidth + 2]; 2548 rerr = new int[destWidth + 2];
2500 gerr = new int[destWidth + 2]; 2549 gerr = new int[destWidth + 2];
2501 berr = new int[destWidth + 2]; 2550 berr = new int[destWidth + 2];
2502 } else { 2551 } else {
2532 break; 2581 break;
2533 case TYPE_INDEX_1_LSB: 2582 case TYPE_INDEX_1_LSB:
2534 index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01; 2583 index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01;
2535 sp += (sfx >>> 16); 2584 sp += (sfx >>> 16);
2536 break; 2585 break;
2586 default:
2537 } 2587 }
2538 2588
2539 /*** DO SPECIAL PROCESSING IF REQUIRED ***/ 2589 /*** DO SPECIAL PROCESSING IF REQUIRED ***/
2540 int r = srcReds[index] & 0xff, g = srcGreens[index] & 0xff, b = srcBlues[index] & 0xff; 2590 int r = srcReds[index] & 0xff, g = srcGreens[index] & 0xff, b = srcBlues[index] & 0xff;
2541 switch (alphaMode) { 2591 switch (alphaMode) {
2544 ap += (sfx >> 16); 2594 ap += (sfx >> 16);
2545 break; 2595 break;
2546 case ALPHA_MASK_UNPACKED: 2596 case ALPHA_MASK_UNPACKED:
2547 alpha = (alphaData[ap] !is 0) ? 0x10000 : 0; 2597 alpha = (alphaData[ap] !is 0) ? 0x10000 : 0;
2548 ap += (sfx >> 16); 2598 ap += (sfx >> 16);
2549 break; 2599 break;
2550 case ALPHA_MASK_PACKED: 2600 case ALPHA_MASK_PACKED:
2551 alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000; 2601 alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
2552 ap += (sfx >> 16); 2602 ap += (sfx >> 16);
2553 break; 2603 break;
2554 case ALPHA_MASK_INDEX: { // could speed up using binary search if we sorted the indices 2604 case ALPHA_MASK_INDEX: { // could speed up using binary search if we sorted the indices
2566 (b is (alphaData[i + 2] & 0xff))) break; 2616 (b is (alphaData[i + 2] & 0xff))) break;
2567 i += 3; 2617 i += 3;
2568 } 2618 }
2569 if (i < alphaData.length) continue; 2619 if (i < alphaData.length) continue;
2570 } break; 2620 } break;
2621 default:
2571 } 2622 }
2572 if (alpha !is 0x10000) { 2623 if (alpha !is 0x10000) {
2573 if (alpha is 0x0000) continue; 2624 if (alpha is 0x0000) continue;
2574 switch (dtype) { 2625 switch (dtype) {
2575 case TYPE_INDEX_8: 2626 case TYPE_INDEX_8:
2586 indexq = (destData[dp >> 3] >>> (7 - (dp & 7))) & 0x01; 2637 indexq = (destData[dp >> 3] >>> (7 - (dp & 7))) & 0x01;
2587 break; 2638 break;
2588 case TYPE_INDEX_1_LSB: 2639 case TYPE_INDEX_1_LSB:
2589 indexq = (destData[dp >> 3] >>> (dp & 7)) & 0x01; 2640 indexq = (destData[dp >> 3] >>> (dp & 7)) & 0x01;
2590 break; 2641 break;
2642 default:
2591 } 2643 }
2592 // Perform alpha blending 2644 // Perform alpha blending
2593 final int rq = destReds[indexq] & 0xff; 2645 int rq = destReds[indexq] & 0xff;
2594 final int gq = destGreens[indexq] & 0xff; 2646 int gq = destGreens[indexq] & 0xff;
2595 final int bq = destBlues[indexq] & 0xff; 2647 int bq = destBlues[indexq] & 0xff;
2596 r = rq + ((r - rq) * alpha >> 16); 2648 r = rq + ((r - rq) * alpha >> 16);
2597 g = gq + ((g - gq) * alpha >> 16); 2649 g = gq + ((g - gq) * alpha >> 16);
2598 b = bq + ((b - bq) * alpha >> 16); 2650 b = bq + ((b - bq) * alpha >> 16);
2599 } 2651 }
2600 2652
2626 } 2678 }
2627 lastr = r; lastg = g; lastb = b; 2679 lastr = r; lastg = g; lastb = b;
2628 } 2680 }
2629 if (ditherEnabled) { 2681 if (ditherEnabled) {
2630 // Floyd-Steinberg error diffusion, cont'd... 2682 // Floyd-Steinberg error diffusion, cont'd...
2631 final int dxm1 = dx - 1, dxp1 = dx + 1; 2683 int dxm1 = dx - 1, dxp1 = dx + 1;
2632 int acc; 2684 int acc;
2633 rerr[dxp1] += acc = (lrerr = r - (destReds[lastindex] & 0xff)) + lrerr + lrerr; 2685 rerr[dxp1] += acc = (lrerr = r - (destReds[lastindex] & 0xff)) + lrerr + lrerr;
2634 rerr[dx] += acc += lrerr + lrerr; 2686 rerr[dx] += acc += lrerr + lrerr;
2635 rerr[dxm1] += acc + lrerr + lrerr; 2687 rerr[dxm1] += acc + lrerr + lrerr;
2636 gerr[dxp1] += acc = (lgerr = g - (destGreens[lastindex] & 0xff)) + lgerr + lgerr; 2688 gerr[dxp1] += acc = (lgerr = g - (destGreens[lastindex] & 0xff)) + lgerr + lgerr;
2649 case TYPE_INDEX_4: 2701 case TYPE_INDEX_4:
2650 if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | lastindex); 2702 if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | lastindex);
2651 else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4)); 2703 else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4));
2652 break; 2704 break;
2653 case TYPE_INDEX_2: { 2705 case TYPE_INDEX_2: {
2654 final int shift = 6 - (dp & 3) * 2; 2706 int shift = 6 - (dp & 3) * 2;
2655 destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift)); 2707 destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift));
2656 } break; 2708 } break;
2657 case TYPE_INDEX_1_MSB: { 2709 case TYPE_INDEX_1_MSB: {
2658 final int shift = 7 - (dp & 7); 2710 int shift = 7 - (dp & 7);
2659 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); 2711 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
2660 } break; 2712 } break;
2661 case TYPE_INDEX_1_LSB: { 2713 case TYPE_INDEX_1_LSB: {
2662 final int shift = dp & 7; 2714 int shift = dp & 7;
2663 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); 2715 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
2664 } break; 2716 } break;
2717 default:
2665 } 2718 }
2666 } 2719 }
2667 } 2720 }
2668 } 2721 }
2669 2722
2671 * Blits an index palette image into a direct palette image. 2724 * Blits an index palette image into a direct palette image.
2672 * <p> 2725 * <p>
2673 * Note: The source and destination masks and palettes must 2726 * Note: The source and destination masks and palettes must
2674 * always be fully specified. 2727 * always be fully specified.
2675 * </p> 2728 * </p>
2676 * 2729 *
2677 * @param op the blitter operation: a combination of BLIT_xxx flags 2730 * @param op the blitter operation: a combination of BLIT_xxx flags
2678 * (see BLIT_xxx constants) 2731 * (see BLIT_xxx constants)
2679 * @param srcData the source byte array containing image data 2732 * @param srcData the source byte array containing image data
2680 * @param srcDepth the source depth: one of 1, 2, 4, 8 2733 * @param srcDepth the source depth: one of 1, 2, 4, 8
2681 * @param srcStride the source number of bytes per line 2734 * @param srcStride the source number of bytes per line
2719 int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY, 2772 int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
2720 byte[] destData, int destDepth, int destStride, int destOrder, 2773 byte[] destData, int destDepth, int destStride, int destOrder,
2721 int destX, int destY, int destWidth, int destHeight, 2774 int destX, int destY, int destWidth, int destHeight,
2722 int destRedMask, int destGreenMask, int destBlueMask, 2775 int destRedMask, int destGreenMask, int destBlueMask,
2723 bool flipX, bool flipY) { 2776 bool flipX, bool flipY) {
2777
2778 static_this();
2779
2724 if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; 2780 if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return;
2725 2781
2726 // these should be supplied as params later 2782 // these should be supplied as params later
2727 final int destAlphaMask = 0; 2783 int destAlphaMask = 0;
2728 2784
2729 /*** Prepare scaling data ***/ 2785 /*** Prepare scaling data ***/
2730 final int dwm1 = destWidth - 1; 2786 int dwm1 = destWidth - 1;
2731 final int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0; 2787 int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0;
2732 final int dhm1 = destHeight - 1; 2788 int dhm1 = destHeight - 1;
2733 final int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0; 2789 int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0;
2734 2790
2735 /*** Prepare source-related data ***/ 2791 /*** Prepare source-related data ***/
2736 final int stype; 2792 int stype;
2737 switch (srcDepth) { 2793 switch (srcDepth) {
2738 case 8: 2794 case 8:
2739 stype = TYPE_INDEX_8; 2795 stype = TYPE_INDEX_8;
2740 break; 2796 break;
2741 case 4: 2797 case 4:
2751 stype = (srcOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; 2807 stype = (srcOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
2752 break; 2808 break;
2753 default: 2809 default:
2754 //throw new IllegalArgumentException("Invalid source type"); 2810 //throw new IllegalArgumentException("Invalid source type");
2755 return; 2811 return;
2756 } 2812 }
2757 int spr = srcY * srcStride + srcX; 2813 int spr = srcY * srcStride + srcX;
2758 2814
2759 /*** Prepare destination-related data ***/ 2815 /*** Prepare destination-related data ***/
2760 final int dbpp, dtype; 2816 int dbpp, dtype;
2761 switch (destDepth) { 2817 switch (destDepth) {
2762 case 8: 2818 case 8:
2763 dbpp = 1; 2819 dbpp = 1;
2764 dtype = TYPE_GENERIC_8; 2820 dtype = TYPE_GENERIC_8;
2765 break; 2821 break;
2776 dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; 2832 dtype = (destOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
2777 break; 2833 break;
2778 default: 2834 default:
2779 //throw new IllegalArgumentException("Invalid destination type"); 2835 //throw new IllegalArgumentException("Invalid destination type");
2780 return; 2836 return;
2781 } 2837 }
2782 int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp; 2838 int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp;
2783 final int dprxi = (flipX) ? -dbpp : dbpp; 2839 int dprxi = (flipX) ? -dbpp : dbpp;
2784 final int dpryi = (flipY) ? -destStride : destStride; 2840 int dpryi = (flipY) ? -destStride : destStride;
2785 2841
2786 /*** Prepare special processing data ***/ 2842 /*** Prepare special processing data ***/
2787 int apr; 2843 int apr;
2788 if ((op & BLIT_ALPHA) !is 0) { 2844 if ((op & BLIT_ALPHA) !is 0) {
2789 switch (alphaMode) { 2845 switch (alphaMode) {
2812 alphaMode = 0x10000; 2868 alphaMode = 0x10000;
2813 apr = 0; 2869 apr = 0;
2814 } 2870 }
2815 2871
2816 /*** Comprehensive blit (apply transformations) ***/ 2872 /*** Comprehensive blit (apply transformations) ***/
2817 final int destRedShift = getChannelShift(destRedMask); 2873 int destRedShift = getChannelShift(destRedMask);
2818 final int destRedWidth = getChannelWidth(destRedMask, destRedShift); 2874 int destRedWidth = getChannelWidth(destRedMask, destRedShift);
2819 final byte[] destReds = ANY_TO_EIGHT[destRedWidth]; 2875 byte[] destReds = ANY_TO_EIGHT[destRedWidth];
2820 final int destRedPreShift = 8 - destRedWidth; 2876 int destRedPreShift = 8 - destRedWidth;
2821 final int destGreenShift = getChannelShift(destGreenMask); 2877 int destGreenShift = getChannelShift(destGreenMask);
2822 final int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift); 2878 int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift);
2823 final byte[] destGreens = ANY_TO_EIGHT[destGreenWidth]; 2879 byte[] destGreens = ANY_TO_EIGHT[destGreenWidth];
2824 final int destGreenPreShift = 8 - destGreenWidth; 2880 int destGreenPreShift = 8 - destGreenWidth;
2825 final int destBlueShift = getChannelShift(destBlueMask); 2881 int destBlueShift = getChannelShift(destBlueMask);
2826 final int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift); 2882 int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift);
2827 final byte[] destBlues = ANY_TO_EIGHT[destBlueWidth]; 2883 byte[] destBlues = ANY_TO_EIGHT[destBlueWidth];
2828 final int destBluePreShift = 8 - destBlueWidth; 2884 int destBluePreShift = 8 - destBlueWidth;
2829 final int destAlphaShift = getChannelShift(destAlphaMask); 2885 int destAlphaShift = getChannelShift(destAlphaMask);
2830 final int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift); 2886 int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift);
2831 final byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth]; 2887 byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth];
2832 final int destAlphaPreShift = 8 - destAlphaWidth; 2888 int destAlphaPreShift = 8 - destAlphaWidth;
2833 2889
2834 int dp = dpr; 2890 int dp = dpr;
2835 int sp = spr; 2891 int sp = spr;
2836 int ap = apr, alpha = alphaMode; 2892 int ap = apr, alpha = alphaMode;
2837 int r = 0, g = 0, b = 0, a = 0, index = 0; 2893 int r = 0, g = 0, b = 0, a = 0, index = 0;
2865 break; 2921 break;
2866 case TYPE_INDEX_1_LSB: 2922 case TYPE_INDEX_1_LSB:
2867 index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01; 2923 index = (srcData[sp >> 3] >>> (sp & 7)) & 0x01;
2868 sp += (sfx >>> 16); 2924 sp += (sfx >>> 16);
2869 break; 2925 break;
2926 default:
2870 } 2927 }
2871 2928
2872 /*** DO SPECIAL PROCESSING IF REQUIRED ***/ 2929 /*** DO SPECIAL PROCESSING IF REQUIRED ***/
2873 r = srcReds[index] & 0xff; 2930 r = srcReds[index] & 0xff;
2874 g = srcGreens[index] & 0xff; 2931 g = srcGreens[index] & 0xff;
2879 ap += (sfx >> 16); 2936 ap += (sfx >> 16);
2880 break; 2937 break;
2881 case ALPHA_MASK_UNPACKED: 2938 case ALPHA_MASK_UNPACKED:
2882 alpha = (alphaData[ap] !is 0) ? 0x10000 : 0; 2939 alpha = (alphaData[ap] !is 0) ? 0x10000 : 0;
2883 ap += (sfx >> 16); 2940 ap += (sfx >> 16);
2884 break; 2941 break;
2885 case ALPHA_MASK_PACKED: 2942 case ALPHA_MASK_PACKED:
2886 alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000; 2943 alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
2887 ap += (sfx >> 16); 2944 ap += (sfx >> 16);
2888 break; 2945 break;
2889 case ALPHA_MASK_INDEX: { // could speed up using binary search if we sorted the indices 2946 case ALPHA_MASK_INDEX: { // could speed up using binary search if we sorted the indices
2901 (b is (alphaData[i + 2] & 0xff))) break; 2958 (b is (alphaData[i + 2] & 0xff))) break;
2902 i += 3; 2959 i += 3;
2903 } 2960 }
2904 if (i < alphaData.length) continue; 2961 if (i < alphaData.length) continue;
2905 } break; 2962 } break;
2963 default:
2906 } 2964 }
2907 if (alpha !is 0x10000) { 2965 if (alpha !is 0x10000) {
2908 if (alpha is 0x0000) continue; 2966 if (alpha is 0x0000) continue;
2909 switch (dtype) { 2967 switch (dtype) {
2910 case TYPE_GENERIC_8: { 2968 case TYPE_GENERIC_8: {
2911 final int data = destData[dp] & 0xff; 2969 int data = destData[dp] & 0xff;
2912 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2970 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2913 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2971 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2914 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2972 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2915 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2973 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2916 } break; 2974 } break;
2917 case TYPE_GENERIC_16_MSB: { 2975 case TYPE_GENERIC_16_MSB: {
2918 final int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff); 2976 int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff);
2919 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2977 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2920 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2978 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2921 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2979 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2922 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2980 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2923 } break; 2981 } break;
2924 case TYPE_GENERIC_16_LSB: { 2982 case TYPE_GENERIC_16_LSB: {
2925 final int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff); 2983 int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff);
2926 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2984 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2927 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2985 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2928 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2986 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2929 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2987 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2930 } break; 2988 } break;
2931 case TYPE_GENERIC_24: { 2989 case TYPE_GENERIC_24: {
2932 final int data = (( ((destData[dp] & 0xff) << 8) | 2990 int data = (( ((destData[dp] & 0xff) << 8) |
2933 (destData[dp + 1] & 0xff)) << 8) | 2991 (destData[dp + 1] & 0xff)) << 8) |
2934 (destData[dp + 2] & 0xff); 2992 (destData[dp + 2] & 0xff);
2935 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 2993 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2936 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 2994 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2937 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 2995 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2938 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 2996 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2939 } break; 2997 } break;
2940 case TYPE_GENERIC_32_MSB: { 2998 case TYPE_GENERIC_32_MSB: {
2941 final int data = (( (( ((destData[dp] & 0xff) << 8) | 2999 int data = (( (( ((destData[dp] & 0xff) << 8) |
2942 (destData[dp + 1] & 0xff)) << 8) | 3000 (destData[dp + 1] & 0xff)) << 8) |
2943 (destData[dp + 2] & 0xff)) << 8) | 3001 (destData[dp + 2] & 0xff)) << 8) |
2944 (destData[dp + 3] & 0xff); 3002 (destData[dp + 3] & 0xff);
2945 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 3003 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2946 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 3004 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2947 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 3005 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2948 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 3006 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2949 } break; 3007 } break;
2950 case TYPE_GENERIC_32_LSB: { 3008 case TYPE_GENERIC_32_LSB: {
2951 final int data = (( (( ((destData[dp + 3] & 0xff) << 8) | 3009 int data = (( (( ((destData[dp + 3] & 0xff) << 8) |
2952 (destData[dp + 2] & 0xff)) << 8) | 3010 (destData[dp + 2] & 0xff)) << 8) |
2953 (destData[dp + 1] & 0xff)) << 8) | 3011 (destData[dp + 1] & 0xff)) << 8) |
2954 (destData[dp] & 0xff); 3012 (destData[dp] & 0xff);
2955 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff; 3013 rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
2956 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff; 3014 gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
2957 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff; 3015 bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
2958 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff; 3016 aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
2959 } break; 3017 } break;
3018 default:
2960 } 3019 }
2961 // Perform alpha blending 3020 // Perform alpha blending
2962 a = aq + ((a - aq) * alpha >> 16); 3021 a = aq + ((a - aq) * alpha >> 16);
2963 r = rq + ((r - rq) * alpha >> 16); 3022 r = rq + ((r - rq) * alpha >> 16);
2964 g = gq + ((g - gq) * alpha >> 16); 3023 g = gq + ((g - gq) * alpha >> 16);
2965 b = bq + ((b - bq) * alpha >> 16); 3024 b = bq + ((b - bq) * alpha >> 16);
2966 } 3025 }
2967 3026
2968 /*** WRITE NEXT PIXEL ***/ 3027 /*** WRITE NEXT PIXEL ***/
2969 final int data = 3028 int data =
2970 (r >>> destRedPreShift << destRedShift) | 3029 (r >>> destRedPreShift << destRedShift) |
2971 (g >>> destGreenPreShift << destGreenShift) | 3030 (g >>> destGreenPreShift << destGreenShift) |
2972 (b >>> destBluePreShift << destBlueShift) | 3031 (b >>> destBluePreShift << destBlueShift) |
2973 (a >>> destAlphaPreShift << destAlphaShift); 3032 (a >>> destAlphaPreShift << destAlphaShift);
2974 switch (dtype) { 3033 switch (dtype) {
2998 destData[dp] = cast(byte) (data & 0xff); 3057 destData[dp] = cast(byte) (data & 0xff);
2999 destData[dp + 1] = cast(byte) (data >>> 8); 3058 destData[dp + 1] = cast(byte) (data >>> 8);
3000 destData[dp + 2] = cast(byte) (data >>> 16); 3059 destData[dp + 2] = cast(byte) (data >>> 16);
3001 destData[dp + 3] = cast(byte) (data >>> 24); 3060 destData[dp + 3] = cast(byte) (data >>> 24);
3002 } break; 3061 } break;
3062 default:
3003 } 3063 }
3004 } 3064 }
3005 } 3065 }
3006 } 3066 }
3007 3067
3008 /** 3068 /**
3009 * Blits a direct palette image into an index palette image. 3069 * Blits a direct palette image into an index palette image.
3010 * <p> 3070 * <p>
3011 * Note: The source and destination masks and palettes must 3071 * Note: The source and destination masks and palettes must
3012 * always be fully specified. 3072 * always be fully specified.
3013 * </p> 3073 * </p>
3014 * 3074 *
3015 * @param op the blitter operation: a combination of BLIT_xxx flags 3075 * @param op the blitter operation: a combination of BLIT_xxx flags
3016 * (see BLIT_xxx constants) 3076 * (see BLIT_xxx constants)
3017 * @param srcData the source byte array containing image data 3077 * @param srcData the source byte array containing image data
3018 * @param srcDepth the source depth: one of 8, 16, 24, 32 3078 * @param srcDepth the source depth: one of 8, 16, 24, 32
3019 * @param srcStride the source number of bytes per line 3079 * @param srcStride the source number of bytes per line
3057 int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY, 3117 int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
3058 byte[] destData, int destDepth, int destStride, int destOrder, 3118 byte[] destData, int destDepth, int destStride, int destOrder,
3059 int destX, int destY, int destWidth, int destHeight, 3119 int destX, int destY, int destWidth, int destHeight,
3060 byte[] destReds, byte[] destGreens, byte[] destBlues, 3120 byte[] destReds, byte[] destGreens, byte[] destBlues,
3061 bool flipX, bool flipY) { 3121 bool flipX, bool flipY) {
3122
3123 static_this();
3124
3062 if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return; 3125 if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode is ALPHA_TRANSPARENT)) return;
3063 3126
3064 // these should be supplied as params later 3127 // these should be supplied as params later
3065 final int srcAlphaMask = 0; 3128 int srcAlphaMask = 0;
3066 3129
3067 /*** Prepare scaling data ***/ 3130 /*** Prepare scaling data ***/
3068 final int dwm1 = destWidth - 1; 3131 int dwm1 = destWidth - 1;
3069 final int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0; 3132 int sfxi = (dwm1 !is 0) ? cast(int)(((cast(long)srcWidth << 16) - 1) / dwm1) : 0;
3070 final int dhm1 = destHeight - 1; 3133 int dhm1 = destHeight - 1;
3071 final int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0; 3134 int sfyi = (dhm1 !is 0) ? cast(int)(((cast(long)srcHeight << 16) - 1) / dhm1) : 0;
3072 3135
3073 /*** Prepare source-related data ***/ 3136 /*** Prepare source-related data ***/
3074 final int sbpp, stype; 3137 int sbpp, stype;
3075 switch (srcDepth) { 3138 switch (srcDepth) {
3076 case 8: 3139 case 8:
3077 sbpp = 1; 3140 sbpp = 1;
3078 stype = TYPE_GENERIC_8; 3141 stype = TYPE_GENERIC_8;
3079 break; 3142 break;
3090 stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB; 3153 stype = (srcOrder is MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
3091 break; 3154 break;
3092 default: 3155 default:
3093 //throw new IllegalArgumentException("Invalid source type"); 3156 //throw new IllegalArgumentException("Invalid source type");
3094 return; 3157 return;
3095 } 3158 }
3096 int spr = srcY * srcStride + srcX * sbpp; 3159 int spr = srcY * srcStride + srcX * sbpp;
3097 3160
3098 /*** Prepare destination-related data ***/ 3161 /*** Prepare destination-related data ***/
3099 final int dtype; 3162 int dtype;
3100 switch (destDepth) { 3163 switch (destDepth) {
3101 case 8: 3164 case 8:
3102 dtype = TYPE_INDEX_8; 3165 dtype = TYPE_INDEX_8;
3103 break; 3166 break;
3104 case 4: 3167 case 4:
3114 dtype = (destOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB; 3177 dtype = (destOrder is MSB_FIRST) ? TYPE_INDEX_1_MSB : TYPE_INDEX_1_LSB;
3115 break; 3178 break;
3116 default: 3179 default:
3117 //throw new IllegalArgumentException("Invalid source type"); 3180 //throw new IllegalArgumentException("Invalid source type");
3118 return; 3181 return;
3119 } 3182 }
3120 int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX); 3183 int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX);
3121 final int dprxi = (flipX) ? -1 : 1; 3184 int dprxi = (flipX) ? -1 : 1;
3122 final int dpryi = (flipY) ? -destStride : destStride; 3185 int dpryi = (flipY) ? -destStride : destStride;
3123 3186
3124 /*** Prepare special processing data ***/ 3187 /*** Prepare special processing data ***/
3125 int apr; 3188 int apr;
3126 if ((op & BLIT_ALPHA) !is 0) { 3189 if ((op & BLIT_ALPHA) !is 0) {
3127 switch (alphaMode) { 3190 switch (alphaMode) {
3150 } 3213 }
3151 } else { 3214 } else {
3152 alphaMode = 0x10000; 3215 alphaMode = 0x10000;
3153 apr = 0; 3216 apr = 0;
3154 } 3217 }
3155 final bool ditherEnabled = (op & BLIT_DITHER) !is 0; 3218 bool ditherEnabled = (op & BLIT_DITHER) !is 0;
3156 3219
3157 /*** Comprehensive blit (apply transformations) ***/ 3220 /*** Comprehensive blit (apply transformations) ***/
3158 final int srcRedShift = getChannelShift(srcRedMask); 3221 int srcRedShift = getChannelShift(srcRedMask);
3159 final byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)]; 3222 byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)];
3160 final int srcGreenShift = getChannelShift(srcGreenMask); 3223 int srcGreenShift = getChannelShift(srcGreenMask);
3161 final byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)]; 3224 byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)];
3162 final int srcBlueShift = getChannelShift(srcBlueMask); 3225 int srcBlueShift = getChannelShift(srcBlueMask);
3163 final byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)]; 3226 byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)];
3164 final int srcAlphaShift = getChannelShift(srcAlphaMask); 3227 int srcAlphaShift = getChannelShift(srcAlphaMask);
3165 final byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)]; 3228 byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)];
3166 3229
3167 int dp = dpr; 3230 int dp = dpr;
3168 int sp = spr; 3231 int sp = spr;
3169 int ap = apr, alpha = alphaMode; 3232 int ap = apr, alpha = alphaMode;
3170 int r = 0, g = 0, b = 0, a = 0; 3233 int r = 0, g = 0, b = 0, a = 0;
3171 int indexq = 0; 3234 int indexq = 0;
3172 int lastindex = 0, lastr = -1, lastg = -1, lastb = -1; 3235 int lastindex = 0, lastr = -1, lastg = -1, lastb = -1;
3173 final int[] rerr, gerr, berr; 3236 int[] rerr, gerr, berr;
3174 int destPaletteSize = 1 << destDepth; 3237 int destPaletteSize = 1 << destDepth;
3175 if ((destReds !is null) && (destReds.length < destPaletteSize)) destPaletteSize = destReds.length; 3238 if ((destReds !is null) && (destReds.length < destPaletteSize)) destPaletteSize = destReds.length;
3176 if (ditherEnabled) { 3239 if (ditherEnabled) {
3177 rerr = new int[destWidth + 2]; 3240 rerr = new int[destWidth + 2];
3178 gerr = new int[destWidth + 2]; 3241 gerr = new int[destWidth + 2];
3190 dp += dprxi, 3253 dp += dprxi,
3191 sfx = (sfx & 0xffff) + sfxi) { 3254 sfx = (sfx & 0xffff) + sfxi) {
3192 /*** READ NEXT PIXEL ***/ 3255 /*** READ NEXT PIXEL ***/
3193 switch (stype) { 3256 switch (stype) {
3194 case TYPE_GENERIC_8: { 3257 case TYPE_GENERIC_8: {
3195 final int data = srcData[sp] & 0xff; 3258 int data = srcData[sp] & 0xff;
3196 sp += (sfx >>> 16); 3259 sp += (sfx >>> 16);
3197 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 3260 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
3198 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 3261 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
3199 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 3262 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
3200 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 3263 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
3201 } break; 3264 } break;
3202 case TYPE_GENERIC_16_MSB: { 3265 case TYPE_GENERIC_16_MSB: {
3203 final int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff); 3266 int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff);
3204 sp += (sfx >>> 16) * 2; 3267 sp += (sfx >>> 16) * 2;
3205 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 3268 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
3206 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 3269 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
3207 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 3270 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
3208 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 3271 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
3209 } break; 3272 } break;
3210 case TYPE_GENERIC_16_LSB: { 3273 case TYPE_GENERIC_16_LSB: {
3211 final int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff); 3274 int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff);
3212 sp += (sfx >>> 16) * 2; 3275 sp += (sfx >>> 16) * 2;
3213 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 3276 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
3214 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 3277 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
3215 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 3278 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
3216 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 3279 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
3217 } break; 3280 } break;
3218 case TYPE_GENERIC_24: { 3281 case TYPE_GENERIC_24: {
3219 final int data = (( ((srcData[sp] & 0xff) << 8) | 3282 int data = (( ((srcData[sp] & 0xff) << 8) |
3220 (srcData[sp + 1] & 0xff)) << 8) | 3283 (srcData[sp + 1] & 0xff)) << 8) |
3221 (srcData[sp + 2] & 0xff); 3284 (srcData[sp + 2] & 0xff);
3222 sp += (sfx >>> 16) * 3; 3285 sp += (sfx >>> 16) * 3;
3223 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 3286 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
3224 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 3287 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
3225 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 3288 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
3226 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 3289 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
3227 } break; 3290 } break;
3228 case TYPE_GENERIC_32_MSB: { 3291 case TYPE_GENERIC_32_MSB: {
3229 final int data = (( (( ((srcData[sp] & 0xff) << 8) | 3292 int data = (( (( ((srcData[sp] & 0xff) << 8) |
3230 (srcData[sp + 1] & 0xff)) << 8) | 3293 (srcData[sp + 1] & 0xff)) << 8) |
3231 (srcData[sp + 2] & 0xff)) << 8) | 3294 (srcData[sp + 2] & 0xff)) << 8) |
3232 (srcData[sp + 3] & 0xff); 3295 (srcData[sp + 3] & 0xff);
3233 sp += (sfx >>> 16) * 4; 3296 sp += (sfx >>> 16) * 4;
3234 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 3297 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
3235 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 3298 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
3236 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 3299 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
3237 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 3300 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
3238 } break; 3301 } break;
3239 case TYPE_GENERIC_32_LSB: { 3302 case TYPE_GENERIC_32_LSB: {
3240 final int data = (( (( ((srcData[sp + 3] & 0xff) << 8) | 3303 int data = (( (( ((srcData[sp + 3] & 0xff) << 8) |
3241 (srcData[sp + 2] & 0xff)) << 8) | 3304 (srcData[sp + 2] & 0xff)) << 8) |
3242 (srcData[sp + 1] & 0xff)) << 8) | 3305 (srcData[sp + 1] & 0xff)) << 8) |
3243 (srcData[sp] & 0xff); 3306 (srcData[sp] & 0xff);
3244 sp += (sfx >>> 16) * 4; 3307 sp += (sfx >>> 16) * 4;
3245 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff; 3308 r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
3246 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff; 3309 g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
3247 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff; 3310 b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
3248 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff; 3311 a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
3249 } break; 3312 } break;
3313 default:
3250 } 3314 }
3251 3315
3252 /*** DO SPECIAL PROCESSING IF REQUIRED ***/ 3316 /*** DO SPECIAL PROCESSING IF REQUIRED ***/
3253 switch (alphaMode) { 3317 switch (alphaMode) {
3254 case ALPHA_CHANNEL_SEPARATE: 3318 case ALPHA_CHANNEL_SEPARATE:
3259 alpha = (a << 16) / 255; 3323 alpha = (a << 16) / 255;
3260 break; 3324 break;
3261 case ALPHA_MASK_UNPACKED: 3325 case ALPHA_MASK_UNPACKED:
3262 alpha = (alphaData[ap] !is 0) ? 0x10000 : 0; 3326 alpha = (alphaData[ap] !is 0) ? 0x10000 : 0;
3263 ap += (sfx >> 16); 3327 ap += (sfx >> 16);
3264 break; 3328 break;
3265 case ALPHA_MASK_PACKED: 3329 case ALPHA_MASK_PACKED:
3266 alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000; 3330 alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
3267 ap += (sfx >> 16); 3331 ap += (sfx >> 16);
3268 break; 3332 break;
3269 case ALPHA_MASK_RGB: 3333 case ALPHA_MASK_RGB:
3273 alpha = 0x0000; 3337 alpha = 0x0000;
3274 break; 3338 break;
3275 } 3339 }
3276 } 3340 }
3277 break; 3341 break;
3342 default:
3278 } 3343 }
3279 if (alpha !is 0x10000) { 3344 if (alpha !is 0x10000) {
3280 if (alpha is 0x0000) continue; 3345 if (alpha is 0x0000) continue;
3281 switch (dtype) { 3346 switch (dtype) {
3282 case TYPE_INDEX_8: 3347 case TYPE_INDEX_8:
3293 indexq = (destData[dp >> 3] >>> (7 - (dp & 7))) & 0x01; 3358 indexq = (destData[dp >> 3] >>> (7 - (dp & 7))) & 0x01;
3294 break; 3359 break;
3295 case TYPE_INDEX_1_LSB: 3360 case TYPE_INDEX_1_LSB:
3296 indexq = (destData[dp >> 3] >>> (dp & 7)) & 0x01; 3361 indexq = (destData[dp >> 3] >>> (dp & 7)) & 0x01;
3297 break; 3362 break;
3363 default:
3298 } 3364 }
3299 // Perform alpha blending 3365 // Perform alpha blending
3300 final int rq = destReds[indexq] & 0xff; 3366 int rq = destReds[indexq] & 0xff;
3301 final int gq = destGreens[indexq] & 0xff; 3367 int gq = destGreens[indexq] & 0xff;
3302 final int bq = destBlues[indexq] & 0xff; 3368 int bq = destBlues[indexq] & 0xff;
3303 r = rq + ((r - rq) * alpha >> 16); 3369 r = rq + ((r - rq) * alpha >> 16);
3304 g = gq + ((g - gq) * alpha >> 16); 3370 g = gq + ((g - gq) * alpha >> 16);
3305 b = bq + ((b - bq) * alpha >> 16); 3371 b = bq + ((b - bq) * alpha >> 16);
3306 } 3372 }
3307 3373
3333 } 3399 }
3334 lastr = r; lastg = g; lastb = b; 3400 lastr = r; lastg = g; lastb = b;
3335 } 3401 }
3336 if (ditherEnabled) { 3402 if (ditherEnabled) {
3337 // Floyd-Steinberg error diffusion, cont'd... 3403 // Floyd-Steinberg error diffusion, cont'd...
3338 final int dxm1 = dx - 1, dxp1 = dx + 1; 3404 int dxm1 = dx - 1, dxp1 = dx + 1;
3339 int acc; 3405 int acc;
3340 rerr[dxp1] += acc = (lrerr = r - (destReds[lastindex] & 0xff)) + lrerr + lrerr; 3406 rerr[dxp1] += acc = (lrerr = r - (destReds[lastindex] & 0xff)) + lrerr + lrerr;
3341 rerr[dx] += acc += lrerr + lrerr; 3407 rerr[dx] += acc += lrerr + lrerr;
3342 rerr[dxm1] += acc + lrerr + lrerr; 3408 rerr[dxm1] += acc + lrerr + lrerr;
3343 gerr[dxp1] += acc = (lgerr = g - (destGreens[lastindex] & 0xff)) + lgerr + lgerr; 3409 gerr[dxp1] += acc = (lgerr = g - (destGreens[lastindex] & 0xff)) + lgerr + lgerr;
3356 case TYPE_INDEX_4: 3422 case TYPE_INDEX_4:
3357 if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | lastindex); 3423 if ((dp & 1) !is 0) destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0xf0) | lastindex);
3358 else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4)); 3424 else destData[dp >> 1] = cast(byte)((destData[dp >> 1] & 0x0f) | (lastindex << 4));
3359 break; 3425 break;
3360 case TYPE_INDEX_2: { 3426 case TYPE_INDEX_2: {
3361 final int shift = 6 - (dp & 3) * 2; 3427 int shift = 6 - (dp & 3) * 2;
3362 destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift)); 3428 destData[dp >> 2] = cast(byte)(destData[dp >> 2] & ~(0x03 << shift) | (lastindex << shift));
3363 } break; 3429 } break;
3364 case TYPE_INDEX_1_MSB: { 3430 case TYPE_INDEX_1_MSB: {
3365 final int shift = 7 - (dp & 7); 3431 int shift = 7 - (dp & 7);
3366 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); 3432 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
3367 } break; 3433 } break;
3368 case TYPE_INDEX_1_LSB: { 3434 case TYPE_INDEX_1_LSB: {
3369 final int shift = dp & 7; 3435 int shift = dp & 7;
3370 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift)); 3436 destData[dp >> 3] = cast(byte)(destData[dp >> 3] & ~(0x01 << shift) | (lastindex << shift));
3371 } break; 3437 } break;
3438 default:
3372 } 3439 }
3373 } 3440 }
3374 } 3441 }
3375 } 3442 }
3376 3443
3401 3468
3402 /** 3469 /**
3403 * Extracts a field from packed RGB data given a mask for that field. 3470 * Extracts a field from packed RGB data given a mask for that field.
3404 */ 3471 */
3405 static byte getChannelField(int data, int mask) { 3472 static byte getChannelField(int data, int mask) {
3406 final int shift = getChannelShift(mask); 3473 static_this();
3474 int shift = getChannelShift(mask);
3407 return ANY_TO_EIGHT[getChannelWidth(mask, shift)][(data & mask) >>> shift]; 3475 return ANY_TO_EIGHT[getChannelWidth(mask, shift)][(data & mask) >>> shift];
3408 } 3476 }
3409 3477
3410 /** 3478 /**
3411 * Creates an ImageData containing one band's worth of a gradient filled 3479 * Creates an ImageData containing one band's worth of a gradient filled
3426 static ImageData createGradientBand( 3494 static ImageData createGradientBand(
3427 int width, int height, bool vertical, 3495 int width, int height, bool vertical,
3428 RGB fromRGB, RGB toRGB, 3496 RGB fromRGB, RGB toRGB,
3429 int redBits, int greenBits, int blueBits) { 3497 int redBits, int greenBits, int blueBits) {
3430 /* Gradients are drawn as tiled bands */ 3498 /* Gradients are drawn as tiled bands */
3431 final int bandWidth, bandHeight, bitmapDepth; 3499 int bandWidth, bandHeight, bitmapDepth;
3432 final byte[] bitmapData; 3500 byte[] bitmapData;
3433 final PaletteData paletteData; 3501 PaletteData paletteData;
3434 /* Select an algorithm depending on the depth of the screen */ 3502 /* Select an algorithm depending on the depth of the screen */
3435 if (redBits !is 0 && greenBits !is 0 && blueBits !is 0) { 3503 if (redBits !is 0 && greenBits !is 0 && blueBits !is 0) {
3436 paletteData = new PaletteData(0x0000ff00, 0x00ff0000, 0xff000000); 3504 paletteData = new PaletteData(0x0000ff00, 0x00ff0000, 0xff000000);
3437 bitmapDepth = 32; 3505 bitmapDepth = 32;
3438 if (redBits >= 8 && greenBits >= 8 && blueBits >= 8) { 3506 if (redBits >= 8 && greenBits >= 8 && blueBits >= 8) {
3439 /* Precise color */ 3507 /* Precise color */
3440 final int steps; 3508 int steps;
3441 if (vertical) { 3509 if (vertical) {
3442 bandWidth = 1; 3510 bandWidth = 1;
3443 bandHeight = height; 3511 bandHeight = height;
3444 steps = bandHeight > 1 ? bandHeight - 1 : 1; 3512 steps = bandHeight > 1 ? bandHeight - 1 : 1;
3445 } else { 3513 } else {
3446 bandWidth = width; 3514 bandWidth = width;
3447 bandHeight = 1; 3515 bandHeight = 1;
3448 steps = bandWidth > 1 ? bandWidth - 1 : 1; 3516 steps = bandWidth > 1 ? bandWidth - 1 : 1;
3449 } 3517 }
3450 final int bytesPerLine = bandWidth * 4; 3518 int bytesPerLine = bandWidth * 4;
3451 bitmapData = new byte[bandHeight * bytesPerLine]; 3519 bitmapData = new byte[bandHeight * bytesPerLine];
3452 buildPreciseGradientChannel(fromRGB.blue, toRGB.blue, steps, bandWidth, bandHeight, vertical, bitmapData, 0, bytesPerLine); 3520 buildPreciseGradientChannel(fromRGB.blue, toRGB.blue, steps, bandWidth, bandHeight, vertical, bitmapData, 0, bytesPerLine);
3453 buildPreciseGradientChannel(fromRGB.green, toRGB.green, steps, bandWidth, bandHeight, vertical, bitmapData, 1, bytesPerLine); 3521 buildPreciseGradientChannel(fromRGB.green, toRGB.green, steps, bandWidth, bandHeight, vertical, bitmapData, 1, bytesPerLine);
3454 buildPreciseGradientChannel(fromRGB.red, toRGB.red, steps, bandWidth, bandHeight, vertical, bitmapData, 2, bytesPerLine); 3522 buildPreciseGradientChannel(fromRGB.red, toRGB.red, steps, bandWidth, bandHeight, vertical, bitmapData, 2, bytesPerLine);
3455 } else { 3523 } else {
3456 /* Dithered color */ 3524 /* Dithered color */
3457 final int steps; 3525 int steps;
3458 if (vertical) { 3526 if (vertical) {
3459 bandWidth = (width < 8) ? width : 8; 3527 bandWidth = (width < 8) ? width : 8;
3460 bandHeight = height; 3528 bandHeight = height;
3461 steps = bandHeight > 1 ? bandHeight - 1 : 1; 3529 steps = bandHeight > 1 ? bandHeight - 1 : 1;
3462 } else { 3530 } else {
3463 bandWidth = width; 3531 bandWidth = width;
3464 bandHeight = (height < 8) ? height : 8; 3532 bandHeight = (height < 8) ? height : 8;
3465 steps = bandWidth > 1 ? bandWidth - 1 : 1; 3533 steps = bandWidth > 1 ? bandWidth - 1 : 1;
3466 } 3534 }
3467 final int bytesPerLine = bandWidth * 4; 3535 int bytesPerLine = bandWidth * 4;
3468 bitmapData = new byte[bandHeight * bytesPerLine]; 3536 bitmapData = new byte[bandHeight * bytesPerLine];
3469 buildDitheredGradientChannel(fromRGB.blue, toRGB.blue, steps, bandWidth, bandHeight, vertical, bitmapData, 0, bytesPerLine, blueBits); 3537 buildDitheredGradientChannel(fromRGB.blue, toRGB.blue, steps, bandWidth, bandHeight, vertical, bitmapData, 0, bytesPerLine, blueBits);
3470 buildDitheredGradientChannel(fromRGB.green, toRGB.green, steps, bandWidth, bandHeight, vertical, bitmapData, 1, bytesPerLine, greenBits); 3538 buildDitheredGradientChannel(fromRGB.green, toRGB.green, steps, bandWidth, bandHeight, vertical, bitmapData, 1, bytesPerLine, greenBits);
3471 buildDitheredGradientChannel(fromRGB.red, toRGB.red, steps, bandWidth, bandHeight, vertical, bitmapData, 2, bytesPerLine, redBits); 3539 buildDitheredGradientChannel(fromRGB.red, toRGB.red, steps, bandWidth, bandHeight, vertical, bitmapData, 2, bytesPerLine, redBits);
3472 } 3540 }
3473 } else { 3541 } else {
3474 /* Dithered two tone */ 3542 /* Dithered two tone */
3475 paletteData = new PaletteData(new RGB[] { fromRGB, toRGB }); 3543 paletteData = new PaletteData([ fromRGB, toRGB ]);
3476 bitmapDepth = 8; 3544 bitmapDepth = 8;
3477 final int blendi; 3545 int blendi;
3478 if (vertical) { 3546 if (vertical) {
3479 bandWidth = (width < 8) ? width : 8; 3547 bandWidth = (width < 8) ? width : 8;
3480 bandHeight = height; 3548 bandHeight = height;
3481 blendi = (bandHeight > 1) ? 0x1040000 / (bandHeight - 1) + 1 : 1; 3549 blendi = (bandHeight > 1) ? 0x1040000 / (bandHeight - 1) + 1 : 1;
3482 } else { 3550 } else {
3483 bandWidth = width; 3551 bandWidth = width;
3484 bandHeight = (height < 8) ? height : 8; 3552 bandHeight = (height < 8) ? height : 8;
3485 blendi = (bandWidth > 1) ? 0x1040000 / (bandWidth - 1) + 1 : 1; 3553 blendi = (bandWidth > 1) ? 0x1040000 / (bandWidth - 1) + 1 : 1;
3486 } 3554 }
3487 final int bytesPerLine = (bandWidth + 3) & -4; 3555 int bytesPerLine = (bandWidth + 3) & -4;
3488 bitmapData = new byte[bandHeight * bytesPerLine]; 3556 bitmapData = new byte[bandHeight * bytesPerLine];
3489 if (vertical) { 3557 if (vertical) {
3490 for (int dy = 0, blend = 0, dp = 0; dy < bandHeight; 3558 for (int dy = 0, blend = 0, dp = 0; dy < bandHeight;
3491 ++dy, blend += blendi, dp += bytesPerLine) { 3559 ++dy, blend += blendi, dp += bytesPerLine) {
3492 for (int dx = 0; dx < bandWidth; ++dx) { 3560 for (int dx = 0; dx < bandWidth; ++dx) {
3493 bitmapData[dp + dx] = (blend + DITHER_MATRIX[dy & 7][dx]) < 3561 bitmapData[dp + dx] = (blend + DITHER_MATRIX[dy & 7][dx]) <
3494 0x1000000 ? cast(byte)0 : cast(byte)1; 3562 0x1000000 ? cast(byte)0 : cast(byte)1;
3495 } 3563 }
3496 } 3564 }
3497 } else { 3565 } else {
3498 for (int dx = 0, blend = 0; dx < bandWidth; ++dx, blend += blendi) { 3566 for (int dx = 0, blend = 0; dx < bandWidth; ++dx, blend += blendi) {
3499 for (int dy = 0, dptr = dx; dy < bandHeight; ++dy, dptr += bytesPerLine) { 3567 for (int dy = 0, dptr = dx; dy < bandHeight; ++dy, dptr += bytesPerLine) {
3500 bitmapData[dptr] = (blend + DITHER_MATRIX[dy][dx & 7]) < 3568 bitmapData[dptr] = (blend + DITHER_MATRIX[dy][dx & 7]) <
3501 0x1000000 ? cast(byte)0 : cast(byte)1; 3569 0x1000000 ? cast(byte)0 : cast(byte)1;
3504 } 3572 }
3505 } 3573 }
3506 return new ImageData(bandWidth, bandHeight, bitmapDepth, paletteData, 4, bitmapData); 3574 return new ImageData(bandWidth, bandHeight, bitmapDepth, paletteData, 4, bitmapData);
3507 } 3575 }
3508 3576
3509 /* 3577 /*
3510 * Fill in gradated values for a color channel 3578 * Fill in gradated values for a color channel
3511 */ 3579 */
3512 static final void buildPreciseGradientChannel(int from, int to, int steps, 3580 static final void buildPreciseGradientChannel(int from, int to, int steps,
3513 int bandWidth, int bandHeight, bool vertical, 3581 int bandWidth, int bandHeight, bool vertical,
3514 byte[] bitmapData, int dp, int bytesPerLine) { 3582 byte[] bitmapData, int dp, int bytesPerLine) {
3515 int val = from << 16; 3583 int val = from << 16;
3516 final int inc = ((to << 16) - val) / steps + 1; 3584 int inc = ((to << 16) - val) / steps + 1;
3517 if (vertical) { 3585 if (vertical) {
3518 for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) { 3586 for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
3519 bitmapData[dp] = cast(byte)(val >>> 16); 3587 bitmapData[dp] = cast(byte)(val >>> 16);
3520 val += inc; 3588 val += inc;
3521 } 3589 }
3522 } else { 3590 } else {
3523 for (int dx = 0; dx < bandWidth; ++dx, dp += 4) { 3591 for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
3524 bitmapData[dp] = cast(byte)(val >>> 16); 3592 bitmapData[dp] = cast(byte)(val >>> 16);
3525 val += inc; 3593 val += inc;
3526 } 3594 }
3527 } 3595 }
3528 } 3596 }
3529 3597
3530 /* 3598 /*
3531 * Fill in dithered gradated values for a color channel 3599 * Fill in dithered gradated values for a color channel
3532 */ 3600 */
3533 static final void buildDitheredGradientChannel(int from, int to, int steps, 3601 static final void buildDitheredGradientChannel(int from, int to, int steps,
3534 int bandWidth, int bandHeight, bool vertical, 3602 int bandWidth, int bandHeight, bool vertical,
3535 byte[] bitmapData, int dp, int bytesPerLine, int bits) { 3603 byte[] bitmapData, int dp, int bytesPerLine, int bits) {
3536 final int mask = 0xff00 >>> bits; 3604 int mask = 0xff00 >>> bits;
3537 int val = from << 16; 3605 int val = from << 16;
3538 final int inc = ((to << 16) - val) / steps + 1; 3606 int inc = ((to << 16) - val) / steps + 1;
3539 if (vertical) { 3607 if (vertical) {
3540 for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) { 3608 for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
3541 for (int dx = 0, dptr = dp; dx < bandWidth; ++dx, dptr += 4) { 3609 for (int dx = 0, dptr = dp; dx < bandWidth; ++dx, dptr += 4) {
3542 final int thresh = DITHER_MATRIX[dy & 7][dx] >>> bits; 3610 int thresh = DITHER_MATRIX[dy & 7][dx] >>> bits;
3543 int temp = val + thresh; 3611 int temp = val + thresh;
3544 if (temp > 0xffffff) bitmapData[dptr] = -1; 3612 if (temp > 0xffffff) bitmapData[dptr] = -1;
3545 else bitmapData[dptr] = cast(byte)((temp >>> 16) & mask); 3613 else bitmapData[dptr] = cast(byte)((temp >>> 16) & mask);
3546 } 3614 }
3547 val += inc; 3615 val += inc;
3548 } 3616 }
3549 } else { 3617 } else {
3550 for (int dx = 0; dx < bandWidth; ++dx, dp += 4) { 3618 for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
3551 for (int dy = 0, dptr = dp; dy < bandHeight; ++dy, dptr += bytesPerLine) { 3619 for (int dy = 0, dptr = dp; dy < bandHeight; ++dy, dptr += bytesPerLine) {
3552 final int thresh = DITHER_MATRIX[dy][dx & 7] >>> bits; 3620 int thresh = DITHER_MATRIX[dy][dx & 7] >>> bits;
3553 int temp = val + thresh; 3621 int temp = val + thresh;
3554 if (temp > 0xffffff) bitmapData[dptr] = -1; 3622 if (temp > 0xffffff) bitmapData[dptr] = -1;
3555 else bitmapData[dptr] = cast(byte)((temp >>> 16) & mask); 3623 else bitmapData[dptr] = cast(byte)((temp >>> 16) & mask);
3556 } 3624 }
3557 val += inc; 3625 val += inc;