Mercurial > projects > dwt-mac
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; |