Revert StaticDisplayState; For hosted only allow debug to be used.
[SquirrelJME.git] / modules / midp-lcdui / src / main / java / cc / squirreljme / runtime / lcdui / gfx / AdvancedGraphics.java
blobdb92aa24531060e9380c8d859d248380d4fde732
1 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the GNU General Public License v3+, or later.
7 // See license.mkd for licensing and copyright information.
8 // ---------------------------------------------------------------------------
10 package cc.squirreljme.runtime.lcdui.gfx;
12 import cc.squirreljme.runtime.cldc.debug.Debugging;
13 import cc.squirreljme.runtime.lcdui.font.SQFFont;
14 import javax.microedition.lcdui.Font;
15 import javax.microedition.lcdui.Graphics;
16 import javax.microedition.lcdui.Image;
17 import javax.microedition.lcdui.Text;
18 import javax.microedition.lcdui.game.Sprite;
20 /**
21 * This class contains the advanced graphics functions which uses
22 * pre-determined functions to determine how to draw something.
24 * This class will eventually be replaced by generic auto-generated classes
25 * which can handle every pixel format.
27 * @since 2019/03/24
29 public class AdvancedGraphics
30 extends Graphics
32 /** Clipping above. */
33 private static final int _CLIP_ABOVE =
36 /** Clipping below. */
37 private static final int _CLIP_BELOW =
40 /** Clip right. */
41 private static final int _CLIP_RIGHT =
44 /** Clip left. */
45 private static final int _CLIP_LEFT =
48 /** The array buffer. */
49 protected final int[] buffer;
51 /** The length of the buffer. */
52 protected final int bufferlen;
54 /** The width of the image. */
55 protected final int width;
57 /** The height of the image. */
58 protected final int height;
60 /** The pitch of the image. */
61 protected final int pitch;
63 /** The buffer offset. */
64 protected final int offset;
66 /** The number of elements that consist of pixel data. */
67 protected final int numelements;
69 /** Physical end of the buffer. */
70 protected final int lastelement;
72 /** Is there an alpha channel? */
73 protected final boolean hasalphachannel;
75 /** Absolute translated X coordinate. */
76 protected final int abstransx;
78 /** Absolute translated Y coordinate. */
79 protected final int abstransy;
81 /** The current stroke style. */
82 protected int strokestyle;
84 /** Is a dot stroke being used? */
85 protected boolean dotstroke;
87 /** Translated X coordinate. */
88 protected int transx;
90 /** Translated Y coordinate. */
91 protected int transy;
93 /** The starting X clip. */
94 protected int clipsx;
96 /** The starting Y clip. */
97 protected int clipsy;
99 /** The ending X clip. */
100 protected int clipex;
102 /** The ending Y clip. */
103 protected int clipey;
105 /** The clip width. */
106 protected int clipw;
108 /** The clip height. */
109 protected int cliph;
111 /** The current font, null means default. */
112 protected Font font;
114 /** The current blending mode. */
115 protected int blendmode;
117 /** Could blending be done? */
118 protected boolean candoblending;
120 /** Is blending actually going to be done? */
121 protected boolean doblending;
123 /** The current color. */
124 protected int color;
126 /** The painting alpha color. */
127 protected int paintalpha;
129 /** The color to use for painting. */
130 protected int paintcolor;
132 /** Paint color with the alpha channel set to the max. */
133 protected int paintcolorhigh;
135 /** The alpha color and normal color for painting. */
136 protected int paintalphacolor;
138 /** Function for filled rectangle. */
139 protected AdvancedFunction funcfillrect;
141 /** Function for drawing characters. */
142 protected AdvancedFunction funccharbmp;
144 /** Function for drawing lines. */
145 protected AdvancedFunction funcline;
147 /** RGB tile. */
148 protected AdvancedFunction funcrgbtile;
150 /** ARGB tile. */
151 protected AdvancedFunction funcargbtile;
154 * Initializes the graphics.
156 * @param __buf The buffer.
157 * @param __alpha Does the buffer actually use the alpha channel?
158 * @param __aba Advanced buffer adapter, used to translate the internal
159 * integer based buffer to other formats.
160 * @param __w The image width.
161 * @param __h The image height.
162 * @param __p The image pitch.
163 * @param __o The buffer offset.
164 * @param __atx Absolute X translation.
165 * @param __aty Absolute Y translation.
166 * @throws IllegalArgumentException If the input parameters are not
167 * correct.
168 * @throws NullPointerException On null arguments.
169 * @since 2019/03/24
171 public AdvancedGraphics(int[] __buf, boolean __alpha,
172 AdvancedBufferAdapter __aba,
173 int __w, int __h, int __p, int __o, int __atx, int __aty)
174 throws IllegalArgumentException, NullPointerException
176 if (__buf == null)
177 throw new NullPointerException("NARG");
179 // {@squirreljme.error EB0b Invalid width and/or height specified.}
180 if (__w <= 0 || __h <= 0)
181 throw new IllegalArgumentException("EB0b");
183 // {@squirreljme.error EB0c The pitch is less than the width.}
184 if (__p < __w)
185 throw new IllegalArgumentException("EB0c");
187 // {@squirreljme.error EB0d The specified parameters exceed the bounds
188 // of the array. (The width; The height; The offset; The pitch;
189 // The array length; The number of elements in the image)}
190 int numelements = (__p * __h),
191 lastelement = __o + numelements,
192 buflen = __buf.length;
193 if (__o < 0 || lastelement > buflen)
194 throw new ArrayIndexOutOfBoundsException(
195 String.format("EB0d %d %d %d %d %d %d", __w, __h,
196 __o, __p, buflen, numelements));
198 // Set
199 this.buffer = __buf;
200 this.bufferlen = buflen;
201 this.width = __w;
202 this.height = __h;
203 this.pitch = __p;
204 this.offset = __o;
205 this.numelements = numelements;
206 this.lastelement = lastelement;
207 this.hasalphachannel = __alpha;
209 // Setup absolute translation and initialize the base translation
210 // which is at the absolute origin
211 this.abstransx = __atx;
212 this.abstransy = __aty;
213 this.transx = __atx;
214 this.transy = __aty;
216 // Initial clipping rectangle has the image bounds
217 this.clipsx = 0;
218 this.clipsy = 0;
219 this.clipex = __w;
220 this.clipey = __h;
221 this.clipw = __w;
222 this.cliph = __h;
224 // Reset all initial functions
225 this.resetParameters(true);
229 * {@inheritDoc}
230 * @since 2019/03/24
232 @Override
233 public void clipRect(int __x, int __y, int __w, int __h)
235 // Translate
236 __x += this.transx;
237 __y += this.transy;
239 // Get right end coordinates
240 int ex = __x + __w,
241 ey = __y + __h;
243 // Swap X if lower
244 if (ex < __x)
246 int boop = __x;
247 __x = ex;
248 ex = boop;
251 // Same for Y
252 if (ey < __y)
254 int boop = __y;
255 __y = ey;
256 ey = boop;
259 // Never go past the end of the viewport because pixels will never
260 // be drawn in negative regions
261 if (__x < 0)
262 __x = 0;
263 if (__y < 0)
264 __y = 0;
266 // Additionally do not go past the edge ever that way the end
267 // clipping point is always valid
268 int width = this.width,
269 height = this.height;
270 if (ex > width)
271 ex = width;
272 if (ey > height)
273 ey = height;
275 // Get the old clipping bounds
276 int oldclipsx = this.clipsx,
277 oldclipsy = this.clipsy,
278 oldclipex = this.clipex,
279 oldclipey = this.clipey;
281 // Only set the clipping bounds if they exceed the previous ones
282 if (__x > oldclipsx)
283 this.clipsx = (oldclipsx = __x);
284 if (__y > oldclipsy)
285 this.clipsy = (oldclipsy = __y);
286 if (ex < oldclipex)
287 this.clipex = (oldclipex = ex);
288 if (ey < oldclipey)
289 this.clipey = (oldclipey = ey);
291 // Set width/height
292 this.clipw = this.clipex - oldclipsx;
293 this.cliph = this.clipey - oldclipsy;
297 * {@inheritDoc}
298 * @since 2019/03/24
300 @Override
301 public void copyArea(int __sx, int __sy, int __w, int __h,
302 int __dx, int __dy, int __anchor)
303 throws IllegalArgumentException, IllegalStateException
305 // Need translation coordinates
306 int tx = this.transx,
307 ty = this.transy;
309 // Image size
310 int iw = this.width,
311 ih = this.height;
313 // Translate all coordinates
314 __sx += tx;
315 __sy += ty;
316 __dx += tx;
317 __dy += ty;
319 // Perform needed anchoring
320 if ((__anchor & Graphics.HCENTER) != 0)
321 __dx -= (__w >> 1);
322 else if ((__anchor & Graphics.RIGHT) != 0)
323 __dx -= __w;
324 if ((__anchor & Graphics.VCENTER) != 0)
325 __dy -= (__h >> 1);
326 else if ((__anchor & Graphics.BOTTOM) != 0)
327 __dy -= __h;
329 // End coordinates for both
330 int sex = __sx + __w,
331 sey = __sx + __h,
332 dex = __dx + __w,
333 dey = __dx + __h;
335 // {@squirreljme.error EB0e Source region for area copy is out of
336 // bounds.}
337 if (__sx < 0 || __sy < 0 || sex > iw || sey > ih)
338 throw new IllegalArgumentException("EB0e");
340 this.__unimplemented(__dx, __dy, "copyArea");
344 * {@inheritDoc}
345 * @since 2019/03/24
347 @Override
348 public void drawArc(int __x, int __y, int __w, int __h, int __sa,
349 int __aa)
351 this.__unimplemented(__x, __y, "drawArc");
355 * {@inheritDoc}
356 * @since 2019/03/24
358 @Override
359 public void drawARGB16(short[] __data, int __off, int __scanlen,
360 int __x, int __y, int __w, int __h)
361 throws NullPointerException
363 this.__unimplemented(__x, __y, "drawARGB16");
367 * {@inheritDoc}
368 * @since 2019/03/24
370 @Override
371 public void drawChar(char __s, int __x, int __y, int __anchor)
373 // Same as drawing strings
374 this.drawString(new String(new char[]{__s}, 0, 1),
375 __x, __y, __anchor);
379 * {@inheritDoc}
380 * @since 2019/03/24
382 @Override
383 public void drawChars(char[] __s, int __o, int __l, int __x,
384 int __y, int __anchor)
385 throws NullPointerException
387 if (__s == null)
388 throw new NullPointerException("NARG");
390 // Same as drawing string
391 this.drawString(new String(__s, __o, __l),
392 __x, __y, __anchor);
396 * {@inheritDoc}
397 * @since 2019/03/24
399 @Override
400 public void drawImage(Image __i, int __x, int __y, int __anchor)
401 throws IllegalArgumentException, NullPointerException
403 if (__i == null)
404 throw new NullPointerException("NARG");
406 this.drawRegion(__i, 0, 0, __i.getWidth(), __i.getHeight(), 0,
407 __x, __y, __anchor);
411 * {@inheritDoc}
412 * @since 2019/03/24
414 @Override
415 public void drawLine(int __x1, int __y1, int __x2, int __y2)
417 // Translate all coordinates
418 int transx = this.transx,
419 transy = this.transy;
420 __x1 += transx;
421 __y1 += transy;
422 __x2 += transx;
423 __y2 += transy;
425 // Get clipping region
426 int clipsx = this.clipsx,
427 clipsy = this.clipsy,
428 clipex = this.clipex,
429 clipey = this.clipey;
431 // Perform Cohen-Sutherland line clipping
432 for (;;)
434 // Determine points that lie outside the box
435 int outa = AdvancedGraphics.__csOut(__x1, __y1,
436 clipsx, clipsy, clipex - 1,clipey - 1),
437 outb = AdvancedGraphics.__csOut(__x2, __y2, clipsx,
438 clipsy, clipex - 1, clipey - 1);
440 // Both points are outside the box, do nothing
441 if ((outa & outb) != 0)
442 return;
444 // Both points are inside the box, use this line
445 if (outa == 0 && outb == 0)
446 break;
448 // Only the second point is outside, swap the points so that the
449 // first point is outside and the first is not
450 if (outa == 0)
452 // Swap X
453 int boop = __x1;
454 __x1 = __x2;
455 __x2 = boop;
457 // Swap Y
458 boop = __y1;
459 __y1 = __y2;
460 __y2 = boop;
462 // Swap clip flags
463 boop = outb;
464 outb = outa;
465 outa = boop;
468 // The point is clipped
469 if (outa != 0)
471 // Differences of points
472 int dx = __x2 - __x1,
473 dy = __y2 - __y1;
475 // Clips above the box
476 if ((outa & AdvancedGraphics._CLIP_ABOVE) != 0)
478 __x1 += dx * (clipey - __y1) / dy;
479 __y1 = clipey - 1;
482 // Clips below
483 else if ((outa & AdvancedGraphics._CLIP_BELOW) != 0)
485 __x1 += dx * (clipsy - __y1) / dy;
486 __y1 = clipsy;
489 // Clips the right side
490 else if ((outa & AdvancedGraphics._CLIP_RIGHT) != 0)
492 __y1 += dy * (clipex - __x1) / dx;
493 __x1 = clipex - 1;
496 // Clips the left side
497 else if ((outa & AdvancedGraphics._CLIP_LEFT) != 0)
499 __y1 += dy * (clipsx - __x1) / dx;
500 __x1 = clipsx;
505 // Have lines which always go to the right
506 if (__x2 < __x1)
508 int boopx = __x1,
509 boopy = __y1;
510 __x1 = __x2;
511 __y1 = __y2;
512 __x2 = boopx;
513 __y2 = boopy;
516 // The resulting line should never be out of bounds
517 if (__x1 < clipsx || __x2 < clipsx || __y1 < clipsy || __y2 < clipsy ||
518 __x1 > clipex || __x2 > clipex || __y1 > clipey || __y2 > clipey)
519 return;
521 // Forward depending on blending and/or dots
524 this.funcline.function(this,
525 new int[]{__x1, __y1, __x2, __y2},
526 null);
529 // Exception happened when drawing a line
530 catch (IndexOutOfBoundsException e)
532 Debugging.debugNote("Line (%d, %d) -> (%d, %d)", __x1, __y1,
533 __x2, __y2);
538 * {@inheritDoc}
539 * @since 2019/03/24
541 @Override
542 public void drawRGB(int[] __data, int __off, int __scanlen,
543 int __x, int __y, int __w, int __h, boolean __alpha)
544 throws NullPointerException
546 if (__data == null)
547 throw new NullPointerException("NARG");
549 // Transform
550 __x += this.transx;
551 __y += this.transy;
553 // Determine ending position
554 int ex = __x + __w;
555 int ey = __y + __h;
557 // Get clipping region
558 int clipsx = this.clipsx;
559 int clipsy = this.clipsy;
560 int clipex = this.clipex;
561 int clipey = this.clipey;
563 // Box is completely outside the bounds of the clip, do not draw
564 if (ex < clipsx || __x >= clipex || ey < clipsy || __y >= clipey)
565 return;
567 // Determine sub-clipping area
568 int subX = Math.max(0, clipsx - __x);
569 int subY = Math.max(0, clipsy - __y);
571 // Clip into bounds
572 if (__x < clipsx)
573 __x = clipsx;
574 if (__y < clipsy)
575 __y = clipsy;
577 // Check end coordinate
578 if (ex >= clipex)
579 ex = clipex;
580 if (ey >= clipey)
581 ey = clipey;
583 // New tile size
584 int tw = ex - __x;
585 int th = ey - __y;
587 // We might have multiplied alpha blending, or just normal blending
588 // If __alpha is true then this is 32-bit RGBA!
591 if (__alpha)
592 this.funcargbtile.function(this,
593 new int[]{__off, __scanlen, __x, __y, tw, th, subX, subY},
594 new Object[]{__data});
595 else
596 this.funcrgbtile.function(this,
597 new int[]{__off, __scanlen, __x, __y, tw, th, subX, subY},
598 new Object[]{__data});
600 catch (IndexOutOfBoundsException e)
602 Debugging.debugNote(
603 "drawRGBTile(buffer[%d]=%s, bufferlen=%d, w=%d, h=%d, " +
604 "pitch=%d, offset=%d -> " +
605 "data[%d]=%s, w=%d, h=%d, off=%d, " +
606 "scanlen=%d, " +
607 "x=%d, y=%d, tw=%d, th=%d, subX=%d, subY=%d)",
608 this.buffer.length, this.buffer, this.bufferlen,
609 this.width, this.height, this.pitch, this.offset,
610 __data.length, __data, __w, __h, __off, __scanlen, __x, __y,
611 tw, th, subX, subY);
616 * {@inheritDoc}
617 * @since 2019/03/24
619 @Override
620 public void drawRGB16(short[] __data, int __off, int __scanlen,
621 int __x, int __y, int __w, int __h)
622 throws NullPointerException
624 this.__unimplemented(__x, __y, "drawRGB16");
628 * {@inheritDoc}
629 * @since 2019/03/24
631 @Override
632 public void drawRect(int __x, int __y, int __w, int __h)
634 // The width and height are increased by a single pixel
635 __w += 1;
636 __h += 1;
638 // For now just cheat and draw four lines
639 int ex = __x + __w,
640 ey = __y + __h;
642 this.drawLine(__x, __y, ex, __y);
643 this.drawLine(__x, ey, ex, ey);
644 this.drawLine(__x, __y, __x, ey);
645 this.drawLine(ex, __y, ex, ey);
649 * {@inheritDoc}
650 * @since 2019/03/24
652 @Override
653 public void drawRegion(Image __src, int __xsrc, int __ysrc,
654 int __wsrc, int __hsrc, int __trans, int __xdest, int __ydest,
655 int __anch)
656 throws IllegalArgumentException, NullPointerException
658 if (__src == null)
659 throw new NullPointerException("NARG");
661 this.__drawRegion(__src, __xsrc, __ysrc, __wsrc, __hsrc, __trans,
662 __xdest, __ydest, __anch, __wsrc, __hsrc, true);
666 * {@inheritDoc}
667 * @since 2019/03/24
669 @Override
670 public void drawRegion(Image __src, int __xsrc, int __ysrc,
671 int __wsrc, int __hsrc, int __trans, int __xdest, int __ydest,
672 int __anch, int __wdest, int __hdest)
673 throws IllegalArgumentException, NullPointerException
675 if (__src == null)
676 throw new NullPointerException("NARG");
678 this.__drawRegion(__src, __xsrc, __ysrc, __wsrc, __hsrc, __trans,
679 __xdest, __ydest, __anch, __wdest, __hdest, false);
683 * {@inheritDoc}
684 * @since 2019/03/24
686 @Override
687 public void drawRoundRect(int __x, int __y, int __w, int __h,
688 int __aw, int __ah)
690 this.__unimplemented(__x, __y, "drawRoundRect");
694 * {@inheritDoc}
695 * @since 2019/03/24
697 @Override
698 public void drawString(String __s, int __x, int __y,
699 int __anchor)
700 throws NullPointerException
702 if (__s == null)
703 throw new NullPointerException("NARG");
705 this.__drawText(this.__buildText(__s), __x, __y, __anchor);
709 * {@inheritDoc}
710 * @since 2019/03/24
712 @Override
713 public void drawSubstring(String __s, int __o, int __l, int __x,
714 int __y, int __anchor)
715 throws NullPointerException, StringIndexOutOfBoundsException
717 if (__s == null)
718 throw new NullPointerException("NARG");
719 if (__o < 0 || __l < 0 || (__o + __l) > __s.length())
720 throw new StringIndexOutOfBoundsException("IOOB");
722 this.__drawText(this.__buildText(__s.substring(__o, __o + __l)),
723 __x, __y, __anchor);
727 * {@inheritDoc}
728 * @since 2019/03/24
730 @Override
731 public void drawText(Text __t, int __x, int __y)
733 this.__drawText(__t, __x, __y, 0);
737 * {@inheritDoc}
738 * @since 2019/03/24
740 @Override
741 public void fillArc(int __x, int __y, int __w, int __h, int __sa,
742 int __aa)
744 this.__unimplemented(__x, __y, "fillArc");
748 * {@inheritDoc}
749 * @since 2019/03/24
751 @Override
752 public void fillRect(int __x, int __y, int __w, int __h)
754 // Get actual end points
755 int ex = __x + __w,
756 ey = __y + __h;
758 // Translate all coordinates
759 int transx = this.transx,
760 transy = this.transy;
761 __x += transx;
762 __y += transy;
763 ex += transx;
764 ey += transy;
766 // Force lower X
767 if (ex < __x)
769 int boop = ex;
770 ex = __x;
771 __x = boop;
774 // Force lower Y
775 if (ey < __y)
777 int boop = ey;
778 ey = __y;
779 __y = boop;
782 // Get clipping region
783 int clipsx = this.clipsx,
784 clipsy = this.clipsy,
785 clipex = this.clipex - 1,
786 clipey = this.clipey - 1;
788 // Never clip past the left/top
789 if (__x < clipsx)
790 __x = clipsx;
791 if (__y < clipsy)
792 __y = clipsy;
794 // Never clip past the right/bottom
795 if (ex > clipex)
796 ex = clipex;
797 if (ey > clipey)
798 ey = clipey;
800 // Calculate actual dimensions used
801 __w = ex - __x;
802 __h = ey - __y;
804 // Call function
805 this.funcfillrect.function(this,
806 new int[]{__x, __y, ex, ey, __w, __h},
807 null);
811 * {@inheritDoc}
812 * @since 2019/03/24
814 @Override
815 public void fillRoundRect(int __x, int __y, int __w, int __h,
816 int __aw, int __ah)
818 this.__unimplemented(__x, __y, "fillRoundRect");
822 * {@inheritDoc}
823 * @since 2019/03/24
825 @Override
826 public void fillTriangle(int __x1, int __y1, int __x2, int __y2,
827 int __x3, int __y3)
829 this.__unimplemented(__x1, __y1, "fillTriangle");
833 * {@inheritDoc}
834 * @since 2019/03/24
836 @Override
837 public int getAlpha()
839 return (this.color >> 24) & 0xFF;
843 * {@inheritDoc}
844 * @since 2019/03/24
846 @Override
847 public int getAlphaColor()
849 return this.color;
853 * {@inheritDoc}
854 * @since 2019/03/24
856 @Override
857 public int getBlendingMode()
859 return this.blendmode;
863 * {@inheritDoc}
864 * @since 2019/03/24
866 @Override
867 public int getBlueComponent()
869 return (this.color) & 0xFF;
873 * Returns the element in the input array which represents the end of the
874 * clipping rectangle.
876 * @return The element which contains the end of the clipping rectangle.
877 * @since 2019/03/24
879 public final int getClipElementEnd()
881 // Subtract one from the Y because it is on the next row
882 return this.offset + (((this.pitch * (this.clipey - 1)) +
883 (this.clipex)));
887 * Returns the element in the input array which represents the start of
888 * the clipping rectangle.
890 * @return The element which contains the start of the clipping rectangle.
891 * @since 2019/03/24
893 public final int getClipElementStart()
895 return this.offset + (((this.pitch * this.clipsy) + this.clipsx));
899 * {@inheritDoc}
900 * @since 2019/03/24
902 @Override
903 public int getClipHeight()
905 return this.cliph;
909 * {@inheritDoc}
910 * @since 2019/03/24
912 @Override
913 public int getClipWidth()
915 return this.clipw;
919 * {@inheritDoc}
920 * @since 2019/03/24
922 @Override
923 public int getClipX()
925 return this.clipsx - this.transx;
929 * {@inheritDoc}
930 * @since 2019/03/24
932 @Override
933 public int getClipY()
935 return this.clipsy - this.transy;
939 * {@inheritDoc}
940 * @since 2019/03/24
942 @Override
943 public int getColor()
945 return this.color & 0xFFFFFF;
949 * {@inheritDoc}
950 * @since 2019/03/24
952 @Override
953 public int getDisplayColor(int __rgb)
955 // Just use the original input color, without the alpha channel
956 return __rgb & 0xFFFFFF;
960 * {@inheritDoc}
961 * @since 2019/03/24
963 @Override
964 public Font getFont()
966 Font rv = this.font;
967 if (rv == null)
968 rv = Font.getDefaultFont();
969 return rv;
973 * {@inheritDoc}
974 * @since 2019/03/24
976 @Override
977 public int getGrayScale()
979 return (this.getRedComponent() + this.getGreenComponent() + this
980 .getBlueComponent()) / 3;
984 * {@inheritDoc}
985 * @since 2019/03/24
987 @Override
988 public int getGreenComponent()
990 return (this.color >> 8) & 0xFF;
994 * {@inheritDoc}
995 * @since 2019/03/24
997 @Override
998 public int getRedComponent()
1000 return (this.color >> 16) & 0xFF;
1004 * {@inheritDoc}
1005 * @since 2019/03/24
1007 @Override
1008 public int getStrokeStyle()
1010 return this.strokestyle;
1014 * {@inheritDoc}
1015 * @since 2019/03/24
1017 @Override
1018 public int getTranslateX()
1020 return this.transx - this.abstransx;
1024 * {@inheritDoc}
1025 * @since 2019/03/24
1027 @Override
1028 public int getTranslateY()
1030 return this.transy - this.abstransy;
1034 * Resets all parameters of the graphics output.
1036 * @param __clip If {@code true} then the clip is also reset.
1037 * @since 2019/03/24
1039 public void resetParameters(boolean __clip)
1041 // Clear translation
1042 this.transx = this.abstransx;
1043 this.transy = this.abstransy;
1045 // Reset clip also
1046 if (__clip)
1048 int width = this.width,
1049 height = this.height;
1051 this.clipsx = 0;
1052 this.clipsy = 0;
1053 this.clipex = width;
1054 this.clipey = height;
1055 this.clipw = width;
1056 this.cliph = height;
1059 // Always reset these
1060 this.setAlphaColor(0xFF000000);
1061 this.setBlendingMode(Graphics.SRC_OVER);
1062 this.setStrokeStyle(Graphics.SOLID);
1063 this.setFont(null);
1067 * {@inheritDoc}
1068 * @since 2019/03/24
1070 @Override
1071 public void setAlpha(int __a)
1072 throws IllegalArgumentException
1074 this.setAlphaColor(__a, this.getRedComponent(), this.getGreenComponent(),
1075 this.getBlueComponent());
1079 * {@inheritDoc}
1080 * @since 2019/03/24
1082 @Override
1083 public void setAlphaColor(int __argb)
1085 // Set the original color directly
1086 this.color = __argb;
1088 // Determine if blending is to be performed or it is just directly
1089 // setting values, blending is only performed if the alpha channel
1090 // is not fully opaque and blending is permitted
1091 int alpha = (__argb >>> 24);
1092 boolean doblending = (this.candoblending && alpha != 0xFF);
1094 // Set internal blend mode
1095 this.doblending = doblending;
1097 // Set painting colors
1098 this.paintalpha = alpha;
1099 this.paintcolor = __argb & 0xFFFFFF;
1100 this.paintcolorhigh = __argb | 0xFF000000;
1101 this.paintalphacolor = __argb;
1103 // Update functions
1104 this.__updateFunctions();
1108 * {@inheritDoc}
1109 * @since 2019/03/24
1111 @Override
1112 public void setAlphaColor(int __a, int __r, int __g, int __b)
1113 throws IllegalArgumentException
1115 // {@squirreljme.error EB0f Color out of range. (Alpha; Red; Green;
1116 // Blue)}
1117 if (__a < 0 || __a > 255 || __r < 0 || __r > 255 ||
1118 __g < 0 || __g > 255 || __b < 0 || __b > 255)
1119 throw new IllegalArgumentException(String.format(
1120 "EB0f %d %d %d %d", __a, __r, __g, __b));
1122 // Set
1123 this.setAlphaColor((__a << 24) | (__r << 16) | (__g << 8) | __b);
1127 * {@inheritDoc}
1128 * @since 2019/03/24
1130 @Override
1131 public void setBlendingMode(int __m)
1132 throws IllegalArgumentException
1134 boolean candoblending,
1135 oldcandoblending = this.candoblending;
1137 // Just use source pixels
1138 if (__m == Graphics.SRC)
1140 // {@squirreljme.error EB0g Cannot set the overlay blending mode
1141 // because this graphics context does not have the alpha channel.}
1142 if (!this.hasalphachannel)
1143 throw new IllegalArgumentException("EB0g");
1145 candoblending = false;
1148 // Perform blending since this is the default mode
1149 else if (__m == Graphics.SRC_OVER)
1151 candoblending = true;
1154 // {@squirreljme.error EB0h Unknown blending mode.}
1155 else
1156 throw new IllegalArgumentException("EB0h");
1158 // Set
1159 this.blendmode = __m;
1160 this.candoblending = candoblending;
1162 // If the blending mode has changed then possible blending tables
1163 // need to be recalculated accordingly
1164 if (candoblending != oldcandoblending)
1165 this.setAlphaColor(this.getAlphaColor());
1167 // Update functions
1168 this.__updateFunctions();
1172 * {@inheritDoc}
1173 * @since 2019/03/24
1175 @Override
1176 public void setClip(int __x, int __y, int __w, int __h)
1178 // Translate
1179 __x += this.transx;
1180 __y += this.transy;
1182 // Get right end coordinates
1183 int ex = __x + __w,
1184 ey = __y + __h;
1186 // Swap X if lower
1187 if (ex < __x)
1189 int boop = __x;
1190 __x = ex;
1191 ex = boop;
1194 // Same for Y
1195 if (ey < __y)
1197 int boop = __y;
1198 __y = ey;
1199 ey = boop;
1202 // Never go past the end of the viewport because pixels will never
1203 // be drawn in negative regions
1204 if (__x < 0)
1205 __x = 0;
1206 if (__y < 0)
1207 __y = 0;
1209 // Additionally do not go past the edge ever that way the end
1210 // clipping point is always valid
1211 int width = this.width,
1212 height = this.height;
1213 if (ex > width)
1214 ex = width;
1215 if (ey > height)
1216 ey = height;
1218 // Set
1219 this.clipsx = __x;
1220 this.clipsy = __y;
1221 this.clipex = ex;
1222 this.clipey = ey;
1224 // Set width/height
1225 this.clipw = ex - __x;
1226 this.cliph = ey - __y;
1230 * {@inheritDoc}
1231 * @since 2019/03/24
1233 @Override
1234 public void setColor(int __rgb)
1236 this.setAlphaColor((this.getAlphaColor() & 0xFF_000000) |
1237 (__rgb & 0x00_FFFFFF));
1241 * {@inheritDoc}
1242 * @since 2019/03/24
1244 @Override
1245 public void setColor(int __r, int __g, int __b)
1246 throws IllegalArgumentException
1248 this.setAlphaColor(this.getAlpha(), __r, __g, __b);
1252 * {@inheritDoc}
1253 * @since 2019/03/24
1255 @Override
1256 public void setFont(Font __font)
1258 // Just set it
1259 this.font = __font;
1263 * {@inheritDoc}
1264 * @since 2019/03/24
1266 @Override
1267 public void setGrayScale(int __v)
1269 this.setAlphaColor(this.getAlpha(), __v, __v, __v);
1273 * {@inheritDoc}
1274 * @since 2019/03/24
1275 * @param __style
1277 @Override
1278 public void setStrokeStyle(int __style)
1279 throws IllegalArgumentException
1281 // {@squirreljme.error EB0i Illegal stroke style.}
1282 if (__style != Graphics.SOLID && __style != Graphics.DOTTED)
1283 throw new IllegalArgumentException("EB0i");
1285 // Set
1286 this.strokestyle = __style;
1287 this.dotstroke = (__style == Graphics.DOTTED);
1289 // Update functions
1290 this.__updateFunctions();
1294 * {@inheritDoc}
1295 * @since 2019/03/24
1297 @Override
1298 public void translate(int __x, int __y)
1300 this.transx += __x;
1301 this.transy += __y;
1305 * Builds and returns a text object for usage.
1307 * @param __s The string used.
1308 * @return A new text object.
1309 * @throws NullPointerException On null arguments.
1310 * @since 2018/11/29
1312 private Text __buildText(String __s)
1313 throws NullPointerException
1315 if (__s == null)
1316 throw new NullPointerException("NARG");
1318 // Get the font, or fallback to the default if it was not set
1319 Font font = this.getFont();
1321 // Setup, use a zero height for now since it will be calculated after
1322 // the font and such has been set
1323 Text rv = new Text(__s,
1324 font.stringWidth(__s), 0);
1326 // Set text properties
1327 if (font != null)
1328 rv.setFont(font);
1329 rv.setForegroundColor(this.color);
1331 // Set the height to the required height of the box now that the
1332 // parameters have been set
1333 rv.setHeight(rv.getRequiredHeight());
1335 return rv;
1339 * Draws region.
1341 * @param __src Source image.
1342 * @param __xsrc X source.
1343 * @param __ysrc Y source.
1344 * @param __wsrc W source.
1345 * @param __hsrc H source.
1346 * @param __trans Translation.
1347 * @param __xdest X destination.
1348 * @param __ydest Y destination.
1349 * @param __anch Anchor.
1350 * @param __wdest W destination.
1351 * @param __hdest H destination.
1352 * @param __dswap Swap destinations on rotate?
1353 * @throws IllegalArgumentException If the input is not valid.
1354 * @throws NullPointerException On null arguments.
1355 * @since 2019/04/18
1357 private void __drawRegion(Image __src, int __xsrc, int __ysrc,
1358 int __wsrc, int __hsrc, int __trans, int __xdest, int __ydest,
1359 int __anch, int __wdest, int __hdest, boolean __dswap)
1360 throws IllegalArgumentException, NullPointerException
1362 if (__src == null)
1363 throw new NullPointerException("NARG");
1365 // Is alpha used?
1366 boolean alpha = __src.hasAlpha();
1368 // Extract image pixel data
1369 int numpixels = __wsrc * __hsrc;
1370 int[] data = new int[numpixels];
1371 __src.getRGB(data, 0, __wsrc, __xsrc, __ysrc, __wsrc, __hsrc);
1373 // Perform the transformation, possibly returning a new data buffer
1374 int[] transdim = new int[]{__wsrc, __hsrc, __wdest, __hdest};
1375 data = __transform(__trans, data, __wsrc, __hsrc, transdim,
1376 __dswap);
1378 // Re-read the new image sizes!
1379 __wsrc = transdim[0];
1380 __hsrc = transdim[1];
1381 __wdest = transdim[2];
1382 __hdest = transdim[3];
1384 // Anchor horizontally?
1385 if ((__anch & Graphics.HCENTER) == Graphics.HCENTER)
1386 __xdest -= __wdest >> 1;
1388 // Anchor right?
1389 else if ((__anch & Graphics.RIGHT) == Graphics.RIGHT)
1390 __xdest -= __wdest;
1392 // Anchor middle?
1393 if ((__anch & Graphics.VCENTER) == Graphics.VCENTER)
1394 __ydest -= __hdest >> 1;
1396 // Anchor bottom?
1397 else if ((__anch & Graphics.BOTTOM) == Graphics.BOTTOM)
1398 __ydest -= __hdest;
1400 // If this is non-stretched we can just use the standard RGB
1401 // drawing function!
1402 if (__wsrc == __wdest && __hsrc == __hdest)
1403 this.drawRGB(data, 0, __wsrc, __xdest, __ydest,
1404 __wsrc, __hsrc, alpha);
1406 // Use stretchy draw
1407 else
1408 this.__drawRGBStretched(data, 0, __wsrc, __xdest, __ydest,
1409 __wsrc, __hsrc, alpha, __wdest, __hdest);
1413 * Draws stretched RGB.
1415 * @param __data The data to draw.
1416 * @param __off The offset into the array.
1417 * @param __scanlen The scan length.
1418 * @param __x X position.
1419 * @param __y Y position.
1420 * @param __wsrc Width of source.
1421 * @param __hsrc Height of source.
1422 * @param __alpha Use alpha channel?
1423 * @param __wdest Width of destination.
1424 * @param __hdest Height of destination.
1425 * @throws NullPointerException On null arguments.
1426 * @since 2019/04/15
1428 private void __drawRGBStretched(int[] __data, int __off, int __scanlen,
1429 int __x, int __y, int __wsrc, int __hsrc, boolean __alpha,
1430 int __wdest, int __hdest)
1431 throws NullPointerException
1433 if (__data == null)
1434 throw new NullPointerException("NARG");
1436 this.__unimplemented(__x, __y, "drawRGBStretched");
1440 * Draws the given text object.
1442 * @param __t The text object to draw.
1443 * @param __x The X position.
1444 * @param __y The Y position.
1445 * @param __anchor The, this just adjusts determines how the actual text
1446 * box region is drawn. If baseline is used, Y is just offset by the
1447 * baseline for the first character and not the entire block size.
1448 * @throws NullPointerException On null arguments.
1449 * @since 2018/11/29
1451 final void __drawText(Text __t, int __x, int __y, int __anchor)
1452 throws NullPointerException
1454 if (__t == null)
1455 throw new NullPointerException("NARG");
1457 // Translate to the displayed coordinate space
1458 __x += this.transx;
1459 __y += this.transy;
1461 // Setup text state
1462 __TextState__ ts = new __TextState__();
1464 // Anchoring
1465 ts.textw = __t.getWidth();
1466 ts.texth = __t.getHeight();
1467 if ((__anchor & Graphics.RIGHT) != 0)
1468 __x -= ts.textw;
1469 else if ((__anchor & Graphics.HCENTER) != 0)
1470 __x -= (ts.textw >> 1);
1471 if ((__anchor & Graphics.BOTTOM) != 0)
1472 __y -= ts.texth;
1473 else if ((__anchor & Graphics.VCENTER) != 0)
1474 __y -= (ts.texth >> 1);
1476 // Get clipping region
1477 ts.clipsx = this.clipsx;
1478 ts.clipsy = this.clipsy;
1479 ts.clipex = this.clipex - 1;
1480 ts.clipey = this.clipey - 1;
1482 // Wanting to draw a bunch of text completely out of the clip? Ignore
1483 if (__x >= ts.clipex || __y >= ts.clipey)
1484 return;
1486 // Trying to draw the text completely out of the clip as well?
1487 ts.tex = __x + ts.textw;
1488 ts.tey = __y + ts.texth;
1489 if (ts.tex < ts.clipsx || ts.tey < ts.clipsy)
1490 return;
1492 // The text box acts as an extra clip, so force everything to clip
1493 // in there
1494 if (__x > ts.clipsx)
1495 ts.clipsx = __x;
1496 if (ts.tex < ts.clipex)
1497 ts.clipex = ts.tex;
1498 if (__y > ts.clipsy)
1499 ts.clipsy = __y;
1500 if (ts.tey < ts.clipey)
1501 ts.clipey = ts.tey;
1503 // Cache the default font in the event it is never changed ever
1504 ts.lastfont = __t.getFont();
1505 ts.sqf = SQFFont.cacheFont(ts.lastfont);
1506 ts.bmp = new byte[ts.sqf.charbitmapsize];
1507 ts.pixelheight = ts.sqf.pixelheight;
1508 ts.bitsperscan = ts.sqf.bitsperscan;
1510 // Background color to use
1511 ts.bgcol = __t.getBackgroundColor();
1512 ts.hasbg = ((ts.bgcol & 0xFF_000000) != 0);
1514 // Need to store the properties since drawing of the text will
1515 // change how characters are drawn
1516 ts.oldcolor = this.getAlphaColor();
1519 // Read in all the text characters
1520 int n = __t.getTextLength();
1521 String chars = __t.getText(0, n);
1523 // Draw each character according to their metrics
1524 for (int i = 0; i < n; i++)
1526 // Ignore certain characters
1527 char c = chars.charAt(i);
1528 if (c == '\r' || c == '\n')
1529 continue;
1531 // Need to find the SQF for this font again?
1532 Font drawfont = __t.getFont(i);
1533 if (drawfont != ts.lastfont)
1535 ts.lastfont = drawfont;
1536 ts.sqf = SQFFont.cacheFont(ts.lastfont);
1537 ts.bmp = new byte[ts.sqf.charbitmapsize];
1538 ts.pixelheight = ts.sqf.pixelheight;
1539 ts.bitsperscan = ts.sqf.bitsperscan;
1542 // Get the metrics for the character
1543 __t.getCharExtent(i, ts.metrics);
1545 // Calculate the draw position of the character
1546 int dsx = __x + ts.metrics[0];
1547 int dsy = __y + ts.metrics[1];
1548 int dex = dsx + ts.metrics[2];
1549 int dey = dsy + ts.metrics[3];
1551 // Completely out of bounds, ignore because we cannot draw it
1552 // anyway
1553 if (dsx >= clipex || dex <= 0 ||
1554 dsy >= clipey || dey <= 0)
1555 continue;
1557 // Map character index to the SQF
1558 char mc = SQFFont.mapChar(c);
1560 // Base scan offsets and such
1561 int scanoff = 0;
1562 int scanlen = ts.sqf.charWidth(mc);
1563 int lineoff = 0;
1564 int linelen = ts.pixelheight;
1566 // Off the left side?
1567 if (dsx < ts.clipsx)
1569 int diff = ts.clipsx - dsx;
1570 scanoff += diff;
1571 scanlen -= diff;
1573 // Reset to clip bound
1574 dsx = ts.clipsx;
1577 // Off the right side
1578 if (dex > ts.clipex)
1579 scanlen -= (dex - ts.clipex);
1581 // Off the top?
1582 if (dsy < ts.clipsy)
1584 int diff = ts.clipsy - dsy;
1585 lineoff += diff;
1586 linelen -= diff;
1588 // Reset to clip bound
1589 dsy = ts.clipsy;
1592 // Off the bottom
1593 if (dey > ts.clipey)
1594 linelen -= (dey - ts.clipey);
1596 // Load the character bitmap
1597 int bps = ts.sqf.loadCharBitmap(mc, ts.bmp);
1599 // Draw background?
1600 if (ts.hasbg)
1602 // Set needed color
1603 this.setAlphaColor(ts.bgcol);
1605 // Perform draw operation
1606 this.funcfillrect.function(this, ts.loadIntArgs(dsx, dsy,
1607 dsx + (scanlen - scanoff), dsy + (linelen - lineoff),
1608 scanlen - scanoff, linelen - lineoff), ts.chobj);
1611 // Set color to the foreground color of this character
1612 this.setAlphaColor(__t.getForegroundColor(i));
1614 // Setup the draw and do it
1615 this.funccharbmp.function(this, ts.loadIntArgs(this.color, dsx, dsy,
1616 bps, scanoff, scanlen, lineoff, linelen),
1617 ts.loadObject(ts.bmp));
1621 // Just in case revert properties
1622 finally
1624 this.setAlphaColor(ts.oldcolor);
1629 * Draw a string which just says not implemented.
1631 * @param __x X Coordinate.
1632 * @param __y Y Coordinate.
1633 * @param __txt The message text.
1634 * @since 2019/03/25
1636 private void __unimplemented(int __x, int __y, String __txt)
1637 throws NullPointerException
1639 if (__txt == null)
1640 throw new NullPointerException("NARG");
1642 // Just draw crosshair and a string
1643 this.drawLine(__x - 5, __y, __x + 5, __y);
1644 this.drawLine(__x, __y - 5, __x, __y + 5);
1645 this.drawString(__txt, __x, __y, 0);
1649 * Updates the graphics drawing functions to what is needed.
1651 * @since 2019/03/24
1653 private void __updateFunctions()
1655 boolean doblending = this.doblending,
1656 dotstroke = this.dotstroke;
1657 int blendmode = this.blendmode;
1659 // Blending
1660 if (doblending)
1662 this.funcfillrect = AdvancedFunction.FILLRECT_BLEND;
1663 this.funccharbmp = AdvancedFunction.CHARBITMAP_BLEND;
1664 this.funcrgbtile = AdvancedFunction.RGBTILE_BLEND;
1665 this.funcargbtile = AdvancedFunction.ARGBTILE_BLEND;
1667 // Dotted
1668 if (dotstroke)
1670 this.funcline = AdvancedFunction.LINE_BLEND_DOT;
1673 // Not dotted
1674 else
1676 this.funcline = AdvancedFunction.LINE_BLEND_NODOT;
1680 // Not blending
1681 else
1683 this.funcfillrect = AdvancedFunction.FILLRECT_NOBLEND;
1684 this.funccharbmp = AdvancedFunction.CHARBITMAP_NOBLEND;
1685 this.funcrgbtile = AdvancedFunction.RGBTILE_NOBLEND;
1686 this.funcargbtile = AdvancedFunction.ARGBTILE_NOBLEND;
1688 // Dotted
1689 if (dotstroke)
1691 this.funcline = AdvancedFunction.LINE_NOBLEND_DOT;
1694 // Not dotted
1695 else
1697 this.funcline = AdvancedFunction.LINE_NOBLEND_NODOT;
1703 * Determines the Cohen-Sutherland clipping flags.
1705 * @param __x Input X coordinate.
1706 * @param __y Input Y coordinate.
1707 * @param __csx Clipping box starting X.
1708 * @param __csy Clipping box starting Y.
1709 * @param __cex Clipping box ending X.
1710 * @param __cey Clipping box ending Y.
1711 * @return The clipping bit flags.
1712 * @since 2017/09/10
1714 private static int __csOut(int __x, int __y, int __csx, int __csy,
1715 int __cex, int __cey)
1717 int rv = 0;
1719 // Clips above or below?
1720 if (__y > __cey)
1721 rv |= AdvancedGraphics._CLIP_ABOVE;
1722 else if (__y < __csy)
1723 rv |= AdvancedGraphics._CLIP_BELOW;
1725 // Clips right or left?
1726 if (__x > __cex)
1727 rv |= AdvancedGraphics._CLIP_RIGHT;
1728 else if (__x < __csx)
1729 rv |= AdvancedGraphics._CLIP_LEFT;
1731 return rv;
1735 * Transforms the data in the buffer.
1737 * @param __trans The transformation to perform.
1738 * @param __data The input data.
1739 * @param __wsrc The width of the source.
1740 * @param __hsrc The width of the destination.
1741 * @param __dimout Output dimensions.
1742 * @param __dswap Swap destinations?
1743 * @return The resulting data is translated, this may be the same as
1744 * {@code __data}.
1745 * @throws NullPointerException On null arguments.
1746 * @since 2019/04/15
1748 private static int[] __transform(int __trans, int[] __data,
1749 int __wsrc, int __hsrc, int[] __dimout, boolean __dswap)
1750 throws NullPointerException
1752 if (__data == null || __dimout == null)
1753 throw new NullPointerException("NARG");
1755 // Destination width and height
1756 int wdest = __wsrc,
1757 hdest = __hsrc;
1759 // Determine the transformation functions to use. There are just three
1760 // primitive transformation functions: flip horizontally, then
1761 // flip vertically, then rotate 90 degrees clockwise. This handles
1762 // every transformation which fill every single bit.
1763 byte xform = 0;
1764 switch (__trans)
1766 // These bits represent the stuff to do! == 0b9VH;
1767 case Sprite.TRANS_NONE: xform = 0b000; break;
1768 case Sprite.TRANS_MIRROR: xform = 0b001; break;
1769 case Sprite.TRANS_MIRROR_ROT180: xform = 0b010; break;
1770 case Sprite.TRANS_ROT180: xform = 0b011; break;
1771 case Sprite.TRANS_ROT90: xform = 0b100; break;
1772 case Sprite.TRANS_MIRROR_ROT90: xform = 0b101; break;
1773 case Sprite.TRANS_MIRROR_ROT270: xform = 0b110; break;
1774 case Sprite.TRANS_ROT270: xform = 0b111; break;
1775 // These bits represent the stuff to do! == 0b9VH;
1778 // Mirror horizontally?
1779 if ((xform & 0b001) != 0)
1780 for (int y = 0; y < hdest; y++)
1782 int dx = wdest * y,
1783 de = (dx + wdest) - 1;
1784 for (int x = 0, n = (wdest >> 1); x < n; x++)
1786 int t = __data[de];
1787 __data[de--] = __data[dx];
1788 __data[dx++] = t;
1792 // Mirror vertically?
1793 if ((xform & 0b010) != 0)
1794 for (int ya = 0, yn = __hsrc >> 1; ya < yn; ya++)
1796 int ra = __wsrc * ya,
1797 rb = (__wsrc * (__hsrc - ya)) - __wsrc;
1799 // Flip
1800 for (int x = 0; x < __wsrc; x++)
1802 int t = __data[rb];
1803 __data[rb++] = __data[ra];
1804 __data[ra++] = t;
1808 // Rotate 90 degrees clockwise
1809 if ((xform & 0b100) != 0)
1811 // Original copy
1812 int[] orig = __data.clone();
1814 // Swap the X and Y pixels first
1815 int ttop = hdest - 1;
1816 for (int y = 0; y < hdest; y++)
1817 for (int x = 0; x < wdest; x++)
1819 int ps = (wdest * y) + x,
1820 pd = (hdest * x) + (ttop - y);
1822 __data[pd] = orig[ps];
1825 // The output width and height are flipped
1826 __dimout[0] = hdest;
1827 __dimout[1] = wdest;
1829 // Swap destinations as well?
1830 if (__dswap)
1832 int t = __dimout[2];
1833 __dimout[2] = __dimout[3];
1834 __dimout[3] = t;
1838 // Otherwise use the same target dimensions
1839 else
1841 __dimout[0] = wdest;
1842 __dimout[1] = hdest;
1845 // Return the data
1846 return __data;