Removal of old and deprecated UIForm code.
[SquirrelJME.git] / modules / midp-lcdui / src / main / java / cc / squirreljme / runtime / lcdui / mle / PencilGraphics.java
blobc537c38f2bb72ee6e6a49b1aa4d514ddaf166d0c
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 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.debug.Debugging;
18 import cc.squirreljme.runtime.lcdui.scritchui.DisplayManager;
19 import javax.microedition.lcdui.Font;
20 import javax.microedition.lcdui.Graphics;
21 import javax.microedition.lcdui.Image;
22 import javax.microedition.lcdui.Text;
23 import javax.microedition.lcdui.game.Sprite;
25 /**
26 * This delegates drawing operations to the hardware graphics layer.
28 * This utilizes both {@link PencilShelf} and {@link PencilBracket} for native
29 * graphics.
31 * @since 2020/09/25
33 public final class PencilGraphics
34 extends Graphics
36 /** The hardware bracket reference. */
37 protected final PencilBracket hardware;
39 /** Surface width. */
40 protected final int surfaceW;
42 /** Surface height. */
43 protected final int surfaceH;
45 /** Is there an alpha channel? */
46 protected final boolean hasAlpha;
48 /** Single character. */
49 private final char[] _singleChar =
50 new char[1];
52 /** The current alpha color. */
53 private int _argbColor;
55 /** The current blending mode. */
56 private int _blendingMode;
58 /** The clip height. */
59 private int _clipHeight;
61 /** The clip width. */
62 private int _clipWidth;
64 /** The clip X position. */
65 private int _clipX;
67 /** The clip Y position. */
68 private int _clipY;
70 /** The current font used. */
71 private Font _font;
73 /** The current stroke style. */
74 private int _strokeStyle;
76 /** The current X translation. */
77 private int _transX;
79 /** The current Y translation. */
80 private int _transY;
82 /**
83 * Initializes the pencil graphics system.
85 * @param __sw The surface width.
86 * @param __sh The surface height.
87 * @param __hardware The hardware bracket reference for drawing.
88 * @throws IllegalArgumentException If hardware graphics are not capable
89 * enough to be used at all.
90 * @throws NullPointerException On null arguments.
91 * @since 2020/09/25
93 private PencilGraphics(int __sw, int __sh, PencilBracket __hardware)
94 throws IllegalArgumentException, NullPointerException
96 if (__hardware == null)
97 throw new NullPointerException("NARG");
99 this.hardware = __hardware;
101 // These are used to manage the clip
102 this.surfaceW = __sw;
103 this.surfaceH = __sh;
105 // Determines which blending modes are valid
106 this.hasAlpha = PencilShelf.hardwareHasAlpha(__hardware);
108 // Set initial parameters for the graphics and make sure they are
109 // properly forwarded as well
110 this.setAlphaColor(0xFF000000);
111 this.setBlendingMode(Graphics.SRC_OVER);
112 this.setStrokeStyle(Graphics.SOLID);
113 this.setFont(null);
117 * {@inheritDoc}
118 * @since 2020/09/25
120 @Override
121 public void clipRect(int __x, int __y, int __w, int __h)
123 throw Debugging.todo();
127 * {@inheritDoc}
128 * @since 2020/09/25
130 @Override
131 public void copyArea(int __sx, int __sy, int __w, int __h, int __dx,
132 int __dy, int __anchor)
133 throws IllegalArgumentException, IllegalStateException
135 // Forward to native call
138 PencilShelf.hardwareCopyArea(this.hardware,
139 __sx, __sy, __w, __h, __dx, __dy, __anchor);
142 // Unwrap any potential errors.
143 catch (MLECallError e)
145 throw e.throwDistinct();
150 * {@inheritDoc}
151 * @since 2020/09/25
153 @Override
154 public void drawArc(int __x, int __y, int __w, int __h, int __startAngle,
155 int __arcAngle)
157 throw Debugging.todo();
161 * {@inheritDoc}
162 * @since 2020/09/25
164 @Override
165 public void drawARGB16(short[] __data, int __off, int __scanlen,
166 int __x, int __y, int __w, int __h)
167 throws NullPointerException
169 throw Debugging.todo();
173 * {@inheritDoc}
174 * @since 2020/09/25
176 @Override
177 public void drawChar(char __s, int __x, int __y, int __anchor)
179 // Fill single character first
180 char[] singleChar = this._singleChar;
181 singleChar[0] = __s;
183 // Forward
186 PencilShelf.hardwareDrawChars(this.hardware,
187 singleChar, 0, 1, __x, __y, __anchor);
189 catch (MLECallError e)
191 throw e.throwDistinct();
196 * {@inheritDoc}
197 * @since 2020/09/25
199 @Override
200 public void drawChars(char[] __s, int __o, int __l, int __x, int __y,
201 int __anchor)
202 throws IllegalArgumentException, IndexOutOfBoundsException,
203 NullPointerException
205 // Check
206 if (__s == null)
207 throw new NullPointerException("NARG");
208 if (__o < 0 || __l < 0 || (__o + __l) > __s.length)
209 throw new IndexOutOfBoundsException("IOOB");
211 // Forward
214 PencilShelf.hardwareDrawChars(this.hardware,
215 __s, __o, __l, __x, __y, __anchor);
217 catch (MLECallError e)
219 throw e.throwDistinct();
224 * {@inheritDoc}
225 * @since 2020/09/25
227 @Override
228 public void drawImage(Image __i, int __x, int __y, int __anchor)
229 throws IllegalArgumentException, NullPointerException
231 // This is a duplicate function, so it gets forwarded
232 this.drawRegion(__i, 0, 0,
233 __i.getWidth(), __i.getHeight(), 0,
234 __x, __y, __anchor);
238 * {@inheritDoc}
239 * @since 2020/09/25
241 @Override
242 public void drawLine(int __x1, int __y1, int __x2, int __y2)
244 PencilShelf.hardwareDrawLine(this.hardware, __x1, __y1, __x2, __y2);
248 * {@inheritDoc}
249 * @since 2020/09/25
251 @Override
252 public void drawRGB(int[] __data, int __off, int __scanlen, int __x,
253 int __y, int __w, int __h, boolean __alpha)
254 throws NullPointerException
256 // Forward Call
257 this.__drawRegion(__data, __off, __scanlen, __alpha,
258 0, 0, __w, __h, Sprite.TRANS_NONE,
259 __x, __y, Graphics.TOP | Graphics.LEFT, __w, __h,
260 __scanlen, (__data.length - __off) / __scanlen);
264 * {@inheritDoc}
265 * @since 2020/09/25
267 @Override
268 public void drawRGB16(short[] __data, int __off, int __scanlen,
269 int __x, int __y, int __w, int __h)
270 throws NullPointerException
272 throw Debugging.todo();
276 * {@inheritDoc}
277 * @since 2020/09/25
279 @Override
280 public void drawRect(int __x, int __y, int __w, int __h)
282 // Forward to hardware
283 PencilShelf.hardwareDrawRect(this.hardware, __x, __y, __w, __h);
287 * {@inheritDoc}
288 * @since 2020/09/25
290 @Override
291 public void drawRegion(Image __src, int __xsrc, int __ysrc,
292 int __wsrc, int __hsrc, int __trans, int __xdest, int __ydest,
293 int __anch)
294 throws IllegalArgumentException, NullPointerException
296 // Forward call
297 this.drawRegion(__src, __xsrc, __ysrc, __wsrc, __hsrc,
298 __trans, __xdest, __ydest, __anch, __wsrc, __hsrc);
302 * {@inheritDoc}
303 * @since 2020/09/25
305 @Override
306 public void drawRegion(Image __src, int __xsrc, int __ysrc,
307 int __wsrc, int __hsrc, int __trans, int __xdest, int __ydest,
308 int __anch, int __wdest, int __hdest)
309 throws IllegalArgumentException, NullPointerException
311 if (__src == null)
312 throw new NullPointerException("NARG");
314 // If the image is direct, use the buffer that is inside rather than
315 // a copy, so we do not waste time copying from it!
316 int[] buf;
317 int offset;
318 int scanLen;
319 if (__src.squirreljmeIsDirect())
321 buf = __src.squirreljmeDirectRGBInt();
322 offset = __src.squirreljmeDirectOffset();
323 scanLen = __src.squirreljmeDirectScanLen();
326 // Image is not directly accessible, so get a copy of it
327 else
329 // Obtain image properties
330 int iW = __src.getWidth();
331 int iH = __src.getHeight();
332 int totalPixels = iW * iH;
334 // Read RGB data
335 buf = new int[totalPixels];
336 offset = 0;
337 scanLen = iW;
338 __src.getRGB(buf, offset, scanLen, 0, 0, iW, iH);
341 // Perform the internal draw
342 this.__drawRegion(buf, offset, scanLen, __src.hasAlpha(),
343 __xsrc, __ysrc, __wsrc, __hsrc, __trans,
344 __xdest, __ydest, __anch,
345 __wdest, __hdest, __src.getWidth(), __src.getHeight());
349 * {@inheritDoc}
350 * @since 2020/09/25
352 @Override
353 public void drawRoundRect(int __x, int __y, int __w, int __h,
354 int __arcWidth, int __arcHeight)
356 throw Debugging.todo();
360 * {@inheritDoc}
361 * @since 2020/09/25
363 @Override
364 public void drawString(String __s, int __x, int __y, int __anchor)
365 throws NullPointerException
367 if (__s == null)
368 throw new NullPointerException("NARG");
370 // Forward
373 PencilShelf.hardwareDrawSubstring(this.hardware,
374 __s, 0, __s.length(), __x, __y, __anchor);
376 catch (MLECallError e)
378 throw e.throwDistinct();
383 * {@inheritDoc}
384 * @since 2020/09/25
386 @Override
387 public void drawSubstring(String __s, int __o, int __l,
388 int __x, int __y, int __anchor)
389 throws NullPointerException, StringIndexOutOfBoundsException
391 if (__s == null)
392 throw new NullPointerException("NARG");
393 if (__o < 0 || __l < 0 || (__o + __l) > __s.length())
394 throw new StringIndexOutOfBoundsException("IOOB");
396 // Forward
399 PencilShelf.hardwareDrawSubstring(this.hardware,
400 __s, __o, __l, __x, __y, __anchor);
402 catch (MLECallError e)
404 throw e.throwDistinct();
409 * {@inheritDoc}
410 * @since 2020/09/25
412 @Override
413 public void drawText(Text __t, int __x, int __y)
415 throw Debugging.todo();
419 * {@inheritDoc}
420 * @since 2020/09/25
422 @Override
423 public void fillArc(int __x, int __y, int __w, int __h, int __startAngle,
424 int __arcAngle)
426 throw Debugging.todo();
430 * {@inheritDoc}
431 * @since 2020/09/25
433 @Override
434 public void fillRect(int __x, int __y, int __w, int __h)
436 // Forward to hardware
437 PencilShelf.hardwareFillRect(this.hardware, __x, __y, __w, __h);
441 * {@inheritDoc}
442 * @since 2020/09/25
444 @Override
445 public void fillRoundRect(int __x, int __y, int __w, int __h,
446 int __arcWidth, int __arcHeight)
448 throw Debugging.todo();
452 * {@inheritDoc}
453 * @since 2020/09/25
455 @Override
456 public void fillTriangle(int __x1, int __y1, int __x2, int __y2,
457 int __x3, int __y3)
459 // Forward to hardware
460 PencilShelf.hardwareFillTriangle(this.hardware, __x1, __y1, __x2, __y2,
461 __x3, __y3);
465 * {@inheritDoc}
466 * @since 2020/09/25
468 @Override
469 public int getAlpha()
471 return (this._argbColor >> 24) & 0xFF;
475 * {@inheritDoc}
476 * @since 2020/09/25
478 @Override
479 public int getAlphaColor()
481 return this._argbColor;
485 * {@inheritDoc}
486 * @since 2020/09/25
488 @Override
489 public int getBlendingMode()
491 return this._blendingMode;
495 * {@inheritDoc}
496 * @since 2020/09/25
498 @Override
499 public int getBlueComponent()
501 return (this._argbColor) & 0xFF;
505 * {@inheritDoc}
506 * @since 2020/09/25
508 @Override
509 public int getClipHeight()
511 return this._clipHeight;
515 * {@inheritDoc}
516 * @since 2020/09/25
518 @Override
519 public int getClipWidth()
521 return this._clipWidth;
525 * {@inheritDoc}
526 * @since 2020/09/25
528 @Override
529 public int getClipX()
531 return this._clipX - this._transX;
535 * {@inheritDoc}
536 * @since 2020/09/25
538 @Override
539 public int getClipY()
541 return this._clipY - this._transY;
545 * {@inheritDoc}
546 * @since 2020/09/25
548 @Override
549 public int getColor()
551 return this._argbColor & 0xFFFFFF;
555 * {@inheritDoc}
556 * @since 2020/09/25
558 @Override
559 public int getDisplayColor(int __rgb)
561 throw Debugging.todo();
562 /*// We can just ask the software graphics for the color we are using
563 // since it should hopefully match the hardware one.
564 return this.software.getDisplayColor(__rgb);*/
568 * {@inheritDoc}
569 * @since 2020/09/25
571 @Override
572 public Font getFont()
574 return this._font;
578 * {@inheritDoc}
579 * @since 2020/09/25
581 @Override
582 public int getGrayScale()
584 return (((this._argbColor >> 16) & 0xFF) +
585 ((this._argbColor >> 8) & 0xFF) +
586 ((this._argbColor) & 0xFF)) / 3;
590 * {@inheritDoc}
591 * @since 2020/09/25
593 @Override
594 public int getGreenComponent()
596 return (this._argbColor >> 8) & 0xFF;
600 * {@inheritDoc}
601 * @since 2020/09/25
603 @Override
604 public int getRedComponent()
606 return (this._argbColor >> 16) & 0xFF;
610 * {@inheritDoc}
611 * @since 2020/09/25
613 @Override
614 public int getStrokeStyle()
616 return this._strokeStyle;
620 * {@inheritDoc}
621 * @since 2020/09/25
623 @Override
624 public int getTranslateX()
626 return this._transX;
630 * {@inheritDoc}
631 * @since 2020/09/25
633 @Override
634 public int getTranslateY()
636 return this._transY;
640 * {@inheritDoc}
641 * @since 2020/09/25
643 @Override
644 public void setAlpha(int __a)
645 throws IllegalArgumentException
647 this.setAlphaColor(__a,
648 this.getRedComponent(),
649 this.getGreenComponent(),
650 this.getBlueComponent());
654 * {@inheritDoc}
655 * @since 2020/09/25
657 @Override
658 public void setAlphaColor(int __argb)
660 // Mirror locally
661 this._argbColor = __argb;
663 // Set on the hardware side
664 PencilShelf.hardwareSetAlphaColor(this.hardware, __argb);
668 * {@inheritDoc}
669 * @since 2020/09/25
671 @Override
672 public void setAlphaColor(int __a, int __r, int __g, int __b)
673 throws IllegalArgumentException
675 /* {@squirreljme.error EB3t Color out of range. (Alpha; Red; Green;
676 Blue)} */
677 if (__a < 0 || __a > 255 || __r < 0 || __r > 255 ||
678 __g < 0 || __g > 255 || __b < 0 || __b > 255)
679 throw new IllegalArgumentException(String.format(
680 "EB3t %d %d %d %d", __a, __r, __g, __b));
682 // Set
683 this.setAlphaColor((__a << 24) | (__r << 16) | (__g << 8) | __b);
687 * {@inheritDoc}
688 * @since 2020/09/25
690 @Override
691 public void setBlendingMode(int __m)
692 throws IllegalArgumentException
694 /* {@squirreljme.error EB3u Invalid blending mode. (The mode)} */
695 if ((__m != Graphics.SRC && __m != Graphics.SRC_OVER) ||
696 (__m == Graphics.SRC && !this.hasAlpha))
697 throw new IllegalArgumentException("EB3u " + __m);
699 // Cache locally
700 this._blendingMode = __m;
702 // Forward to both software and hardware graphics
703 PencilShelf.hardwareSetBlendingMode(this.hardware, __m);
707 * {@inheritDoc}
708 * @since 2020/09/25
710 @Override
711 public void setClip(int __x, int __y, int __w, int __h)
713 // Calculate the base clip coordinates
714 int startX = __x + this._transX;
715 int startY = __y + this._transY;
716 int endX = startX + __w;
717 int endY = startY + __h;
719 // Normalize X
720 if (endX < startX)
722 int temp = endX;
723 endX = startX;
724 startX = temp;
727 // Normalize Y
728 if (endY < startY)
730 int temp = endY;
731 endY = startY;
732 startY = temp;
735 // Determine the bounds of all of these
736 int clipX = Math.min(this.surfaceW, Math.max(0, startX));
737 int clipY = Math.min(this.surfaceH, Math.max(0, startY));
738 int clipEndX = Math.min(this.surfaceW, Math.max(0, endX));
739 int clipEndY = Math.min(this.surfaceH, Math.max(0, endY));
741 // Record internally
742 this._clipX = clipX;
743 this._clipY = clipY;
744 this._clipWidth = clipEndX - clipX;
745 this._clipHeight = clipEndY - clipY;
747 // Forward to both software and hardware graphics
748 PencilShelf.hardwareSetClip(this.hardware, __x, __y, __w, __h);
752 * {@inheritDoc}
753 * @since 2020/09/25
755 @SuppressWarnings("MagicNumber")
756 @Override
757 public void setColor(int __rgb)
759 this.setAlphaColor((this.getAlphaColor() & 0xFF_000000) |
760 (__rgb & 0x00_FFFFFF));
764 * {@inheritDoc}
765 * @since 2020/09/25
767 @Override
768 public void setColor(int __r, int __g, int __b)
769 throws IllegalArgumentException
771 this.setAlphaColor(this.getAlpha(), __r, __g, __b);
775 * {@inheritDoc}
776 * @since 2020/09/25
778 @Override
779 public void setFont(Font __font)
781 // Clearing the font?
782 if (__font == null)
783 __font = Font.getDefaultFont();
785 // Cache locally
786 this._font = __font;
788 // Set font natively from the font details
789 PencilShelf.hardwareSetFont(this.hardware,
790 ((PencilFontProvider)__font).__squirreljmePencilFont());
794 * {@inheritDoc}
795 * @since 2020/09/25
797 @Override
798 public void setGrayScale(int __v)
800 this.setAlphaColor(this.getAlpha(), __v, __v, __v);
804 * {@inheritDoc}
805 * @since 2020/09/25
807 @Override
808 public void setStrokeStyle(int __style)
809 throws IllegalArgumentException
811 /* {@squirreljme.error EB3v Illegal stroke style.} */
812 if (__style != Graphics.SOLID && __style != Graphics.DOTTED)
813 throw new IllegalArgumentException("EB3v");
815 // Set
816 this._strokeStyle = __style;
818 // Forward to both software and hardware graphics
819 PencilShelf.hardwareSetStrokeStyle(this.hardware, __style);
823 * {@inheritDoc}
824 * @since 2020/09/25
826 @Override
827 public void translate(int __x, int __y)
829 // Set locally
830 this._transX += __x;
831 this._transY += __y;
833 // Forward to both software and hardware graphics
834 PencilShelf.hardwareTranslate(this.hardware, __x, __y);
838 * Draws a direct RGB region of an image.
840 * @param __data The source buffer.
841 * @param __off The offset into the buffer.
842 * @param __scanlen The scanline length.
843 * @param __alpha Drawing with the alpha channel?
844 * @param __xsrc The source X position.
845 * @param __ysrc The source Y position.
846 * @param __wsrc The width of the source region.
847 * @param __hsrc The height of the source region.
848 * @param __trans Sprite translation and/or rotation, see {@link Sprite}.
849 * @param __xdest The destination X position, is translated.
850 * @param __ydest The destination Y position, is translated.
851 * @param __anch The anchor point.
852 * @param __wdest The destination width.
853 * @param __hdest The destination height.
854 * @param __origImgWidth Original image width.
855 * @param __origImgHeight Original image height.
856 * @throws NullPointerException On null arguments.
857 * @since 2022/01/26
859 private void __drawRegion(int[] __data, int __off, int __scanlen,
860 boolean __alpha, int __xsrc, int __ysrc, int __wsrc, int __hsrc,
861 int __trans, int __xdest, int __ydest, int __anch, int __wdest,
862 int __hdest, int __origImgWidth, int __origImgHeight)
863 throws NullPointerException
865 if (__data == null)
866 throw new NullPointerException("NARG");
868 // Forward to the native region drawing method
869 PencilShelf.hardwareDrawXRGB32Region(this.hardware,
870 __data, __off, __scanlen,
871 __alpha, __xsrc, __ysrc, __wsrc, __hsrc,
872 __trans, __xdest, __ydest, __anch,
873 __wdest, __hdest, __origImgWidth, __origImgHeight);
877 * Creates a graphics that is capable of drawing on hardware if it is
878 * supported, but falling back to software level graphics.
880 * @param __pf The {@link UIPixelFormat} used for the draw.
881 * @param __bw The buffer width, this is the scanline width of the buffer.
882 * @param __bh The buffer height.
883 * @param __buf The target buffer to draw to, this is cast to the correct
884 * buffer format.
885 * @param __pal The color palette, may be {@code null}.
886 * @param __sx Starting surface X coordinate.
887 * @param __sy Starting surface Y coordinate.
888 * @param __sw Surface width.
889 * @param __sh Surface height.
890 * @throws NullPointerException On null arguments.
891 * @since 2020/09/25
893 public static Graphics hardwareGraphics(int __pf, int __bw,
894 int __bh, Object __buf, int[] __pal, int __sx, int __sy,
895 int __sw, int __sh)
896 throws NullPointerException
898 return new PencilGraphics(__sw, __sh,
899 DisplayManager.instance().scritch().hardwareGraphics(
900 __pf, __bw, __bh, __buf, __pal, __sx, __sy, __sw, __sh));
904 * Initializes a new graphics interface.
906 * @param __hw The hardware graphics to use.
907 * @param __sw The surface width.
908 * @param __sh The surface height.
909 * @return The wrapped graphics.
910 * @throws NullPointerException On null arguments.
911 * @since 2024/05/12
913 public static Graphics of(ScritchPencilBracket __hw, int __sw, int __sh)
914 throws NullPointerException
916 if (__hw == null)
917 throw new NullPointerException("NARG");
919 return new PencilGraphics(__sw, __sh, __hw);