Source Code Cross Referenced for SkinRomizationTool.java in  » 6.0-JDK-Modules » j2me » com » sun » midp » skinromization » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.midp.skinromization 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *   
0003:         *
0004:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006:         * 
0007:         * This program is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU General Public License version
0009:         * 2 only, as published by the Free Software Foundation.
0010:         * 
0011:         * This program is distributed in the hope that it will be useful, but
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014:         * General Public License version 2 for more details (a copy is
0015:         * included at /legal/license.txt).
0016:         * 
0017:         * You should have received a copy of the GNU General Public License
0018:         * version 2 along with this work; if not, write to the Free Software
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020:         * 02110-1301 USA
0021:         * 
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional
0024:         * information or have any questions.
0025:         *
0026:         */
0027:
0028:        /**
0029:         * This tool takes XML file describing skin as input and produces Java
0030:         * and C files with romized skin's properties values. Those files are
0031:         * intended to be compiled with the rest of Chameleon source files.
0032:         *
0033:         */package com.sun.midp.skinromization;
0034:
0035:        import java.io.*;
0036:        import java.util.*;
0037:
0038:        import javax.xml.parsers.*;
0039:        import org.w3c.dom.*;
0040:
0041:        import java.awt.image.*;
0042:        import java.awt.*;
0043:        import com.sun.midp.imageutil.*;
0044:        import java.lang.reflect.*;
0045:        import com.sun.midp.chameleon.skins.resources.*;
0046:
0047:        /**
0048:         * Represents romization job
0049:         */
0050:        class RomizationJob {
0051:            /** XML file name to get skin properties from */
0052:            public String skinXMLFileName = "";
0053:
0054:            /** Skin images directory name */
0055:            public String skinImagesDirName = "";
0056:
0057:            /** Output file name for RomizedSkin class */
0058:            public String outBinFileName = "";
0059:
0060:            /** Output file name for romized images data */
0061:            public String outCFileName = "";
0062:
0063:            /** For QA purposes: overrides images romization settings from XML */
0064:            public String imageRomOverride = "";
0065:        }
0066:
0067:        /**
0068:         * Main tool class
0069:         */
0070:        public class SkinRomizationTool {
0071:            /** Romizer that does actual romization */
0072:            private static SkinRomizer romizer = null;
0073:
0074:            /** Romization job to perform */
0075:            private static RomizationJob romizationJob = null;
0076:
0077:            /** Print debug output while running */
0078:            private static boolean debug = false;
0079:
0080:            /** Print usage info and exit */
0081:            private static boolean printHelp = false;
0082:
0083:            /**
0084:             * Main method
0085:             *
0086:             * @param args Command line arguments
0087:             */
0088:            public static void main(String[] args) {
0089:                try {
0090:                    parseArgs(args);
0091:                    if (printHelp) {
0092:                        printHelp();
0093:                        return;
0094:                    }
0095:
0096:                    if (!validateParsedArgs()) {
0097:                        System.exit(1);
0098:                    }
0099:
0100:                    romizer = new SkinRomizer(debug);
0101:                    romizer.romize(romizationJob);
0102:                } catch (Exception e) {
0103:                    e.printStackTrace();
0104:                    System.exit(1);
0105:                }
0106:            }
0107:
0108:            /**
0109:             * Parses command line arguments
0110:             *
0111:             * @param args command line arguments
0112:             */
0113:            private static void parseArgs(String[] args) {
0114:                romizationJob = new RomizationJob();
0115:
0116:                for (int i = 0; i < args.length; ++i) {
0117:                    String arg = args[i];
0118:                    if (arg.equals("-xml")) {
0119:                        romizationJob.skinXMLFileName = args[++i];
0120:                    } else if (arg.equals("-outbin")) {
0121:                        romizationJob.outBinFileName = args[++i];
0122:                    } else if (arg.equals("-imagedir")) {
0123:                        romizationJob.skinImagesDirName = args[++i];
0124:                    } else if (arg.equals("-outc")) {
0125:                        romizationJob.outCFileName = args[++i];
0126:                        // this option is for QA purposes only and therefore 
0127:                        // hidden, undocumented and unsupported
0128:                    } else if (arg.equals("-qaimagerom")) {
0129:                        romizationJob.imageRomOverride = args[++i];
0130:                    } else if (arg.equals("-debug")) {
0131:                        debug = true;
0132:                    } else {
0133:                        throw new IllegalArgumentException("invalid option \""
0134:                                + args[i] + "\"");
0135:                    }
0136:                }
0137:            }
0138:
0139:            /**
0140:             * Validates parsed arguments, printing error message
0141:             * if some arg is invalid.
0142:             *
0143:             * @return true, if all arguments are valid
0144:             */
0145:            private static boolean validateParsedArgs() {
0146:                File f = new File(romizationJob.skinXMLFileName);
0147:                if (!f.isFile()) {
0148:                    System.err
0149:                            .println("SkinRomizationTool: Couldn't find input XML file: "
0150:                                    + '"' + romizationJob.skinXMLFileName + '"');
0151:
0152:                    return false;
0153:                }
0154:
0155:                f = new File(romizationJob.skinImagesDirName);
0156:                if (!f.isDirectory()) {
0157:                    System.err.println("SkinRomizationTool: " + '"'
0158:                            + romizationJob.skinImagesDirName + '"'
0159:                            + " isn't a directory");
0160:
0161:                    return false;
0162:                }
0163:
0164:                return true;
0165:            }
0166:
0167:            /**
0168:             * Prints usage information
0169:             */
0170:            private static void printHelp() {
0171:                /**
0172:                 * Following options are recognized:
0173:                 * -xml:        XML file describing skin.
0174:                 * -out:        Output file. If empty, output will be to stdout.
0175:                 * -help:       Print usage information
0176:                 * -debug:      Be verbose: print some debug info while running. 
0177:                 *
0178:                 */
0179:                System.err
0180:                        .println("Usage: java -jar "
0181:                                + "com.sun.midp.SkinRomizationTool "
0182:                                + "-xml <localXMLFile> "
0183:                                + "-imagedir <skinImagesDirName> "
0184:                                + "-outbin <localOutputBinFile> "
0185:                                + "-outc <localOutputCFile> " + "[-debug] "
0186:                                + "[-help]");
0187:            }
0188:        }
0189:
0190:        /**
0191:         * Base class for all skin properties
0192:         */
0193:        abstract class SkinPropertyBase {
0194:
0195:            /** Print some debug info */
0196:            static boolean debug = false;
0197:
0198:            /** Name of property ID */
0199:            String idName;
0200:
0201:            /** Integer number used as property ID */
0202:            int id;
0203:
0204:            /** Offset of the property value(s) in romized values array */
0205:            int valueOffset;
0206:
0207:            /**
0208:             * Constructor
0209:             *
0210:             * @param idName name of the property's ID
0211:             * @param id property's ID
0212:             * @exception IllegalArgumentException if some of parameters 
0213:             * are invalid
0214:             */
0215:            SkinPropertyBase(String idName, String id) {
0216:                this .idName = idName;
0217:
0218:                try {
0219:                    this .id = Integer.parseInt(id);
0220:                } catch (NumberFormatException e) {
0221:                    throw new IllegalArgumentException("Skin property " + '"'
0222:                            + idName + '"' + " has illegal ID value: " + '"'
0223:                            + id + '"');
0224:                }
0225:
0226:                // offset will be set later
0227:                this .valueOffset = -1;
0228:            }
0229:
0230:            /**
0231:             * Tests if two properties have the same value
0232:             *
0233:             * @param prop property to compare value with
0234:             * @return true if properties have the same value
0235:             */
0236:            abstract boolean isEqualValue(SkinPropertyBase prop);
0237:
0238:            /**
0239:             * How many entries in values array is required for 
0240:             * storing this property value
0241:             *
0242:             * @return number of array entries required for storing
0243:             * the value of this property
0244:             */
0245:            abstract int getValueOffsetDelta();
0246:
0247:            /**
0248:             * Prints values array entries for this property's value
0249:             *
0250:             * @param writer where to print entries
0251:             * @param indent indentation string for each entry
0252:             */
0253:            abstract void outputValue(BinaryOutputStream out)
0254:                    throws java.io.IOException;
0255:
0256:            /**
0257:             * Factory method: constructs SkinProperty from DOM node that
0258:             * corresponds to the property description in XML file.`
0259:             *
0260:             * @param n DOM node that corresponds to the property 
0261:             *          description in XML file
0262:             * @return SkinPropertyBase object constructed from DOM node
0263:             * @exception IllegalArgumentException if DOM node is invalid
0264:             */
0265:            static SkinPropertyBase valueOf(Node n)
0266:                    throws IllegalArgumentException {
0267:
0268:                if (debug) {
0269:                    System.err.println("Property node: " + n.getNodeName());
0270:                }
0271:
0272:                SkinPropertyBase p = null;
0273:
0274:                String idName = getAttributeValue(n, "Key");
0275:                String id = getAttributeValue(n, "KeyValue");
0276:                String value = getAttributeValue(n, "Value");
0277:
0278:                if (debug) {
0279:                    System.err.println("\tID name: " + idName);
0280:                    System.err.println("\tID: " + id);
0281:                    System.err.println("\tValue: " + value);
0282:                    System.err.println("");
0283:                }
0284:
0285:                String nodeName = n.getNodeName();
0286:
0287:                if (nodeName.equals("integer")) {
0288:                    p = new IntSkinProperty(idName, id, value);
0289:                } else if (nodeName.equals("integer_seq")) {
0290:                    p = new IntSeqSkinProperty(idName, id, value);
0291:                } else if (nodeName.equals("string")) {
0292:                    p = new StringSkinProperty(idName, id, value);
0293:                } else if (nodeName.equals("font")) {
0294:                    p = new FontSkinProperty(idName, id, value);
0295:                } else if (nodeName.equals("image")) {
0296:                    String isRomized = getAttributeValue(n, "Romized");
0297:                    p = new ImageSkinProperty(idName, id, value, isRomized);
0298:                } else if (nodeName.equals("composite_image")) {
0299:                    String totalPieces = getAttributeValue(n, "Pieces");
0300:                    String isRomized = getAttributeValue(n, "Romized");
0301:                    p = new CompositeImageSkinProperty(idName, id, value,
0302:                            totalPieces, isRomized);
0303:                } else {
0304:                    throw new IllegalArgumentException(
0305:                            "Illegal skin property node: " + '"' + nodeName
0306:                                    + '"');
0307:                }
0308:
0309:                return p;
0310:            }
0311:
0312:            /**
0313:             * Helper method: gets attribute value from node with some
0314:             * errors checking.
0315:             *
0316:             * @param n DOM node to get attribute value from
0317:             * @param attrName attribute name
0318:             * @return requested attribute value
0319:             */
0320:            private static String getAttributeValue(Node n, String attrName) {
0321:                Element e = (Element) n;
0322:                String attrValue = e.getAttribute(attrName);
0323:
0324:                return attrValue.trim();
0325:            }
0326:
0327:            /**
0328:             * Helper method for renaming symbolic property value coming
0329:             * from XML file (constant name) into another constant name.
0330:             * Needed for backward compatibility.
0331:             *
0332:             * @param value original value
0333:             * @return renamed value
0334:             */
0335:            protected static String renameSymbolicValue(String value) {
0336:                /**
0337:                 * Value can be in form of "Graphics.VALUE" where "VALUE" is 
0338:                 * the name of one of the constants defined in Graphics class.
0339:                 * Convert such value into "SkinResourcesConstants.VALUE".
0340:                 * The reason why "SkinResourcesConstants.VALUE" is not used 
0341:                 * directly in XML file is backward compatibility.
0342:                 */
0343:                if (value.startsWith("Graphics.")) {
0344:                    int dotIdx = value.indexOf(".");
0345:                    value = "SkinResourcesConstants" + value.substring(dotIdx);
0346:                }
0347:
0348:                /**
0349:                 * Value can be in form of "ScrollIndSkin.VALUE" where "VALUE" is 
0350:                 * the name of one of the constants defined in 
0351:                 * ScrollIndResourcesConstants class.
0352:                 * Convert such value into "ScrollIndResourcesConstants.VALUE".
0353:                 * The reason why "ScrollIndResourcesConstants.VALUE" is not 
0354:                 * used directly in XML file is backward compatibility.
0355:                 */
0356:                if (value.startsWith("ScrollIndSkin.")) {
0357:                    int dotIdx = value.indexOf(".");
0358:                    value = "ScrollIndResourcesConstants"
0359:                            + value.substring(dotIdx);
0360:                }
0361:
0362:                /**
0363:                 * Value can be in form of "FontResources.VALUE" where "VALUE" is 
0364:                 * the name of one of the constants defined in 
0365:                 * FontResourcesConstants class.
0366:                 * Convert such value into "FontResourcesConstants.VALUE".
0367:                 * The reason why "FontResourcesConstants.VALUE" is not 
0368:                 * used directly in XML file is backward compatibility.
0369:                 */
0370:                if (value.startsWith("FontResources.")) {
0371:                    int dotIdx = value.indexOf(".");
0372:                    value = "FontResourcesConstants" + value.substring(dotIdx);
0373:                }
0374:
0375:                return value;
0376:            }
0377:
0378:            /**
0379:             * Helper method for convertic symbolic property value into int value.
0380:             * Basically, it converts integer constant name into constant value.
0381:             *
0382:             * @param value symbolic value
0383:             * @return integer value
0384:             */
0385:            protected static int symbolicValueToInt(String value) {
0386:                int dotIdx = value.indexOf(".");
0387:                if (dotIdx == -1 || dotIdx == value.length() - 1) {
0388:                    throw new IllegalArgumentException();
0389:                }
0390:
0391:                String className = value.substring(0, dotIdx);
0392:                if (className.length() == 0) {
0393:                    throw new IllegalArgumentException();
0394:                }
0395:
0396:                className = "com.sun.midp.chameleon.skins.resources."
0397:                        + className;
0398:                Class c = null;
0399:                try {
0400:                    c = Class.forName(className);
0401:                } catch (Throwable t) {
0402:                    throw new IllegalArgumentException();
0403:                }
0404:
0405:                String fieldName = value.substring(dotIdx + 1);
0406:                if (fieldName.length() == 0) {
0407:                    throw new IllegalArgumentException();
0408:                }
0409:
0410:                Field f = null;
0411:                try {
0412:                    f = c.getField(fieldName);
0413:                } catch (Throwable t) {
0414:                    throw new IllegalArgumentException();
0415:                }
0416:
0417:                int val = 0;
0418:                try {
0419:                    val = f.getInt(null);
0420:                } catch (Throwable t) {
0421:                    throw new IllegalArgumentException();
0422:                }
0423:
0424:                return val;
0425:            }
0426:
0427:            /**
0428:             * Property value can be primitive arithmetic expression. 
0429:             * This helper method evaluates such expression. Operators
0430:             * precedence is simple, left to right.
0431:             *
0432:             * @param exp expression to evaluate
0433:             * @return integer expression value
0434:             */
0435:            protected static int evalValueExpression(String exp) {
0436:                int result = 0;
0437:                char op = '=';
0438:
0439:                StringTokenizer st = new StringTokenizer(exp);
0440:                while (true) {
0441:                    String v = renameSymbolicValue(st.nextToken());
0442:
0443:                    int intVal = 0;
0444:                    try {
0445:                        int radix = 10;
0446:                        if (v.startsWith("0x")) {
0447:                            v = v.substring(2);
0448:                            radix = 16;
0449:                        }
0450:                        intVal = Integer.parseInt(v, radix);
0451:                    } catch (NumberFormatException e) {
0452:                        intVal = symbolicValueToInt(v);
0453:                    }
0454:
0455:                    switch (op) {
0456:                    case '=':
0457:                        result = intVal;
0458:                        break;
0459:
0460:                    case '|':
0461:                        result |= intVal;
0462:                        break;
0463:
0464:                    default:
0465:                        throw new IllegalArgumentException();
0466:                    }
0467:
0468:                    if (!st.hasMoreTokens()) {
0469:                        break;
0470:                    }
0471:
0472:                    String opStr = st.nextToken();
0473:                    if (opStr.length() > 1) {
0474:                        throw new IllegalArgumentException();
0475:                    }
0476:                    op = (opStr.toCharArray())[0];
0477:                }
0478:
0479:                return result;
0480:            }
0481:        }
0482:
0483:        /**
0484:         * Integer property
0485:         */
0486:        class IntSkinProperty extends SkinPropertyBase {
0487:
0488:            /**
0489:             * Property's value: integer number 
0490:             */
0491:            int value;
0492:
0493:            /**
0494:             * Constructor
0495:             * 
0496:             * @param idName name of the property's ID
0497:             * @param id property's ID
0498:             * @param value integer value as string
0499:             */
0500:            IntSkinProperty(String idName, String id, String value) {
0501:                super (idName, id);
0502:
0503:                String v = value;
0504:                try {
0505:                    this .value = evalValueExpression(v);
0506:                } catch (Throwable t) {
0507:                    throw new IllegalArgumentException(
0508:                            "Invalid int property value: " + value);
0509:                }
0510:            }
0511:
0512:            /**
0513:             * Tests if two properties have the same value
0514:             *
0515:             * @param prop property to compare value with
0516:             * @return true if properties have the same value
0517:             */
0518:            boolean isEqualValue(SkinPropertyBase prop) {
0519:                if (!(prop instanceof  IntSkinProperty)) {
0520:                    return false;
0521:                }
0522:                IntSkinProperty p = (IntSkinProperty) prop;
0523:
0524:                return (p.value == value);
0525:            }
0526:
0527:            /**
0528:             * How many entries in values array is required for 
0529:             * storing this property value
0530:             *
0531:             * @return number of array entries required for storing
0532:             * the value of this property
0533:             */
0534:            int getValueOffsetDelta() {
0535:                // For performance optimization, integers values aren't stored in
0536:                // separate values array as in case for other properties. So there
0537:                // is no offset delta for integer value.
0538:                return 0;
0539:            }
0540:
0541:            /**
0542:             * Prints values array entries for this property's value
0543:             *
0544:             * @param writer where to print entries
0545:             * @param indent indentation string for each entry
0546:             */
0547:            void outputValue(BinaryOutputStream out) throws java.io.IOException {
0548:
0549:                out.writeInt(value);
0550:            }
0551:        }
0552:
0553:        /**
0554:         * Integers sequence property
0555:         */
0556:        class IntSeqSkinProperty extends SkinPropertyBase {
0557:
0558:            /**
0559:             * Propety's value: array of integers 
0560:             */
0561:            int[] value;
0562:
0563:            /**
0564:             * Constructor
0565:             *
0566:             * @param idName name of the property's ID
0567:             * @param id property's ID
0568:             * @param value comma separated integer values as string
0569:             */
0570:            IntSeqSkinProperty(String idName, String id, String value) {
0571:                super (idName, id);
0572:
0573:                // find number of integers in sequence
0574:                int seqLen = 0;
0575:                char[] chars = value.toCharArray();
0576:                int numStart = 0;
0577:                for (int i = 0; i <= chars.length; ++i) {
0578:                    if (i == chars.length || chars[i] == ',') {
0579:                        seqLen++;
0580:                        numStart = i + 1;
0581:                    }
0582:                }
0583:
0584:                this .value = new int[seqLen];
0585:
0586:                // fill values array
0587:                int idx = 0;
0588:                numStart = 0;
0589:                for (int i = 0; i <= chars.length; ++i) {
0590:                    if (i == chars.length || chars[i] == ',') {
0591:                        String v = (value.substring(numStart, i)).trim();
0592:                        int intVal = 0;
0593:                        try {
0594:                            intVal = evalValueExpression(v);
0595:                        } catch (Throwable t) {
0596:                            throw new IllegalArgumentException(
0597:                                    "Invalid integer sequence property value: "
0598:                                            + value);
0599:                        }
0600:
0601:                        this .value[idx++] = intVal;
0602:                        numStart = i + 1;
0603:                    }
0604:                }
0605:            }
0606:
0607:            /**
0608:             * Tests if two properties have the same value
0609:             *
0610:             * @param prop property to compare value with
0611:             * @return true if properties have the same value
0612:             */
0613:            boolean isEqualValue(SkinPropertyBase prop) {
0614:                if (!(prop instanceof  IntSeqSkinProperty)) {
0615:                    return false;
0616:                }
0617:                IntSeqSkinProperty p = (IntSeqSkinProperty) prop;
0618:
0619:                if (p.value.length != value.length) {
0620:                    return false;
0621:                }
0622:
0623:                for (int i = 0; i < value.length; ++i) {
0624:                    if (p.value[i] != value[i]) {
0625:                        return false;
0626:                    }
0627:                }
0628:
0629:                return true;
0630:            }
0631:
0632:            /**
0633:             * How many entries in values array is required for 
0634:             * storing this property value
0635:             *
0636:             * @return number of array entries required for storing
0637:             * the value of this property
0638:             */
0639:            int getValueOffsetDelta() {
0640:                // integers sequence value is stored as length of 
0641:                // the sequence followed by sequence integers
0642:                return (1 + value.length);
0643:            }
0644:
0645:            /**
0646:             * Prints values array entries for this property's value
0647:             *
0648:             * @param writer where to print entries
0649:             * @param indent indentation string for each entry
0650:             */
0651:            void outputValue(BinaryOutputStream out) throws java.io.IOException {
0652:
0653:                // out sequence length
0654:                out.writeInt(value.length);
0655:
0656:                // out sequence integers
0657:                for (int i = 0; i < value.length; ++i) {
0658:                    out.writeInt(value[i]);
0659:                }
0660:            }
0661:        }
0662:
0663:        /**
0664:         * String property
0665:         */
0666:        class StringSkinProperty extends SkinPropertyBase {
0667:
0668:            /**
0669:             * Property's value: string
0670:             */
0671:            String value;
0672:
0673:            /**
0674:             * Constructor
0675:             *
0676:             * @param idName name of the property's ID
0677:             * @param id property's ID
0678:             * @param value string value
0679:             */
0680:            StringSkinProperty(String idName, String id, String value) {
0681:                super (idName, id);
0682:                this .value = value;
0683:            }
0684:
0685:            /**
0686:             * Tests if two properties have the same value
0687:             *
0688:             * @param prop property to compare value with
0689:             * @return true if properties have the same value
0690:             */
0691:            boolean isEqualValue(SkinPropertyBase prop) {
0692:                if (!(prop instanceof  StringSkinProperty)) {
0693:                    return false;
0694:                }
0695:                StringSkinProperty p = (StringSkinProperty) prop;
0696:
0697:                return p.value.equals(value);
0698:            }
0699:
0700:            /**
0701:             * How many entries in values array is required for 
0702:             * storing this property value
0703:             *
0704:             * @return number of array entries required for storing
0705:             * the value of this property
0706:             */
0707:            int getValueOffsetDelta() {
0708:                return 1;
0709:            }
0710:
0711:            /**
0712:             * Prints values array entries for this property's value
0713:             *
0714:             * @param writer where to print entries
0715:             * @param indent indentation string for each entry
0716:             */
0717:            void outputValue(BinaryOutputStream out) throws java.io.IOException {
0718:
0719:                out.writeString(value);
0720:            }
0721:        }
0722:
0723:        /**
0724:         * Font property
0725:         */
0726:        class FontSkinProperty extends SkinPropertyBase {
0727:
0728:            /**
0729:             * Property's value: integer font type 
0730:             */
0731:            int value;
0732:
0733:            /**
0734:             * Constructor
0735:             *
0736:             * @param idName name of the property's ID
0737:             * @param id property's ID
0738:             * @param value integer font ID as string
0739:             */
0740:            FontSkinProperty(String idName, String id, String value) {
0741:                super (idName, id);
0742:
0743:                String v = value;
0744:                try {
0745:                    this .value = evalValueExpression(v);
0746:                } catch (Throwable t) {
0747:                    throw new IllegalArgumentException(
0748:                            "Invalid font property value: " + value);
0749:                }
0750:            }
0751:
0752:            /**
0753:             * Tests if two properties have the same value
0754:             *
0755:             * @param prop property to compare value with
0756:             * @return true if properties have the same value
0757:             */
0758:            boolean isEqualValue(SkinPropertyBase prop) {
0759:                if (!(prop instanceof  FontSkinProperty)) {
0760:                    return false;
0761:                }
0762:                FontSkinProperty p = (FontSkinProperty) prop;
0763:
0764:                return (p.value == value);
0765:            }
0766:
0767:            /**
0768:             * How many entries in values array is required for 
0769:             * storing this property value
0770:             *
0771:             * @return number of array entries required for storing
0772:             * the value of this property
0773:             */
0774:            int getValueOffsetDelta() {
0775:                return 1;
0776:            }
0777:
0778:            /**
0779:             * Prints values array entries for this property's value
0780:             *
0781:             * @param writer where to print entries
0782:             * @param indent indentation string for each entry
0783:             */
0784:            void outputValue(BinaryOutputStream out) throws java.io.IOException {
0785:
0786:                out.writeInt(value);
0787:            }
0788:        }
0789:
0790:        /**
0791:         * Image property
0792:         */
0793:        class ImageSkinProperty extends SkinPropertyBase {
0794:
0795:            /**
0796:             * Property's value: image file name without extension
0797:             */
0798:            String value;
0799:
0800:            /**
0801:             * Romize this image
0802:             */
0803:            boolean isRomized;
0804:
0805:            /**
0806:             * True, if image value has been specified,
0807:             * i.e. it is not an empty string
0808:             */
0809:            boolean hasValue;
0810:
0811:            /** total unique images for all properties */
0812:            static int totalImages;
0813:
0814:            /**
0815:             * Constructor
0816:             *
0817:             * @param idName name of the property's ID
0818:             * @param id property's ID
0819:             * @param value image file name without extension
0820:             * @param isRomized boolean value as string
0821:             * @exception IllegalArgumentException if some of parameters
0822:             * are invalid
0823:             */
0824:            ImageSkinProperty(String idName, String id, String value,
0825:                    String isRomized) throws IllegalArgumentException {
0826:
0827:                super (idName, id);
0828:                this .value = value;
0829:
0830:                if (isRomized.equals("true")) {
0831:                    this .isRomized = true;
0832:                } else if (isRomized.equals("false")) {
0833:                    this .isRomized = false;
0834:                } else {
0835:                    throw new IllegalArgumentException("Skin property " + '"'
0836:                            + idName + '"' + " has illegal romization value: "
0837:                            + '"' + isRomized + '"');
0838:                }
0839:
0840:                hasValue = true;
0841:                if (value.equals("")) {
0842:                    hasValue = false;
0843:                }
0844:            }
0845:
0846:            /**
0847:             * Tests if two properties have the same value
0848:             *
0849:             * @param prop property to compare value with
0850:             * @return true if properties have the same value
0851:             */
0852:            boolean isEqualValue(SkinPropertyBase prop) {
0853:                if (!(prop instanceof  ImageSkinProperty)) {
0854:                    return false;
0855:                }
0856:                ImageSkinProperty p = (ImageSkinProperty) prop;
0857:
0858:                return p.value.equals(value);
0859:            }
0860:
0861:            /**
0862:             * How many entries in values array is required for 
0863:             * storing this property value
0864:             *
0865:             * @return number of array entries required for storing
0866:             * the value of this property
0867:             */
0868:            int getValueOffsetDelta() {
0869:                return 1;
0870:            }
0871:
0872:            /**
0873:             * Prints values array entries for this property's value
0874:             *
0875:             * @param writer where to print entries
0876:             * @param indent indentation string for each entry
0877:             */
0878:            void outputValue(BinaryOutputStream out) throws java.io.IOException {
0879:
0880:                out.writeString(value);
0881:            }
0882:        }
0883:
0884:        /**
0885:         * Composite image property. Composite image is an image that consists
0886:         * of several pieces, where each piece is some image file.
0887:         */
0888:        class CompositeImageSkinProperty extends SkinPropertyBase {
0889:            /**
0890:             * Property's value: pieces files names without extension.
0891:             * File name for each piece is constructed from base prefix by
0892:             * addition of piece number, i.e. if the prefix is "image" and 
0893:             * number of pieces is 2, then file name for first piece is 
0894:             * "image0" and for the second piece is "image1".
0895:             */
0896:            String[] value;
0897:
0898:            /**
0899:             * Number of pieces
0900:             */
0901:            int totalPieces;
0902:
0903:            /**
0904:             * Romize this image
0905:             */
0906:            boolean isRomized;
0907:
0908:            /**
0909:             * True, if image value has been specified,
0910:             * i.e. it is not an empty string
0911:             */
0912:            boolean hasValue;
0913:
0914:            /** total unique images for all properties */
0915:            static int totalImages;
0916:
0917:            /**
0918:             * Constructor
0919:             *
0920:             * @param idName name of the property's ID
0921:             * @param id property's ID
0922:             * @param value base prefix for pieces files names
0923:             * @param totalPieces number of pieces in composite image
0924:             * @param isRomized boolean value as string
0925:             * @exception IllegalArgumentException if some of parameters
0926:             * are invalid
0927:             */
0928:            CompositeImageSkinProperty(String idName, String id, String value,
0929:                    String totalPieces, String isRomized)
0930:                    throws IllegalArgumentException {
0931:
0932:                super (idName, id);
0933:
0934:                try {
0935:                    this .totalPieces = Integer.parseInt(totalPieces);
0936:                } catch (NumberFormatException e) {
0937:                    throw new IllegalArgumentException(
0938:                            "Composite image skin property " + '"' + idName
0939:                                    + '"' + " has illegal total pieces value: "
0940:                                    + '"' + totalPieces + '"');
0941:                }
0942:
0943:                this .value = new String[this .totalPieces];
0944:                for (int i = 0; i < this .totalPieces; ++i) {
0945:                    String v = "";
0946:                    if (!value.equals("")) {
0947:                        v = value + i;
0948:                    }
0949:
0950:                    this .value[i] = v;
0951:                }
0952:
0953:                if (isRomized.equals("true")) {
0954:                    this .isRomized = true;
0955:                } else if (isRomized.equals("false")) {
0956:                    this .isRomized = false;
0957:                } else {
0958:                    throw new IllegalArgumentException("Skin property " + '"'
0959:                            + idName + '"' + " has illegal romization value: "
0960:                            + '"' + isRomized + '"');
0961:                }
0962:
0963:                hasValue = true;
0964:                if (value.equals("")) {
0965:                    hasValue = false;
0966:                }
0967:            }
0968:
0969:            /**
0970:             * Tests if two properties have the same value
0971:             *
0972:             * @param prop property to compare value with
0973:             * @return true if properties have the same value
0974:             */
0975:            boolean isEqualValue(SkinPropertyBase prop) {
0976:                if (!(prop instanceof  CompositeImageSkinProperty)) {
0977:                    return false;
0978:                }
0979:                CompositeImageSkinProperty p = (CompositeImageSkinProperty) prop;
0980:
0981:                if (p.value.length != value.length) {
0982:                    return false;
0983:                }
0984:
0985:                boolean equal = true;
0986:                for (int i = 0; i < value.length; ++i) {
0987:                    if (!(p.value[i].equals(value[i]))) {
0988:                        equal = false;
0989:                        break;
0990:                    }
0991:                }
0992:
0993:                return equal;
0994:            }
0995:
0996:            /**
0997:             * How many entries in values array is required for 
0998:             * storing this property value
0999:             *
1000:             * @return number of array entries required for storing
1001:             * the value of this property
1002:             */
1003:            int getValueOffsetDelta() {
1004:                // for composite image, values array contain 
1005:                // file names of image pieces
1006:                return value.length;
1007:            }
1008:
1009:            /**
1010:             * Prints values array entries for this property's value
1011:             *
1012:             * @param writer where to print entries
1013:             * @param indent indentation string for each entry
1014:             */
1015:            void outputValue(BinaryOutputStream out) throws java.io.IOException {
1016:
1017:                // output pieces file names
1018:                for (int i = 0; i < value.length; ++i) {
1019:                    out.writeString(value[i]);
1020:                }
1021:            }
1022:        }
1023:
1024:        /**
1025:         * Represents romized image
1026:         */
1027:        final class RomizedImage {
1028:            /** romized image data */
1029:            byte[] imageData;
1030:
1031:            /** romized image index */
1032:            int imageIndex;
1033:
1034:            /**
1035:             * Constructor
1036:             *
1037:             * @param imageData romized image data
1038:             * @param imageIndex romized image index
1039:             */
1040:            RomizedImage(byte imageData[], int imageIndex) {
1041:                this .imageData = imageData;
1042:                this .imageIndex = imageIndex;
1043:            }
1044:
1045:            /**
1046:             * Prints romized image data as C array
1047:             *
1048:             * @param writer where to print
1049:             * @param indent indent string for each row
1050:             * @param maxColumns max number of columns
1051:             */
1052:            void printDataArray(PrintWriter writer, String indent,
1053:                    int maxColumns) {
1054:                int len = imageData.length;
1055:
1056:                writer.print(indent);
1057:                for (int i = 0; i < len; i++) {
1058:                    writer.print(toHex(imageData[i]));
1059:                    if (i != len - 1) {
1060:                        writer.print(", ");
1061:
1062:                        if ((i > 0) && ((i + 1) % maxColumns == 0)) {
1063:                            writer.println("");
1064:                            writer.print(indent);
1065:                        }
1066:                    }
1067:                }
1068:            }
1069:
1070:            /**
1071:             * Converts byte to a hex string
1072:             *
1073:             * @param b byte value to convert
1074:             * @return hex representation of byte
1075:             */
1076:            private static String toHex(byte b) {
1077:                Integer I = new Integer((((int) b) << 24) >>> 24);
1078:                int i = I.intValue();
1079:
1080:                if (i < (byte) 16) {
1081:                    return "0x0" + Integer.toString(i, 16);
1082:                } else {
1083:                    return "0x" + Integer.toString(i, 16);
1084:                }
1085:            }
1086:        }
1087:
1088:        /**
1089:         * Creates RomizedImage instances
1090:         */
1091:        final class RomizedImageFactory {
1092:            /** for converting image into raw format */
1093:            ImageToRawConverter converter;
1094:
1095:            /** romized images counter */
1096:            int romizedImageCounter = 0;
1097:
1098:            /**
1099:             * Constructor
1100:             *
1101:             * @param converter converter to use for converting images
1102:             * into raw format
1103:             */
1104:            private RomizedImageFactory(ImageToRawConverter converter) {
1105:                this .converter = converter;
1106:            }
1107:
1108:            /**
1109:             * Creates RomizedImage from BufferedImage object
1110:             *
1111:             * @param image image to create romized image from
1112:             * @param imageIndex romized image index
1113:             * @return created RomizedImage
1114:             */
1115:            RomizedImage createFromBufferedImage(BufferedImage image,
1116:                    int imageIndex) {
1117:
1118:                int width = image.getWidth(null);
1119:                int height = image.getHeight(null);
1120:                boolean hasAlpha = image.getColorModel().hasAlpha();
1121:                int[] imageData = getBufferedImageData(image);
1122:
1123:                byte[] rawData = converter.convertToRaw(imageData, width,
1124:                        height, hasAlpha);
1125:
1126:                return new RomizedImage(rawData, romizedImageCounter++);
1127:            }
1128:
1129:            /**
1130:             * Utility method. Gets BuffredImage data as in array.
1131:             *
1132:             * @param image BufferedImage to return data for
1133:             * @return image data as byte array
1134:             */
1135:            private static int[] getBufferedImageData(BufferedImage image) {
1136:                int width = image.getWidth(null);
1137:                int height = image.getHeight(null);
1138:                BufferedImage bi = new BufferedImage(width, height,
1139:                        BufferedImage.TYPE_INT_ARGB);
1140:
1141:                Graphics g = bi.getGraphics();
1142:                try {
1143:                    g.drawImage(image, 0, 0, width, height, null);
1144:                } finally {
1145:                    g.dispose();
1146:                }
1147:
1148:                DataBuffer srcBuf = bi.getData().getDataBuffer();
1149:                int[] buf = ((DataBufferInt) srcBuf).getData();
1150:
1151:                return buf;
1152:            }
1153:
1154:            /**
1155:             * Returns factory class instance
1156:             *
1157:             * @param rawFormat format of raw file
1158:             * @param colorFormat format of pixel in raw file
1159:             * @param endian romized image data endianess
1160:             * @return RomizedImage factory
1161:             */
1162:            static RomizedImageFactory getFactory(int rawFormat,
1163:                    int colorFormat, int endian) {
1164:
1165:                ImageToRawConverter converter = new ImageToRawConverter(
1166:                        rawFormat, colorFormat, endian);
1167:
1168:                return new RomizedImageFactory(converter);
1169:            }
1170:        }
1171:
1172:        /**
1173:         * Binary output stream capable of writing data 
1174:         * in big/little endian format.
1175:         */
1176:        final class BinaryOutputStream {
1177:            /** Underlying stream for writing bytes into */
1178:            private DataOutputStream outputStream = null;
1179:
1180:            /** true for big endian format, false for little */
1181:            private boolean isBigEndian = false;
1182:
1183:            /**
1184:             * Constructor
1185:             *
1186:             * @param out underlying output stream for writing bytes into
1187:             * @param isBigEndian true for big endian format, false for little
1188:             */
1189:            BinaryOutputStream(OutputStream out, boolean isBigEndian) {
1190:                this .outputStream = new DataOutputStream(out);
1191:                this .isBigEndian = isBigEndian;
1192:            }
1193:
1194:            /**
1195:             * Writes byte value into stream
1196:             *
1197:             * @param value byte value to write
1198:             */
1199:            public void writeByte(int value) throws java.io.IOException {
1200:
1201:                outputStream.writeByte(value);
1202:            }
1203:
1204:            /**
1205:             * Writes integer value into stream
1206:             *
1207:             * @param value integer value to write
1208:             */
1209:            public void writeInt(int value) throws java.io.IOException {
1210:
1211:                if (isBigEndian) {
1212:                    outputStream.writeByte((value >> 24) & 0xFF);
1213:                    outputStream.writeByte((value >> 16) & 0xFF);
1214:                    outputStream.writeByte((value >> 8) & 0xFF);
1215:                    outputStream.writeByte(value & 0xFF);
1216:                } else {
1217:                    outputStream.writeByte(value & 0xFF);
1218:                    outputStream.writeByte((value >> 8) & 0xFF);
1219:                    outputStream.writeByte((value >> 16) & 0xFF);
1220:                    outputStream.writeByte((value >> 24) & 0xFF);
1221:                }
1222:            }
1223:
1224:            /**
1225:             * Writes string into stream. The string data is written 
1226:             * in follwoing order:
1227:             * - Number of bytes for string chars
1228:             * - Encoding (US ASCII or UTF8)
1229:             * - String chars as bytes
1230:             * 
1231:             * The number of bytes for string chars is written as 
1232:             * single byte, so it can't exceed 255.
1233:             *
1234:             * @param value String value to write into stream
1235:             */
1236:            public void writeString(String value) throws java.io.IOException {
1237:
1238:                byte[] chars = value.getBytes("UTF8");
1239:                int length = chars.length;
1240:
1241:                // determine what encoding to use
1242:                int encoding = SkinResourcesConstants.STRING_ENCODING_USASCII;
1243:                for (int i = 0; i < length; ++i) {
1244:                    int ch = chars[i] & 0xFF;
1245:                    if (ch >= 128) {
1246:                        encoding = SkinResourcesConstants.STRING_ENCODING_UTF8;
1247:                        break;
1248:                    }
1249:                }
1250:
1251:                if (encoding == SkinResourcesConstants.STRING_ENCODING_UTF8) {
1252:                    System.err.println("UTF8: " + value);
1253:                    // for '\0' at the end of the string
1254:                    length += 1;
1255:                }
1256:
1257:                // write string data length
1258:                if (length > 255) {
1259:                    throw new IllegalArgumentException(
1260:                            "String data length exceeds 255 bytes");
1261:                }
1262:                outputStream.writeByte(length);
1263:
1264:                // write string encoding
1265:                outputStream.writeByte(encoding);
1266:
1267:                // write string data
1268:                for (int i = 0; i < chars.length; ++i) {
1269:                    outputStream.writeByte(chars[i] & 0xFF);
1270:                }
1271:
1272:                if (encoding == SkinResourcesConstants.STRING_ENCODING_UTF8) {
1273:                    // '\0' at the end of the string
1274:                    outputStream.writeByte(0);
1275:                }
1276:            }
1277:
1278:            /**
1279:             * Closes stream
1280:             */
1281:            public void close() throws java.io.IOException {
1282:
1283:                outputStream.close();
1284:            }
1285:        }
1286:
1287:        /**
1288:         * Perform the romization
1289:         */
1290:        class SkinRomizer {
1291:            /** current romization job */
1292:            RomizationJob romizationJob;
1293:
1294:            /** XML with skin properties as Document */
1295:            private Document domDoc = null;
1296:
1297:            /** Be verbose: print some debug info while running */
1298:            private boolean debug = false;
1299:
1300:            /** All skin properties */
1301:            Vector allProps = null;
1302:
1303:            /** All integers sequence skin properties */
1304:            Vector intSeqProps = null;
1305:
1306:            /** All string skin properties */
1307:            Vector stringProps = null;
1308:
1309:            /** All integers font skin properties */
1310:            Vector fontProps = null;
1311:
1312:            /** All image skin properties */
1313:            Vector imageProps = null;
1314:
1315:            /** All composite image skin properties */
1316:            Vector compImageProps = null;
1317:
1318:            /** All romized images */
1319:            Vector romizedImages = null;
1320:
1321:            /** Romized image factory */
1322:            RomizedImageFactory romizedImageFactory;
1323:
1324:            /** Character output file writer */
1325:            PrintWriter writer = null;
1326:
1327:            /** Binary output file stream */
1328:            BinaryOutputStream outputStream = null;
1329:
1330:            /** raw image file format */
1331:            int rawFormat = ImageToRawConverter.FORMAT_INVALID;
1332:
1333:            /** raw image color format */
1334:            int colorFormat = ImageToRawConverter.FORMAT_INVALID;
1335:
1336:            /** raw image data endianess */
1337:            int endianFormat = ImageToRawConverter.FORMAT_INVALID;
1338:
1339:            /** array of strings used in XML file to specify raw image format */
1340:            static String[] imageFormatStrings = {
1341:            // raw file formats 
1342:                    "Putpixel", "ARGB",
1343:                    // endianess
1344:                    "Little", "Big",
1345:                    // supported pixel formats
1346:                    "565", "888", };
1347:
1348:            /** array of constants corresponding to strings above */
1349:            static int[] imageFormats = {
1350:                    // raw file formats 
1351:                    ImageToRawConverter.RAW_FORMAT_PP,
1352:                    ImageToRawConverter.RAW_FORMAT_ARGB,
1353:                    // endianess
1354:                    ImageToRawConverter.INT_FORMAT_LITTLE_ENDIAN,
1355:                    ImageToRawConverter.INT_FORMAT_BIG_ENDIAN,
1356:                    // supported pixel formats        
1357:                    ImageToRawConverter.COLOR_FORMAT_565,
1358:                    ImageToRawConverter.COLOR_FORMAT_888 };
1359:
1360:            /**
1361:             * Constructor
1362:             *
1363:             * @param dbg print some debug output while running
1364:             */
1365:            public SkinRomizer(boolean dbg) {
1366:                debug = dbg;
1367:                SkinPropertyBase.debug = dbg;
1368:
1369:            }
1370:
1371:            /**
1372:             * Does the actual romization
1373:             * 
1374:             * @param romizationJob romization to perform
1375:             * @exception Exception if there was an error during romization
1376:             */
1377:            public void romize(RomizationJob romizationJob) throws Exception {
1378:
1379:                this .romizationJob = romizationJob;
1380:
1381:                allProps = new Vector();
1382:                intSeqProps = new Vector();
1383:                stringProps = new Vector();
1384:                fontProps = new Vector();
1385:                imageProps = new Vector();
1386:                compImageProps = new Vector();
1387:
1388:                // load XML file as DOM tree 
1389:                DocumentBuilderFactory domFactory = DocumentBuilderFactory
1390:                        .newInstance();
1391:
1392:                // do not validate input XML file,
1393:                // we assume it has been validated before
1394:                domFactory.setValidating(false);
1395:
1396:                DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
1397:                domDoc = domBuilder.parse(new File(
1398:                        romizationJob.skinXMLFileName));
1399:
1400:                // traverse DOM tree constructed fro input XML and 
1401:                // collect all skin properties described there
1402:                collectSkinProperties(domDoc.getDocumentElement());
1403:
1404:                // now, when we know format of romized images,
1405:                // we can create romized images factory
1406:                romizedImageFactory = RomizedImageFactory.getFactory(rawFormat,
1407:                        colorFormat, endianFormat);
1408:
1409:                // assign offsets
1410:                assignPropertiesValuesOffsets(intSeqProps, 0);
1411:                assignPropertiesValuesOffsets(stringProps, 0);
1412:                assignPropertiesValuesOffsets(fontProps, 0);
1413:
1414:                // values for composite image properties are stored in same
1415:                // array as values for image properties. first, values for 
1416:                // image properties are stored, followed by values for 
1417:                // composite image properties.
1418:                int lastOffset = assignPropertiesValuesOffsets(imageProps, 0);
1419:                ImageSkinProperty.totalImages = lastOffset - 1;
1420:                lastOffset = assignPropertiesValuesOffsets(compImageProps,
1421:                        lastOffset);
1422:                CompositeImageSkinProperty.totalImages = lastOffset - 1;
1423:
1424:                // total unique skin images
1425:                int totalImages = ImageSkinProperty.totalImages
1426:                        + CompositeImageSkinProperty.totalImages;
1427:
1428:                // if image isn't romized, then corresponding value will be null
1429:                romizedImages = new Vector(totalImages);
1430:                romizedImages.setSize(totalImages);
1431:
1432:                romizeImages();
1433:
1434:                // output generated file
1435:                makeDirectoryTree(romizationJob.outBinFileName);
1436:
1437:                OutputStream out = new BufferedOutputStream(
1438:                        new FileOutputStream(romizationJob.outBinFileName),
1439:                        8192);
1440:                outputStream = new BinaryOutputStream(
1441:                        out,
1442:                        endianFormat == ImageToRawConverter.INT_FORMAT_BIG_ENDIAN);
1443:
1444:                writeBinHeader();
1445:                writeRomizedProperties();
1446:                outputStream.close();
1447:
1448:                out = new FileOutputStream(romizationJob.outCFileName);
1449:                writer = new PrintWriter(new OutputStreamWriter(out));
1450:
1451:                writeCHeader();
1452:                writeRomizedImagesData();
1453:                writeGetMethod();
1454:                writer.close();
1455:            }
1456:
1457:            /**
1458:             * Walks the XML tree and collects all skin properties elements
1459:             * 
1460:             * @param n current DOM node in document
1461:             * @exception Exception if there was an error during romization
1462:             */
1463:            private void collectSkinProperties(Node n) throws Exception {
1464:
1465:                if (n.getNodeName().equals("skin") && (n instanceof  Element)) {
1466:                    NodeList list = n.getChildNodes();
1467:                    for (int i = 0; i < list.getLength(); i++) {
1468:                        collectSkinProperties(list.item(i));
1469:                    }
1470:                } else if (n.getNodeName().equals("rawimage")
1471:                        && (n instanceof  Element)) {
1472:
1473:                    collectImageFormat(n);
1474:                } else if (n.getNodeName().equals("skin_properties")
1475:                        && (n instanceof  Element)) {
1476:
1477:                    NodeList list = n.getChildNodes();
1478:                    for (int i = 0; i < list.getLength(); i++) {
1479:                        collectSkinProperty(list.item(i));
1480:                    }
1481:                } else {
1482:                    NodeList list = n.getChildNodes();
1483:                    for (int i = 0; i < list.getLength(); i++) {
1484:                        collectSkinProperties(list.item(i));
1485:                    }
1486:                }
1487:            }
1488:
1489:            /**
1490:             * Collects raw images format specification
1491:             * @param n current DOM node in document
1492:             * @exception Exception if there was an error during romization
1493:             */
1494:            private void collectImageFormat(Node n) {
1495:                Element e = (Element) n;
1496:
1497:                String rawFormatStr = e.getAttribute("Format");
1498:                rawFormat = ImageToRawConverter.FORMAT_INVALID;
1499:                for (int i = 0; i < imageFormatStrings.length; ++i) {
1500:                    if (imageFormatStrings[i].equals(rawFormatStr)) {
1501:                        rawFormat = imageFormats[i];
1502:                        break;
1503:                    }
1504:                }
1505:                if (rawFormat == ImageToRawConverter.FORMAT_INVALID) {
1506:                    throw new IllegalArgumentException(
1507:                            "invalid raw file format " + '"' + rawFormatStr
1508:                                    + '"');
1509:                }
1510:
1511:                String colorFormatStr = e.getAttribute("Colors");
1512:                colorFormat = ImageToRawConverter.FORMAT_INVALID;
1513:                for (int i = 0; i < imageFormatStrings.length; ++i) {
1514:                    if (imageFormatStrings[i].equals(colorFormatStr)) {
1515:                        colorFormat = imageFormats[i];
1516:                        break;
1517:                    }
1518:                }
1519:                if (colorFormat == ImageToRawConverter.FORMAT_INVALID) {
1520:                    throw new IllegalArgumentException("invalid color format "
1521:                            + '"' + colorFormatStr + '"');
1522:                }
1523:
1524:                String endianFormatStr = e.getAttribute("Endian");
1525:                endianFormat = ImageToRawConverter.FORMAT_INVALID;
1526:                for (int i = 0; i < imageFormatStrings.length; ++i) {
1527:                    if (imageFormatStrings[i].equals(endianFormatStr)) {
1528:                        endianFormat = imageFormats[i];
1529:                        break;
1530:                    }
1531:                }
1532:                if (endianFormat == ImageToRawConverter.FORMAT_INVALID) {
1533:                    throw new IllegalArgumentException("invalid color format "
1534:                            + '"' + endianFormatStr + '"');
1535:                }
1536:
1537:                if (!ImageToRawConverter.isFormatSupported(rawFormat,
1538:                        colorFormat)) {
1539:                    throw new IllegalArgumentException(
1540:                            "unsupported romized image format: " + "raw file "
1541:                                    + '"' + rawFormat + '"' + ", color " + '"'
1542:                                    + colorFormat + '"');
1543:                }
1544:            }
1545:
1546:            /**
1547:             * Collects single skin property element.
1548:             *
1549:             * @param n DOM node corresponding to skin property description
1550:             * in XML file
1551:             * @exception Exception if there was an error during romization
1552:             */
1553:            private void collectSkinProperty(Node n) throws Exception {
1554:
1555:                if (n instanceof  Element) {
1556:                    SkinPropertyBase p = SkinPropertyBase.valueOf(n);
1557:
1558:                    // ID of the property is the index into skinProperties vector
1559:                    if (allProps.size() < p.id + 1) {
1560:                        allProps.setSize(p.id + 1);
1561:                    }
1562:
1563:                    if (allProps.elementAt(p.id) != null) {
1564:                        throw new IllegalArgumentException(
1565:                                "Duplicate skin property " + p.idName);
1566:                    }
1567:                    allProps.setElementAt(p, p.id);
1568:
1569:                    if (p instanceof  IntSeqSkinProperty) {
1570:                        intSeqProps.add(p);
1571:                    } else if (p instanceof  StringSkinProperty) {
1572:                        stringProps.add(p);
1573:                    } else if (p instanceof  FontSkinProperty) {
1574:                        fontProps.add(p);
1575:                    } else if (p instanceof  ImageSkinProperty) {
1576:                        ImageSkinProperty ip = (ImageSkinProperty) p;
1577:                        if (romizationJob.imageRomOverride.equals("all")) {
1578:                            ip.isRomized = true;
1579:                        } else if (romizationJob.imageRomOverride
1580:                                .equals("none")) {
1581:                            ip.isRomized = false;
1582:                        }
1583:
1584:                        imageProps.add(p);
1585:                    } else if (p instanceof  CompositeImageSkinProperty) {
1586:                        CompositeImageSkinProperty ip = (CompositeImageSkinProperty) p;
1587:                        if (romizationJob.imageRomOverride.equals("all")) {
1588:                            ip.isRomized = true;
1589:                        } else if (romizationJob.imageRomOverride
1590:                                .equals("none")) {
1591:                            ip.isRomized = false;
1592:                        }
1593:
1594:                        compImageProps.add(p);
1595:                    }
1596:                }
1597:            }
1598:
1599:            /**
1600:             * Assigns offsets into properties values array
1601:             *
1602:             * @param props properties to assign offsets for
1603:             * @param startOffset offset to start from
1604:             * @return offset past the last property value
1605:             */
1606:            private static int assignPropertiesValuesOffsets(Vector props,
1607:                    int startOffset) {
1608:
1609:                // current (last) offset in the values array
1610:                int curOffset = startOffset;
1611:
1612:                for (int i = 0; i < props.size(); ++i) {
1613:                    SkinPropertyBase curP = (SkinPropertyBase) props
1614:                            .elementAt(i);
1615:
1616:                    // properties with same values share same offset,
1617:                    // so look if there already was property with same value
1618:                    int sameValueOffset = -1;
1619:                    for (int j = i - 1; j >= 0; --j) {
1620:                        SkinPropertyBase p = (SkinPropertyBase) props
1621:                                .elementAt(j);
1622:                        if (p.isEqualValue(curP)) {
1623:                            sameValueOffset = p.valueOffset;
1624:                            break;
1625:                        }
1626:                    }
1627:
1628:                    if (sameValueOffset != -1) {
1629:                        // use offset from property with same value
1630:                        curP.valueOffset = sameValueOffset;
1631:                    } else {
1632:                        // this value is new, give it current offset 
1633:                        curP.valueOffset = curOffset;
1634:                        curOffset += curP.getValueOffsetDelta();
1635:                    }
1636:                }
1637:
1638:                return curOffset;
1639:            }
1640:
1641:            /**
1642:             * Romizes images
1643:             *
1644:             * @exception IOException if there was IO error during romization
1645:             */
1646:            private void romizeImages() throws IOException {
1647:
1648:                int maxOffset = -1;
1649:                for (int i = 0; i < imageProps.size(); ++i) {
1650:                    ImageSkinProperty p = (ImageSkinProperty) imageProps
1651:                            .elementAt(i);
1652:                    if (!(p.isRomized) || !p.hasValue) {
1653:                        continue;
1654:                    }
1655:
1656:                    // this property has the same value as some other 
1657:                    // property seen before, so skip it
1658:                    if (p.valueOffset <= maxOffset) {
1659:                        continue;
1660:                    }
1661:
1662:                    romizeImage(p.value, p.valueOffset);
1663:                    maxOffset = p.valueOffset;
1664:                }
1665:
1666:                for (int i = 0; i < compImageProps.size(); ++i) {
1667:                    CompositeImageSkinProperty p = (CompositeImageSkinProperty) compImageProps
1668:                            .elementAt(i);
1669:                    if (!(p.isRomized) || !p.hasValue) {
1670:                        continue;
1671:                    }
1672:
1673:                    // this property has the same value as some other 
1674:                    // property seen before, so skip it
1675:                    if (p.valueOffset <= maxOffset) {
1676:                        continue;
1677:                    }
1678:
1679:                    for (int j = 0; j < p.value.length; ++j) {
1680:                        romizeImage(p.value[j], p.valueOffset + j);
1681:                    }
1682:                    maxOffset = p.valueOffset;
1683:                }
1684:
1685:            }
1686:
1687:            /**
1688:             * Romizes single image
1689:             *
1690:             * @param imageName of the image to romize without extension
1691:             * @param imageIndex romized image index
1692:             * @exception IOException if there was IO error during romization
1693:             */
1694:            private void romizeImage(String imageName, int imageIndex)
1695:                    throws IOException {
1696:
1697:                // we romize png images only
1698:                String imageFileName = imageName + ".png";
1699:                imageFileName = romizationJob.skinImagesDirName
1700:                        + File.separator + imageFileName;
1701:
1702:                System.out.println("     " + imageFileName);
1703:
1704:                // load image
1705:                BufferedImage image = javax.imageio.ImageIO.read(new File(
1706:                        imageFileName));
1707:
1708:                // and romize it
1709:                RomizedImage ri = romizedImageFactory.createFromBufferedImage(
1710:                        image, imageIndex);
1711:
1712:                romizedImages.set(imageIndex, ri);
1713:            }
1714:
1715:            /**
1716:             *  Writes copyrigth banner
1717:             */
1718:            private void writeCopyright() {
1719:                pl("/**");
1720:                pl(" * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.");
1721:                pl(" * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER");
1722:                pl(" * ");
1723:                pl(" * This program is free software; you can redistribute it and/or");
1724:                pl(" * modify it under the terms of the GNU General Public License version");
1725:                pl(" * 2 only, as published by the Free Software Foundation.");
1726:                pl(" * ");
1727:                pl(" * This program is distributed in the hope that it will be useful, but");
1728:                pl(" * WITHOUT ANY WARRANTY; without even the implied warranty of");
1729:                pl(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU");
1730:                pl(" * General Public License version 2 for more details (a copy is");
1731:                pl(" * included at /legal/license.txt).");
1732:                pl(" * ");
1733:                pl(" * You should have received a copy of the GNU General Public License");
1734:                pl(" * version 2 along with this work; if not, write to the Free Software");
1735:                pl(" * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA");
1736:                pl(" * 02110-1301 USA");
1737:                pl(" * ");
1738:                pl(" * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa");
1739:                pl(" * Clara, CA 95054 or visit www.sun.com if you need additional");
1740:                pl(" * information or have any questions.");
1741:                pl(" * ");
1742:                pl(" * NOTE: DO NOT EDIT. THIS FILE IS GENERATED. If you want to ");
1743:                pl(" * edit it, you need to modify the corresponding XML files.");
1744:                pl(" */");
1745:            }
1746:
1747:            /**
1748:             * Writes RomizedSkin class file header
1749:             */
1750:            private void writeBinHeader() throws IOException {
1751:
1752:                // write magic sequence
1753:                int magicLength = SkinResourcesConstants.CHAM_BIN_MAGIC.length;
1754:                for (int i = 0; i < magicLength; ++i) {
1755:                    byte b = (byte) (SkinResourcesConstants.CHAM_BIN_MAGIC[i] & 0xFF);
1756:                    outputStream.writeByte(b);
1757:                }
1758:
1759:                // write version info as an array 
1760:                outputStream.writeInt(1); // array size
1761:                outputStream
1762:                        .writeInt(SkinResourcesConstants.CHAM_BIN_FORMAT_VERSION);
1763:            }
1764:
1765:            /**
1766:             *  Writes romized images C file header
1767:             */
1768:            private void writeCHeader() {
1769:                writeCopyright();
1770:
1771:                pl("");
1772:                pl("#include <string.h>");
1773:                pl("#include <kni.h>");
1774:                pl("#include <midpError.h>");
1775:                pl("#include <midpMalloc.h>");
1776:                pl("#include <midpServices.h>\n");
1777:            }
1778:
1779:            /**
1780:             * Writes romized properties data
1781:             * @exception Exception if there was an error during output
1782:             */
1783:            private void writeRomizedProperties() throws Exception {
1784:
1785:                outputStream.writeInt(allProps.size());
1786:                for (int i = 0; i < allProps.size(); ++i) {
1787:                    SkinPropertyBase p = (SkinPropertyBase) allProps
1788:                            .elementAt(i);
1789:                    if (p instanceof  IntSkinProperty) {
1790:                        IntSkinProperty intP = (IntSkinProperty) p;
1791:                        // for integer property the array holds actual property's 
1792:                        // value, not an offset into values array
1793:                        p.outputValue(outputStream);
1794:                    } else {
1795:                        // for all other properties the array holds an offset into
1796:                        // values array, in which actual values are stored
1797:                        outputStream.writeInt(p.valueOffset);
1798:                    }
1799:                }
1800:
1801:                writePropertiesValues(intSeqProps);
1802:                writePropertiesValues(stringProps);
1803:                writePropertiesValues(fontProps);
1804:
1805:                Vector v = new Vector(imageProps);
1806:                v.addAll(compImageProps);
1807:                writePropertiesValues(v);
1808:
1809:                writeRomizedImagesIndexes();
1810:            }
1811:
1812:            /**
1813:             * Writes properties values array entries
1814:             *
1815:             * @param props properties to write entries for 
1816:             */
1817:            private void writePropertiesValues(Vector props)
1818:                    throws java.io.IOException {
1819:
1820:                int maxOffset = -1;
1821:                int totalValues = 0;
1822:                for (int i = 0; i < props.size(); ++i) {
1823:                    SkinPropertyBase p = (SkinPropertyBase) props.elementAt(i);
1824:
1825:                    // this property has the same value as some other 
1826:                    // property printed before, so skip it
1827:                    if (p.valueOffset <= maxOffset) {
1828:                        continue;
1829:                    }
1830:
1831:                    totalValues += p.getValueOffsetDelta();
1832:                    maxOffset = p.valueOffset;
1833:                }
1834:                outputStream.writeInt(totalValues);
1835:
1836:                maxOffset = -1;
1837:                for (int i = 0; i < props.size(); ++i) {
1838:                    SkinPropertyBase p = (SkinPropertyBase) props.elementAt(i);
1839:
1840:                    // this property has the same value as some other 
1841:                    // property outputed before, so skip it
1842:                    if (p.valueOffset <= maxOffset) {
1843:                        continue;
1844:                    }
1845:
1846:                    p.outputValue(outputStream);
1847:                    maxOffset = p.valueOffset;
1848:                }
1849:            }
1850:
1851:            /**
1852:             * Writes indexes for romized images. 
1853:             */
1854:            private void writeRomizedImagesIndexes() throws java.io.IOException {
1855:
1856:                outputStream.writeInt(romizedImages.size());
1857:                for (int i = 0; i < romizedImages.size(); ++i) {
1858:                    Object o = romizedImages.elementAt(i);
1859:                    // image with index = i isn't romized
1860:                    if (o == null) {
1861:                        outputStream.writeInt(-1);
1862:                    } else {
1863:                        RomizedImage ri = (RomizedImage) o;
1864:                        outputStream.writeInt(ri.imageIndex);
1865:                    }
1866:                }
1867:            }
1868:
1869:            /**
1870:             *  Writes romized images data
1871:             */
1872:            private void writeRomizedImagesData() {
1873:                int totalRomizedImages = 0;
1874:                for (int i = 0; i < romizedImages.size(); ++i) {
1875:                    if (romizedImages.elementAt(i) != null) {
1876:                        ++totalRomizedImages;
1877:                    }
1878:                }
1879:
1880:                pl("");
1881:                pl("static const int NUM_ROM_IMAGES = " + totalRomizedImages
1882:                        + ";");
1883:
1884:                if (totalRomizedImages != 0) {
1885:                    // output a structure declaration used for storing 
1886:                    // romized images data in it
1887:                    pl("");
1888:                    pl("struct romized_images_data {");
1889:                    for (int i = 0; i < romizedImages.size(); ++i) {
1890:                        Object o = romizedImages.elementAt(i);
1891:                        if (o != null) {
1892:                            RomizedImage ri = (RomizedImage) o;
1893:
1894:                            // this field ensures proper alignment of 
1895:                            // subsequent data array
1896:                            pl("    " + "const int align_" + ri.imageIndex
1897:                                    + ";");
1898:
1899:                            String dataArrayName = "romized_image"
1900:                                    + ri.imageIndex;
1901:                            int dataArrayLength = ri.imageData.length;
1902:                            pl("    " + "const unsigned char " + dataArrayName
1903:                                    + "[" + dataArrayLength + "];");
1904:                        }
1905:                    }
1906:                    pl("};");
1907:
1908:                    pl("");
1909:                    pl("static const struct romized_images_data "
1910:                            + "romized_images_data = {");
1911:                    for (int i = 0; i < romizedImages.size(); ++i) {
1912:                        Object o = romizedImages.elementAt(i);
1913:                        if (o != null) {
1914:                            // alignemnt field
1915:                            pl("    " + "0,");
1916:
1917:                            RomizedImage ri = (RomizedImage) o;
1918:                            String dataArrayName = "romized_image"
1919:                                    + ri.imageIndex;
1920:
1921:                            // romized image data field
1922:                            pl("    " + "/* " + dataArrayName + " */");
1923:                            pl("    " + "{");
1924:                            ri.printDataArray(writer, "        ", 11);
1925:                            pl(" },");
1926:                        }
1927:                    }
1928:                    pl("};");
1929:                }
1930:
1931:                pl("");
1932:                pl("static const unsigned char* image_cache[] = {");
1933:                // if there are no romized images, print dummy value
1934:                // to make array non empty and keep compilers happy
1935:                if (totalRomizedImages == 0) {
1936:                    pl("    NULL");
1937:                } else {
1938:                    for (int i = 0; i < romizedImages.size(); ++i) {
1939:                        Object o = romizedImages.elementAt(i);
1940:                        if (o != null) {
1941:                            RomizedImage ri = (RomizedImage) o;
1942:                            String dataArrayName = "romized_images_data.romized_image"
1943:                                    + ri.imageIndex;
1944:                            pl("    " + dataArrayName + ",");
1945:                        }
1946:                    }
1947:                }
1948:                pl("};");
1949:
1950:                pl("");
1951:                pl("static const int image_size[] = {");
1952:                // if there are no romized images, print dummy value
1953:                // to make array non empty and keep compilers happy
1954:                if (totalRomizedImages == 0) {
1955:                    pl("    0");
1956:                } else {
1957:                    for (int i = 0; i < romizedImages.size(); ++i) {
1958:                        Object o = romizedImages.elementAt(i);
1959:                        if (o != null) {
1960:                            RomizedImage ri = (RomizedImage) o;
1961:                            String dataArrayName = "romized_images_data.romized_image"
1962:                                    + ri.imageIndex;
1963:                            pl("    sizeof(" + dataArrayName + "),");
1964:                        }
1965:                    }
1966:                }
1967:                pl("};");
1968:            }
1969:
1970:            /**
1971:             * Writes get method for obtaining romized image data
1972:             */
1973:            void writeGetMethod() {
1974:                pl("");
1975:                pl("/**");
1976:                pl(" * Loads a native image from rom, if present.");
1977:                pl(" *");
1978:                pl(" * @param imageId    The image id");
1979:                pl(" * @param **bufPtr   Pointer where a buffer will be "
1980:                        + "allocated and data stored");
1981:                pl(" * @return           -1 if failed, else length of buffer");
1982:                pl(" */");
1983:                pl("int lfj_load_image_from_rom(int imageId, "
1984:                        + "unsigned char** bufPtr) {\n");
1985:                pl("    int len = -1;");
1986:                pl("    if ((imageId < 0) || (imageId > NUM_ROM_IMAGES)) {");
1987:                pl("        REPORT_WARN1(LC_LOWUI,");
1988:                pl("            \"Warning: could not load romized"
1989:                        + "image for index %d; \", imageId); ");
1990:                pl("        return len;");
1991:                pl("    }\n");
1992:                pl("    *bufPtr = (unsigned char*)image_cache[imageId];");
1993:                pl("    len = image_size[imageId];");
1994:                pl("    return len;");
1995:                pl("}");
1996:            }
1997:
1998:            /**
1999:             * Creates a directory structure.
2000:             *
2001:             * @param fullFileName Full path to the file to be created. If directory
2002:             * in which file is to be created doesn't exists, it will be created
2003:             * @exception IOException is thrown if directory couldn't be created 
2004:             */
2005:            private void makeDirectoryTree(String fullFileName)
2006:                    throws IOException {
2007:
2008:                if (debug == true) {
2009:                    System.out.println("mkdir: " + fullFileName);
2010:                }
2011:                int index = fullFileName.lastIndexOf(File.separatorChar);
2012:                if (index == -1) {
2013:                    // To be compatible with MKS-hosted build on win32, which
2014:                    // does not translate / to \.
2015:                    index = fullFileName.lastIndexOf('/');
2016:                }
2017:                File outputDirectory = new File(fullFileName
2018:                        .substring(0, index));
2019:
2020:                if (!(outputDirectory).exists()) {
2021:                    if (!(outputDirectory).mkdirs()) {
2022:                        throw new IOException(
2023:                                "failed to create output directory");
2024:                    }
2025:                }
2026:
2027:            }
2028:
2029:            /**
2030:             * Short-hand for printint a line into the output file
2031:             *
2032:             * @param s line to print
2033:             */
2034:            void pl(String s) {
2035:                writer.println(s);
2036:            }
2037:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.