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 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 java
.io
.ByteArrayInputStream
;
14 import java
.io
.ByteArrayOutputStream
;
15 import java
.io
.DataInputStream
;
16 import java
.io
.DataOutputStream
;
17 import java
.io
.IOException
;
18 import javax
.microedition
.lcdui
.Font
;
19 import javax
.microedition
.lcdui
.Graphics
;
20 import javax
.microedition
.lcdui
.Image
;
21 import javax
.microedition
.lcdui
.Text
;
24 * This class takes any input graphics operations that were performed for it,
25 * serializing anything that was sent to it. The serialized graphics can be
26 * forwarded somewhere for example for later deserialization.
28 * Translation is performed locally to the graphics and wherever the graphics
29 * target is, it will not have translation forwarded and serialized to simplify
34 @SuppressWarnings({"ManualMinMaxCalculation", "MagicNumber"})
36 public abstract class SerializedGraphics
46 * This method is called for any operation which serializes to graphics.
48 * @param __func The graphics operation to perform.
49 * @param __args The input arguments to the function.
50 * @return Any result from the operation.
53 public abstract Object
serialize(GraphicsFunction __func
,
61 public void clipRect(int __x
, int __y
, int __w
, int __h
)
63 int transx
= this.transx
,
66 // Calculate the actual desired clip location
67 int nx
= __x
+ transx
,
72 // Get the current clip location
73 int cx
= this.__getClipX(),
74 cy
= this.__getClipY(),
75 ca
= cx
+ this.getClipWidth(),
76 cb
= cy
+ this.getClipHeight();
78 // Use direct set clip but with the correct coordinates
79 int bx
= (nx
> cx ? nx
: cx
),
80 by
= (ny
> cy ? ny
: cy
);
81 this.serialize(GraphicsFunction
.SET_CLIP
,
84 (na
< ca ? na
: ca
) - bx
,
85 (nb
< cb ? nb
: cb
) - by
);
93 public void copyArea(int __sx
, int __sy
, int __w
, int __h
,
94 int __dx
, int __dy
, int __anchor
)
95 throws IllegalArgumentException
, IllegalStateException
97 int transx
= this.transx
,
100 this.serialize(GraphicsFunction
.COPY_AREA
,
101 __sx
+ transx
, __sy
+ transy
, __w
, __h
,
102 __dx
+ transx
, __dy
+ transy
, __anchor
);
110 public void drawArc(int __x
, int __y
, int __w
, int __h
, int __sa
,
113 int transx
= this.transx
,
114 transy
= this.transy
;
116 this.serialize(GraphicsFunction
.DRAW_ARC
,
117 __x
+ transx
, __y
+ transy
, __w
, __h
, __sa
, __aa
);
125 public void drawARGB16(short[] __data
, int __off
, int __scanlen
,
126 int __x
, int __y
, int __w
, int __h
)
127 throws NullPointerException
129 int transx
= this.transx
,
130 transy
= this.transy
;
132 this.serialize(GraphicsFunction
.DRAW_ARGB16
,
133 __data
, __off
, __scanlen
, __x
+ transx
, __y
+ transy
, __w
, __h
);
141 public void drawChar(char __s
, int __x
, int __y
, int __anchor
)
143 int transx
= this.transx
,
144 transy
= this.transy
;
146 this.serialize(GraphicsFunction
.DRAW_CHAR
,
147 (int)__s
, __x
+ transx
, __y
+ transy
, __anchor
);
155 public void drawChars(char[] __s
, int __o
, int __l
, int __x
,
156 int __y
, int __anchor
)
157 throws NullPointerException
159 int transx
= this.transx
,
160 transy
= this.transy
;
162 this.serialize(GraphicsFunction
.DRAW_CHARS
,
163 __s
, __o
, __l
, __x
+ transx
, __y
+ transy
, __anchor
);
171 public void drawImage(Image __i
, int __x
, int __y
, int __anchor
)
172 throws IllegalArgumentException
, NullPointerException
175 throw new NullPointerException("NARG");
177 this.drawRegion(__i
, 0, 0, __i
.getWidth(), __i
.getHeight(), 0,
186 public void drawLine(int __x1
, int __y1
, int __x2
, int __y2
)
188 int transx
= this.transx
,
189 transy
= this.transy
;
191 this.serialize(GraphicsFunction
.DRAW_LINE
,
192 __x1
+ transx
, __y1
+ transy
, __x2
+ transx
, __y2
+ transy
);
200 public void drawRGB(int[] __data
, int __off
, int __scanlen
,
201 int __x
, int __y
, int __w
, int __h
, boolean __alpha
)
202 throws NullPointerException
204 int transx
= this.transx
,
205 transy
= this.transy
;
207 this.serialize(GraphicsFunction
.DRAW_RGB
,
208 __data
, __off
, __scanlen
, __x
+ transx
, __y
+ transy
,
209 __w
, __h
, (__alpha ?
1 : 0));
217 public void drawRGB16(short[] __data
, int __off
, int __scanlen
,
218 int __x
, int __y
, int __w
, int __h
)
219 throws NullPointerException
221 int transx
= this.transx
,
222 transy
= this.transy
;
224 this.serialize(GraphicsFunction
.DRAW_RGB16
,
225 __data
, __off
, __scanlen
, __x
+ transx
, __y
+ transy
, __w
, __h
);
233 public void drawRect(int __x
, int __y
, int __w
, int __h
)
235 int transx
= this.transx
,
236 transy
= this.transy
;
238 this.serialize(GraphicsFunction
.DRAW_RECT
,
239 __x
+ transx
, __y
+ transy
, __w
, __h
);
247 public void drawRegion(Image __src
, int __xsrc
, int __ysrc
,
248 int __wsrc
, int __hsrc
, int __trans
, int __xdest
, int __ydest
,
250 throws IllegalArgumentException
, NullPointerException
253 throw new NullPointerException("NARG");
255 this.drawRegion(__src
, __xsrc
, __ysrc
, __wsrc
, __hsrc
, __trans
,
256 __xdest
, __ydest
, __anch
, __wsrc
, __hsrc
);
264 public void drawRegion(Image __src
, int __xsrc
, int __ysrc
,
265 int __wsrc
, int __hsrc
, int __trans
, int __xdest
, int __ydest
,
266 int __anch
, int __wdest
, int __hdest
)
267 throws IllegalArgumentException
, NullPointerException
270 throw new NullPointerException("NARG");
272 int transx
= this.transx
,
273 transy
= this.transy
;
275 // Extract image pixel data before sending over
276 int numpixels
= __wsrc
* __hsrc
;
277 int[] data
= new int[numpixels
];
278 __src
.getRGB(data
, 0, __wsrc
, __xsrc
, __ysrc
, __wsrc
, __hsrc
);
280 // {@squirreljme.error EB0l Illegal region draw.}
281 int rv
= (Integer
)this.serialize(GraphicsFunction
.DRAW_REGION
,
282 data
, (__wsrc
<< 16) | __hsrc
, __trans
,
283 __xdest
+ transx
, __ydest
+ transy
,
284 __anch
, (__wdest
<< 16) | __hdest
);
286 throw new IllegalArgumentException("EB0l");
294 public void drawRoundRect(int __x
, int __y
, int __w
, int __h
,
297 int transx
= this.transx
,
298 transy
= this.transy
;
300 this.serialize(GraphicsFunction
.DRAW_ROUND_RECT
,
301 __x
+ transx
, __y
+ transy
, __w
, __h
, __aw
, __ah
);
309 public void drawString(String __s
, int __x
, int __y
,
311 throws NullPointerException
313 // Just pass the chars of the string since we cannot represent
315 this.serialize(GraphicsFunction
.DRAW_SUB_CHARS
,
316 __s
.toCharArray(), 0, __s
.length(), __x
, __y
, __anchor
);
324 public void drawSubstring(String __s
, int __o
, int __l
, int __x
,
325 int __y
, int __anchor
)
326 throws NullPointerException
, StringIndexOutOfBoundsException
328 // Just pass the chars of the string since we cannot represent
330 this.serialize(GraphicsFunction
.DRAW_SUB_CHARS
,
331 __s
.toCharArray(), __o
, __l
, __x
, __y
, __anchor
);
339 public void drawText(Text __t
, int __x
, int __y
)
341 this.serialize(GraphicsFunction
.DRAW_TEXT
,
342 SerializedGraphics
.textSerialize(__t
), __x
, __y
);
350 public void fillArc(int __x
, int __y
, int __w
, int __h
, int __sa
,
353 this.serialize(GraphicsFunction
.FILL_ARC
,
354 __x
, __y
, __w
, __h
, __sa
, __aa
);
362 public void fillRect(int __x
, int __y
, int __w
, int __h
)
364 this.serialize(GraphicsFunction
.FILL_RECT
,
373 public void fillRoundRect(int __x
, int __y
, int __w
, int __h
,
376 this.serialize(GraphicsFunction
.FILL_ROUND_RECT
,
377 __x
, __y
, __w
, __h
, __aw
, __ah
);
385 public void fillTriangle(int __x1
, int __y1
, int __x2
, int __y2
,
388 this.serialize(GraphicsFunction
.FILL_TRIANGLE
,
389 __x1
, __y1
, __x2
, __y2
, __x3
, __y3
);
397 public int getAlpha()
399 return (this.getAlphaColor() >> 24) & 0xFF;
407 public int getAlphaColor()
409 return (Integer
)this.serialize(GraphicsFunction
.GET_ALPHA_COLOR
);
417 public int getBlendingMode()
419 return (Integer
)this.serialize(GraphicsFunction
.GET_BLENDING_MODE
);
427 public int getBlueComponent()
429 return (this.getAlphaColor()) & 0xFF;
437 public int getClipHeight()
439 return (Integer
)this.serialize(GraphicsFunction
.GET_CLIP_HEIGHT
);
447 public int getClipWidth()
449 return (Integer
)this.serialize(GraphicsFunction
.GET_CLIP_WIDTH
);
457 public int getClipX()
459 return this.__getClipX() - this.transx
;
467 public int getClipY()
469 return this.__getClipY() - this.transy
;
477 public int getColor()
479 return this.getAlphaColor() & 0xFFFFFF;
487 public int getDisplayColor(int __rgb
)
489 return (Integer
)this.serialize(GraphicsFunction
.GET_DISPLAY_COLOR
,
498 public Font
getFont()
500 return SerializedGraphics
.fontDeserialize(
501 (byte[])this.serialize(GraphicsFunction
.GET_FONT
));
509 public int getGrayScale()
511 return (this.getRedComponent() + this.getGreenComponent() +
512 this.getBlueComponent()) / 3;
520 public int getGreenComponent()
522 return (this.getAlphaColor() >> 8) & 0xFF;
530 public int getRedComponent()
532 return (this.getAlphaColor() >> 16) & 0xFF;
540 public int getStrokeStyle()
542 return (Integer
)this.serialize(GraphicsFunction
.GET_STROKE_STYLE
);
550 public int getTranslateX()
560 public int getTranslateY()
570 public void setAlpha(int __a
)
571 throws IllegalArgumentException
573 this.setAlphaColor(__a
, this.getRedComponent(),
574 this.getGreenComponent(), this.getBlueComponent());
582 public void setAlphaColor(int __argb
)
584 this.serialize(GraphicsFunction
.SET_ALPHA_COLOR
, __argb
);
592 public void setAlphaColor(int __a
, int __r
, int __g
, int __b
)
593 throws IllegalArgumentException
595 this.serialize(GraphicsFunction
.SET_ALPHA_COLOR
,
596 ((__a
& 0xFF) << 24) |
597 ((__r
& 0xFF) << 16) |
598 ((__g
& 0xFF) << 8) |
607 public void setBlendingMode(int __m
)
608 throws IllegalArgumentException
610 // {@squirreljme.error EB0m Failed to set blending mode.}
611 int okay
= (Integer
)this.serialize(GraphicsFunction
.SET_BLENDING_MODE
,
614 throw new IllegalArgumentException("EB0m");
622 public void setClip(int __x
, int __y
, int __w
, int __h
)
624 int transx
= this.transx
,
625 transy
= this.transy
;
627 this.serialize(GraphicsFunction
.SET_CLIP
,
628 __x
+ transx
, __y
+ transy
, __w
, __h
);
636 public void setColor(int __rgb
)
638 this.serialize(GraphicsFunction
.SET_COLOR
, __rgb
);
646 public void setColor(int __r
, int __g
, int __b
)
647 throws IllegalArgumentException
649 this.serialize(GraphicsFunction
.SET_COLOR
,
650 ((__r
& 0xFF) << 16) |
651 ((__g
& 0xFF) << 8) |
660 public void setFont(Font __font
)
664 __font
= Font
.getDefaultFont();
667 this.serialize(GraphicsFunction
.SET_FONT
,
668 SerializedGraphics
.fontSerialize(__font
));
676 public void setGrayScale(int __v
)
678 this.setAlphaColor(this.getAlpha(), __v
, __v
, __v
);
687 public void setStrokeStyle(int __s
)
688 throws IllegalArgumentException
690 // {@squirreljme.error EB0n Failed to set stroke style.}
691 int okay
= (Integer
)this.serialize(GraphicsFunction
.SET_STROKE_STYLE
,
694 throw new IllegalArgumentException("EB0n");
702 public void translate(int __x
, int __y
)
709 * Returns the raw clipping X of the target.
711 * @return The target clipping.
714 private int __getClipX()
716 return (Integer
)this.serialize(GraphicsFunction
.GET_CLIP_X
);
720 * Returns the raw clipping Y of the target.
722 * @return The target clipping.
725 private int __getClipY()
727 return (Integer
)this.serialize(GraphicsFunction
.GET_CLIP_Y
);
731 * Deserializes the input operation arguments and performs the call on
732 * the destination graphics.
734 * @param __g The destination graphics object.
735 * @param __func The graphics function to call.
736 * @param __args Arguments to the function.
737 * @return The result of the call.
738 * @throws NullPointerException On null arguments.
741 public static Object
deserialize(Graphics __g
, GraphicsFunction __func
,
743 throws IllegalArgumentException
, NullPointerException
745 if (__g
== null || __func
== null)
746 throw new NullPointerException("NARG");
748 // Depends on the function
765 return __g
.getClipX();
768 return __g
.getClipY();
771 return __g
.getClipWidth();
773 case GET_CLIP_HEIGHT
:
774 return __g
.getClipHeight();
794 case GET_ALPHA_COLOR
:
795 return __g
.getAlphaColor();
798 case SET_ALPHA_COLOR
:
799 __g
.setAlphaColor((Integer
)__args
[0]);
813 __g
.setFont(SerializedGraphics
.fontDeserialize(
819 return SerializedGraphics
.fontSerialize(__g
.getFont());
821 // Draw sub-characters
835 SerializedGraphics
.textDeserialize((byte[])__args
[0]),
841 case GET_STROKE_STYLE
:
842 return __g
.getStrokeStyle();
845 case SET_STROKE_STYLE
:
848 __g
.setStrokeStyle((Integer
)__args
[0]);
850 catch (IllegalArgumentException e
)
894 (char)(((Integer
)__args
[0]).intValue()),
921 (((Integer
)__args
[7]) != 0 ?
true : false));
936 // Draw round rectangle.
937 case DRAW_ROUND_RECT
:
958 // Fill round rectangle.
959 case FILL_ROUND_RECT
:
980 // Get blending mode.
981 case GET_BLENDING_MODE
:
982 return __g
.getBlendingMode();
984 // Get display color.
985 case GET_DISPLAY_COLOR
:
986 return __g
.getDisplayColor((Integer
)__args
[0]);
988 // Set blending mode.
989 case SET_BLENDING_MODE
:
992 __g
.setBlendingMode((Integer
)__args
[0]);
994 catch (IllegalArgumentException e
)
1004 // Extract width/heights since they are combined here
1005 int sw
= ((Integer
)__args
[1]) >>> 16,
1006 sh
= ((Integer
)__args
[1]) & 0xFFFF,
1007 dw
= ((Integer
)__args
[6]) >>> 16,
1008 dh
= ((Integer
)__args
[6]) & 0xFFFF;
1010 // Note that the passed buffer only contains image data
1011 // from the source region, as such the source coordinates
1012 // will always be zero
1013 __g
.drawRegion(Image
.createRGBImage(
1014 (int[])__args
[0], sw
, sh
, true),
1023 catch (IllegalArgumentException e
)
1030 throw Debugging
.oops(__func
);
1035 * Deserializes the font.
1037 * @param __b The input byte data.
1038 * @return The resulting font.
1039 * @throws NullPointerException On null arguments.
1042 public static Font
fontDeserialize(byte[] __b
)
1043 throws NullPointerException
1046 throw new NullPointerException("NARG");
1048 // Deserialize all of the data
1049 try (ByteArrayInputStream bais
= new ByteArrayInputStream(__b
))
1051 int style
, pixelsize
;
1054 try (DataInputStream dis
= new DataInputStream(bais
))
1056 style
= dis
.readInt();
1057 pixelsize
= dis
.readInt();
1058 name
= dis
.readUTF();
1061 return Font
.getFont(name
, style
, pixelsize
);
1064 // {@squirreljme.error EB0o Could not serialize the text object.}
1065 catch (IOException e
)
1067 throw new RuntimeException("EB0o", e
);
1072 * Deserializes the font.
1074 * @param __dis The stream to read from.
1075 * @return The deserialized font.
1076 * @throws IOException On read errors.
1077 * @throws NullPointerException On null arguments.
1080 public static Font
fontDeserialize(DataInputStream __dis
)
1081 throws IOException
, NullPointerException
1084 throw new NullPointerException("NARG");
1087 int len
= __dis
.readUnsignedShort();
1088 byte[] ser
= new byte[len
];
1089 __dis
.readFully(ser
);
1090 return SerializedGraphics
.fontDeserialize(ser
);
1094 * Serializes the font.
1096 * @param __f The font to serialize.
1097 * @return The resulting byte data.
1098 * @throws NullPointerException On null arguments.
1101 public static byte[] fontSerialize(Font __f
)
1102 throws NullPointerException
1105 throw new NullPointerException("NARG");
1107 // Serialize all of the data
1108 try (ByteArrayOutputStream baos
= new ByteArrayOutputStream(64))
1110 try (DataOutputStream dos
= new DataOutputStream(baos
))
1112 dos
.writeInt(__f
.getStyle());
1113 dos
.writeInt(__f
.getPixelSize());
1114 dos
.writeUTF(__f
.getFontName());
1118 return baos
.toByteArray();
1121 // {@squirreljme.error EB0p Could not serialize the text object.}
1122 catch (IOException e
)
1124 throw new RuntimeException("EB0p", e
);
1129 * Serializes the font.
1131 * @param __dos The stream to write to.
1132 * @param __f The font to serialize.
1133 * @throws IOException On write errors.
1134 * @throws NullPointerException On null arguments.
1137 public static void fontSerialize(DataOutputStream __dos
, Font __f
)
1138 throws IOException
, NullPointerException
1140 if (__dos
== null || __f
== null)
1141 throw new NullPointerException("NARG");
1144 byte[] ser
= SerializedGraphics
.fontSerialize(__f
);
1145 __dos
.writeShort(ser
.length
);
1150 * Deserializes the byte array to a {@link Text} object.
1152 * @param __b The byte array to deserialize.
1153 * @return The deserialized text.
1154 * @throws NullPointerException On null arguments.
1157 public static Text
textDeserialize(byte[] __b
)
1158 throws NullPointerException
1161 throw new NullPointerException("NARG");
1163 // Deserialize all of the data
1164 try (ByteArrayInputStream bais
= new ByteArrayInputStream(__b
))
1166 Text rv
= new Text();
1167 try (DataInputStream dis
= new DataInputStream(bais
))
1169 rv
.setWidth(dis
.readInt());
1170 rv
.setHeight(dis
.readInt());
1171 rv
.setAlignment(dis
.readInt());
1172 rv
.setBackgroundColor(dis
.readInt());
1173 rv
.setFont(SerializedGraphics
.fontDeserialize(dis
));
1174 rv
.setForegroundColor(dis
.readInt());
1175 rv
.setIndent(dis
.readInt());
1176 rv
.setInitialDirection(dis
.readInt());
1177 rv
.setScrollOffset(dis
.readInt());
1178 rv
.setSpaceAbove(dis
.readInt());
1179 rv
.setSpaceBelow(dis
.readInt());
1182 int n
= dis
.readInt();
1184 // Read in text string
1185 rv
.insert(0, dis
.readUTF());
1187 // Read all character properties
1188 for (int i
= 0; i
< n
; i
++)
1190 rv
.setForegroundColor(dis
.readInt(), i
, 1);
1193 if (dis
.readBoolean())
1195 SerializedGraphics
.fontDeserialize(dis
), i
, 1);
1198 // And now that there is proper length
1199 rv
.setCaret(dis
.readInt());
1200 rv
.setHighlight(dis
.readInt(), dis
.readInt());
1207 // {@squirreljme.error EB0q Could not serialize the text object.}
1208 catch (IOException e
)
1210 throw new RuntimeException("EB0q", e
);
1215 * Serializes the text object to a byte array.
1217 * @param __t The text to serialize.
1218 * @return The serialized byte array.
1219 * @throws NullPointerException On null arguments.
1222 public static byte[] textSerialize(Text __t
)
1223 throws NullPointerException
1226 throw new NullPointerException("NARG");
1228 // Serialize all of the data
1229 try (ByteArrayOutputStream baos
= new ByteArrayOutputStream(4096))
1231 try (DataOutputStream dos
= new DataOutputStream(baos
))
1233 // Properties which do not need characters
1234 dos
.writeInt(__t
.getWidth());
1235 dos
.writeInt(__t
.getHeight());
1236 dos
.writeInt(__t
.getAlignment());
1237 dos
.writeInt(__t
.getBackgroundColor());
1238 SerializedGraphics
.fontSerialize(dos
, __t
.getFont());
1239 dos
.writeInt(__t
.getForegroundColor());
1240 dos
.writeInt(__t
.getIndent());
1241 dos
.writeInt(__t
.getInitialDirection());
1242 dos
.writeInt(__t
.getScrollOffset());
1243 dos
.writeInt(__t
.getSpaceAbove());
1244 dos
.writeInt(__t
.getSpaceBelow());
1247 int n
= __t
.getTextLength();
1250 // Record the string
1251 dos
.writeUTF(__t
.getText(0, n
));
1253 // Record all the character properties
1254 for (int i
= 0; i
< n
; i
++)
1256 dos
.writeInt(__t
.getForegroundColor(i
));
1258 // Font needs serialization
1259 Font f
= __t
.getFont(i
);
1261 dos
.writeBoolean(false);
1264 dos
.writeBoolean(true);
1265 SerializedGraphics
.fontSerialize(dos
, f
);
1269 // Depends on character stuff
1270 dos
.writeInt(__t
.getCaret());
1271 dos
.writeInt(__t
.getHighlightIndex());
1272 dos
.writeInt(__t
.getHighlightLength());
1276 return baos
.toByteArray();
1279 // {@squirreljme.error EB0r Could not serialize the text object.}
1280 catch (IOException e
)
1282 throw new RuntimeException("EB0r", e
);