1 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // ---------------------------------------------------------------------------
10 package cc
.squirreljme
.runtime
.lcdui
.mle
;
12 import cc
.squirreljme
.jvm
.mle
.PencilShelf
;
13 import cc
.squirreljme
.jvm
.mle
.brackets
.PencilBracket
;
14 import cc
.squirreljme
.jvm
.mle
.constants
.UIPixelFormat
;
15 import cc
.squirreljme
.jvm
.mle
.exceptions
.MLECallError
;
16 import cc
.squirreljme
.jvm
.mle
.scritchui
.brackets
.ScritchPencilBracket
;
17 import cc
.squirreljme
.runtime
.cldc
.annotation
.SquirrelJMEVendorApi
;
18 import cc
.squirreljme
.runtime
.cldc
.debug
.Debugging
;
19 import cc
.squirreljme
.runtime
.lcdui
.scritchui
.DisplayManager
;
20 import javax
.microedition
.lcdui
.Font
;
21 import javax
.microedition
.lcdui
.Graphics
;
22 import javax
.microedition
.lcdui
.Image
;
23 import javax
.microedition
.lcdui
.Text
;
24 import javax
.microedition
.lcdui
.game
.Sprite
;
27 * This delegates drawing operations to the hardware graphics layer.
29 * This utilizes both {@link PencilShelf} and {@link PencilBracket} for native
35 public final class PencilGraphics
38 /** The hardware bracket reference. */
40 protected final PencilBracket hardware
;
44 protected final int surfaceW
;
46 /** Surface height. */
48 protected final int surfaceH
;
50 /** Is there an alpha channel? */
52 protected final boolean hasAlpha
;
54 /** Single character. */
56 private final char[] _singleChar
=
59 /** The current alpha color. */
61 private int _argbColor
;
63 /** The current blending mode. */
65 private int _blendingMode
;
67 /** The clip height. */
69 private int _clipHeight
;
71 /** The clip width. */
73 private int _clipWidth
;
75 /** The clip X position. */
79 /** The clip Y position. */
83 /** The current font used. */
87 /** The current stroke style. */
89 private int _strokeStyle
;
92 * Initializes the pencil graphics system.
94 * @param __sw The surface width.
95 * @param __sh The surface height.
96 * @param __hardware The hardware bracket reference for drawing.
97 * @throws IllegalArgumentException If hardware graphics are not capable
98 * enough to be used at all.
99 * @throws NullPointerException On null arguments.
102 @SquirrelJMEVendorApi
103 private PencilGraphics(int __sw
, int __sh
, PencilBracket __hardware
)
104 throws IllegalArgumentException
, NullPointerException
106 if (__hardware
== null)
107 throw new NullPointerException("NARG");
109 this.hardware
= __hardware
;
111 // These are used to manage the clip
112 this.surfaceW
= __sw
;
113 this.surfaceH
= __sh
;
115 // Determines which blending modes are valid
116 this.hasAlpha
= PencilShelf
.hardwareHasAlpha(__hardware
);
118 // Set initial parameters for the graphics and make sure they are
119 // properly forwarded as well
120 this.setAlphaColor(0xFF000000);
121 this.setBlendingMode(Graphics
.SRC_OVER
);
122 this.setStrokeStyle(Graphics
.SOLID
);
131 @SquirrelJMEVendorApi
132 public void clipRect(int __x
, int __y
, int __w
, int __h
)
134 throw Debugging
.todo();
142 @SquirrelJMEVendorApi
143 public void copyArea(int __sx
, int __sy
, int __w
, int __h
, int __dx
,
144 int __dy
, int __anchor
)
145 throws IllegalArgumentException
, IllegalStateException
147 // Forward to native call
150 PencilShelf
.hardwareCopyArea(this.hardware
,
151 __sx
, __sy
, __w
, __h
, __dx
, __dy
, __anchor
);
154 // Unwrap any potential errors.
155 catch (MLECallError e
)
157 throw e
.throwDistinct();
166 @SquirrelJMEVendorApi
167 public void drawArc(int __x
, int __y
, int __w
, int __h
, int __startAngle
,
170 throw Debugging
.todo();
178 @SquirrelJMEVendorApi
179 public void drawARGB16(short[] __data
, int __off
, int __scanlen
,
180 int __x
, int __y
, int __w
, int __h
)
181 throws NullPointerException
183 throw Debugging
.todo();
191 @SquirrelJMEVendorApi
192 public void drawChar(char __s
, int __x
, int __y
, int __anchor
)
194 // Fill single character first
195 char[] singleChar
= this._singleChar
;
201 PencilShelf
.hardwareDrawChars(this.hardware
,
202 singleChar
, 0, 1, __x
, __y
, __anchor
);
204 catch (MLECallError e
)
206 throw e
.throwDistinct();
215 @SquirrelJMEVendorApi
216 public void drawChars(char[] __s
, int __o
, int __l
, int __x
, int __y
,
218 throws IllegalArgumentException
, IndexOutOfBoundsException
,
223 throw new NullPointerException("NARG");
224 if (__o
< 0 || __l
< 0 || (__o
+ __l
) > __s
.length
)
225 throw new IndexOutOfBoundsException("IOOB");
230 PencilShelf
.hardwareDrawChars(this.hardware
,
231 __s
, __o
, __l
, __x
, __y
, __anchor
);
233 catch (MLECallError e
)
235 throw e
.throwDistinct();
244 @SquirrelJMEVendorApi
245 public void drawImage(Image __i
, int __x
, int __y
, int __anchor
)
246 throws IllegalArgumentException
, NullPointerException
248 // This is a duplicate function, so it gets forwarded
249 this.drawRegion(__i
, 0, 0,
250 __i
.getWidth(), __i
.getHeight(), 0,
259 @SquirrelJMEVendorApi
260 public void drawLine(int __x1
, int __y1
, int __x2
, int __y2
)
262 PencilShelf
.hardwareDrawLine(this.hardware
, __x1
, __y1
, __x2
, __y2
);
270 @SquirrelJMEVendorApi
271 public void drawRGB(int[] __data
, int __off
, int __scanlen
, int __x
,
272 int __y
, int __w
, int __h
, boolean __alpha
)
273 throws NullPointerException
276 this.__drawRegion(__data
, __off
, __scanlen
, __alpha
,
277 0, 0, __w
, __h
, Sprite
.TRANS_NONE
,
278 __x
, __y
, Graphics
.TOP
| Graphics
.LEFT
, __w
, __h
,
279 __scanlen
, (__data
.length
- __off
) / __scanlen
);
287 @SquirrelJMEVendorApi
288 public void drawRGB16(short[] __data
, int __off
, int __scanlen
,
289 int __x
, int __y
, int __w
, int __h
)
290 throws NullPointerException
292 throw Debugging
.todo();
300 @SquirrelJMEVendorApi
301 public void drawRect(int __x
, int __y
, int __w
, int __h
)
303 // Forward to hardware
304 PencilShelf
.hardwareDrawRect(this.hardware
, __x
, __y
, __w
, __h
);
312 @SquirrelJMEVendorApi
313 public void drawRegion(Image __src
, int __xsrc
, int __ysrc
,
314 int __wsrc
, int __hsrc
, int __trans
, int __xdest
, int __ydest
,
316 throws IllegalArgumentException
, NullPointerException
319 this.drawRegion(__src
, __xsrc
, __ysrc
, __wsrc
, __hsrc
,
320 __trans
, __xdest
, __ydest
, __anch
, __wsrc
, __hsrc
);
328 @SquirrelJMEVendorApi
329 public void drawRegion(Image __src
, int __xsrc
, int __ysrc
,
330 int __wsrc
, int __hsrc
, int __trans
, int __xdest
, int __ydest
,
331 int __anch
, int __wdest
, int __hdest
)
332 throws IllegalArgumentException
, NullPointerException
335 throw new NullPointerException("NARG");
337 // If the image is direct, use the buffer that is inside rather than
338 // a copy, so we do not waste time copying from it!
342 if (__src
.squirreljmeIsDirect())
344 buf
= __src
.squirreljmeDirectRGBInt();
345 offset
= __src
.squirreljmeDirectOffset();
346 scanLen
= __src
.squirreljmeDirectScanLen();
349 // Image is not directly accessible, so get a copy of it
352 // Obtain image properties
353 int iW
= __src
.getWidth();
354 int iH
= __src
.getHeight();
355 int totalPixels
= iW
* iH
;
358 buf
= new int[totalPixels
];
361 __src
.getRGB(buf
, offset
, scanLen
, 0, 0, iW
, iH
);
364 // Perform the internal draw
365 this.__drawRegion(buf
, offset
, scanLen
, __src
.hasAlpha(),
366 __xsrc
, __ysrc
, __wsrc
, __hsrc
, __trans
,
367 __xdest
, __ydest
, __anch
,
368 __wdest
, __hdest
, __src
.getWidth(), __src
.getHeight());
376 @SquirrelJMEVendorApi
377 public void drawRoundRect(int __x
, int __y
, int __w
, int __h
,
378 int __arcWidth
, int __arcHeight
)
380 throw Debugging
.todo();
388 @SquirrelJMEVendorApi
389 public void drawString(String __s
, int __x
, int __y
, int __anchor
)
390 throws NullPointerException
393 throw new NullPointerException("NARG");
398 PencilShelf
.hardwareDrawSubstring(this.hardware
,
399 __s
, 0, __s
.length(), __x
, __y
, __anchor
);
401 catch (MLECallError e
)
403 throw e
.throwDistinct();
412 @SquirrelJMEVendorApi
413 public void drawSubstring(String __s
, int __o
, int __l
,
414 int __x
, int __y
, int __anchor
)
415 throws NullPointerException
, StringIndexOutOfBoundsException
418 throw new NullPointerException("NARG");
419 if (__o
< 0 || __l
< 0 || (__o
+ __l
) > __s
.length())
420 throw new StringIndexOutOfBoundsException("IOOB");
425 PencilShelf
.hardwareDrawSubstring(this.hardware
,
426 __s
, __o
, __l
, __x
, __y
, __anchor
);
428 catch (MLECallError e
)
430 throw e
.throwDistinct();
439 @SquirrelJMEVendorApi
440 public void drawText(Text __t
, int __x
, int __y
)
442 throw Debugging
.todo();
450 @SquirrelJMEVendorApi
451 public void fillArc(int __x
, int __y
, int __w
, int __h
, int __startAngle
,
454 throw Debugging
.todo();
462 @SquirrelJMEVendorApi
463 public void fillRect(int __x
, int __y
, int __w
, int __h
)
465 // Forward to hardware
466 PencilShelf
.hardwareFillRect(this.hardware
, __x
, __y
, __w
, __h
);
474 @SquirrelJMEVendorApi
475 public void fillRoundRect(int __x
, int __y
, int __w
, int __h
,
476 int __arcWidth
, int __arcHeight
)
478 throw Debugging
.todo();
486 @SquirrelJMEVendorApi
487 public void fillTriangle(int __x1
, int __y1
, int __x2
, int __y2
,
490 // Forward to hardware
491 PencilShelf
.hardwareFillTriangle(this.hardware
, __x1
, __y1
, __x2
, __y2
,
500 @SquirrelJMEVendorApi
501 public int getAlpha()
503 return (this._argbColor
>> 24) & 0xFF;
511 @SquirrelJMEVendorApi
512 public int getAlphaColor()
514 return this._argbColor
;
522 @SquirrelJMEVendorApi
523 public int getBlendingMode()
525 return this._blendingMode
;
533 @SquirrelJMEVendorApi
534 public int getBlueComponent()
536 return (this._argbColor
) & 0xFF;
544 @SquirrelJMEVendorApi
545 public int getClipHeight()
547 return this._clipHeight
;
555 @SquirrelJMEVendorApi
556 public int getClipWidth()
558 return this._clipWidth
;
566 @SquirrelJMEVendorApi
567 public int getClipX()
569 return this._clipX
- this.getTranslateX();
577 @SquirrelJMEVendorApi
578 public int getClipY()
580 return this._clipY
- this.getTranslateY();
588 @SquirrelJMEVendorApi
589 public int getColor()
591 return this._argbColor
& 0xFFFFFF;
599 @SquirrelJMEVendorApi
600 public int getDisplayColor(int __rgb
)
602 throw Debugging
.todo();
603 /*// We can just ask the software graphics for the color we are using
604 // since it should hopefully match the hardware one.
605 return this.software.getDisplayColor(__rgb);*/
613 @SquirrelJMEVendorApi
614 public Font
getFont()
624 @SquirrelJMEVendorApi
625 public int getGrayScale()
627 return (((this._argbColor
>> 16) & 0xFF) +
628 ((this._argbColor
>> 8) & 0xFF) +
629 ((this._argbColor
) & 0xFF)) / 3;
637 @SquirrelJMEVendorApi
638 public int getGreenComponent()
640 return (this._argbColor
>> 8) & 0xFF;
648 @SquirrelJMEVendorApi
649 public int getRedComponent()
651 return (this._argbColor
>> 16) & 0xFF;
659 @SquirrelJMEVendorApi
660 public int getStrokeStyle()
662 return this._strokeStyle
;
670 @SquirrelJMEVendorApi
671 public int getTranslateX()
673 return PencilShelf
.hardwareTranslateXY(this.hardware
, false);
681 @SquirrelJMEVendorApi
682 public int getTranslateY()
684 return PencilShelf
.hardwareTranslateXY(this.hardware
, true);
692 @SquirrelJMEVendorApi
693 public void setAlpha(int __a
)
694 throws IllegalArgumentException
696 this.setAlphaColor(__a
,
697 this.getRedComponent(),
698 this.getGreenComponent(),
699 this.getBlueComponent());
707 @SquirrelJMEVendorApi
708 public void setAlphaColor(int __argb
)
711 this._argbColor
= __argb
;
713 // Set on the hardware side
714 PencilShelf
.hardwareSetAlphaColor(this.hardware
, __argb
);
722 @SquirrelJMEVendorApi
723 public void setAlphaColor(int __a
, int __r
, int __g
, int __b
)
724 throws IllegalArgumentException
726 /* {@squirreljme.error EB3t Color out of range. (Alpha; Red; Green;
728 if (__a
< 0 || __a
> 255 || __r
< 0 || __r
> 255 ||
729 __g
< 0 || __g
> 255 || __b
< 0 || __b
> 255)
730 throw new IllegalArgumentException(String
.format(
731 "EB3t %d %d %d %d", __a
, __r
, __g
, __b
));
734 this.setAlphaColor((__a
<< 24) | (__r
<< 16) | (__g
<< 8) | __b
);
742 @SquirrelJMEVendorApi
743 public void setBlendingMode(int __m
)
744 throws IllegalArgumentException
746 /* {@squirreljme.error EB3u Invalid blending mode. (The mode)} */
747 if ((__m
!= Graphics
.SRC
&& __m
!= Graphics
.SRC_OVER
) ||
748 (__m
== Graphics
.SRC
&& !this.hasAlpha
))
749 throw new IllegalArgumentException("EB3u " + __m
);
752 this._blendingMode
= __m
;
754 // Forward to both software and hardware graphics
755 PencilShelf
.hardwareSetBlendingMode(this.hardware
, __m
);
763 @SquirrelJMEVendorApi
764 public void setClip(int __x
, int __y
, int __w
, int __h
)
766 // Calculate the base clip coordinates
767 int startX
= __x
+ this.getTranslateX();
768 int startY
= __y
+ this.getTranslateY();
769 int endX
= startX
+ __w
;
770 int endY
= startY
+ __h
;
788 // Determine the bounds of all of these
789 int clipX
= Math
.min(this.surfaceW
, Math
.max(0, startX
));
790 int clipY
= Math
.min(this.surfaceH
, Math
.max(0, startY
));
791 int clipEndX
= Math
.min(this.surfaceW
, Math
.max(0, endX
));
792 int clipEndY
= Math
.min(this.surfaceH
, Math
.max(0, endY
));
797 this._clipWidth
= clipEndX
- clipX
;
798 this._clipHeight
= clipEndY
- clipY
;
800 // Forward to both software and hardware graphics
801 PencilShelf
.hardwareSetClip(this.hardware
, __x
, __y
, __w
, __h
);
808 @SuppressWarnings("MagicNumber")
810 @SquirrelJMEVendorApi
811 public void setColor(int __rgb
)
813 this.setAlphaColor((this.getAlphaColor() & 0xFF_
000000) |
814 (__rgb
& 0x00_FFFFFF
));
822 @SquirrelJMEVendorApi
823 public void setColor(int __r
, int __g
, int __b
)
824 throws IllegalArgumentException
826 this.setAlphaColor(this.getAlpha(), __r
, __g
, __b
);
834 @SquirrelJMEVendorApi
835 public void setFont(Font __font
)
837 // Clearing the font?
839 __font
= Font
.getDefaultFont();
844 // Set font natively from the font details
845 PencilShelf
.hardwareSetFont(this.hardware
,
846 ((PencilFontProvider
)__font
).__squirreljmePencilFont());
854 @SquirrelJMEVendorApi
855 public void setGrayScale(int __v
)
857 this.setAlphaColor(this.getAlpha(), __v
, __v
, __v
);
865 @SquirrelJMEVendorApi
866 public void setStrokeStyle(int __style
)
867 throws IllegalArgumentException
869 /* {@squirreljme.error EB3v Illegal stroke style.} */
870 if (__style
!= Graphics
.SOLID
&& __style
!= Graphics
.DOTTED
)
871 throw new IllegalArgumentException("EB3v");
874 this._strokeStyle
= __style
;
876 // Forward to both software and hardware graphics
877 PencilShelf
.hardwareSetStrokeStyle(this.hardware
, __style
);
885 @SquirrelJMEVendorApi
886 public void translate(int __x
, int __y
)
888 PencilShelf
.hardwareTranslate(this.hardware
, __x
, __y
);
892 * Draws a direct RGB region of an image.
894 * @param __data The source buffer.
895 * @param __off The offset into the buffer.
896 * @param __scanlen The scanline length.
897 * @param __alpha Drawing with the alpha channel?
898 * @param __xsrc The source X position.
899 * @param __ysrc The source Y position.
900 * @param __wsrc The width of the source region.
901 * @param __hsrc The height of the source region.
902 * @param __trans Sprite translation and/or rotation, see {@link Sprite}.
903 * @param __xdest The destination X position, is translated.
904 * @param __ydest The destination Y position, is translated.
905 * @param __anch The anchor point.
906 * @param __wdest The destination width.
907 * @param __hdest The destination height.
908 * @param __origImgWidth Original image width.
909 * @param __origImgHeight Original image height.
910 * @throws NullPointerException On null arguments.
913 @SquirrelJMEVendorApi
914 private void __drawRegion(int[] __data
, int __off
, int __scanlen
,
915 boolean __alpha
, int __xsrc
, int __ysrc
, int __wsrc
, int __hsrc
,
916 int __trans
, int __xdest
, int __ydest
, int __anch
, int __wdest
,
917 int __hdest
, int __origImgWidth
, int __origImgHeight
)
918 throws NullPointerException
921 throw new NullPointerException("NARG");
923 // Forward to the native region drawing method
924 PencilShelf
.hardwareDrawXRGB32Region(this.hardware
,
925 __data
, __off
, __scanlen
,
926 __alpha
, __xsrc
, __ysrc
, __wsrc
, __hsrc
,
927 __trans
, __xdest
, __ydest
, __anch
,
928 __wdest
, __hdest
, __origImgWidth
, __origImgHeight
);
932 * Creates a graphics that is capable of drawing on hardware if it is
933 * supported, but falling back to software level graphics.
935 * @param __pf The {@link UIPixelFormat} used for the draw.
936 * @param __bw The buffer width, this is the scanline width of the buffer.
937 * @param __bh The buffer height.
938 * @param __buf The target buffer to draw to, this is cast to the correct
940 * @param __pal The color palette, may be {@code null}.
941 * @param __sx Starting surface X coordinate.
942 * @param __sy Starting surface Y coordinate.
943 * @param __sw Surface width.
944 * @param __sh Surface height.
945 * @throws NullPointerException On null arguments.
948 @SquirrelJMEVendorApi
949 public static Graphics
hardwareGraphics(int __pf
, int __bw
,
950 int __bh
, Object __buf
, int[] __pal
, int __sx
, int __sy
,
952 throws NullPointerException
954 return new PencilGraphics(__sw
, __sh
,
955 DisplayManager
.instance().scritch().hardwareGraphics(
956 __pf
, __bw
, __bh
, __buf
, __pal
, __sx
, __sy
, __sw
, __sh
));
960 * Initializes a new graphics interface.
962 * @param __hw The hardware graphics to use.
963 * @param __sw The surface width.
964 * @param __sh The surface height.
965 * @return The wrapped graphics.
966 * @throws NullPointerException On null arguments.
969 @SquirrelJMEVendorApi
970 public static Graphics
of(ScritchPencilBracket __hw
, int __sw
, int __sh
)
971 throws NullPointerException
974 throw new NullPointerException("NARG");
976 return new PencilGraphics(__sw
, __sh
, __hw
);