~ubuntu-branches/ubuntu/jaunty/electric/jaunty

« back to all changes in this revision

Viewing changes to com/sun/electric/technology/xml/XmlParam.java

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2009-01-08 02:05:08 UTC
  • mfrom: (1.1.2 upstream) (3.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090108020508-0h3li7zt9mu5gf0i
Tags: 8.08-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- tab-width: 4 -*-
 
2
 *
 
3
 * Electric(tm) VLSI Design System
 
4
 *
 
5
 * File: XmlParam.java
 
6
 *
 
7
 * Copyright (c) 2003 Sun Microsystems and Static Free Software
 
8
 *
 
9
 * Electric(tm) is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; either version 3 of the License, or
 
12
 * (at your option) any later version.
 
13
 *
 
14
 * Electric(tm) is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with Electric(tm); see the file COPYING.  If not, write to
 
21
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 
22
 * Boston, Mass 02111-1307, USA.
 
23
 */
 
24
package com.sun.electric.technology.xml;
 
25
 
 
26
import com.sun.electric.database.geometry.EGraphics;
 
27
import com.sun.electric.database.geometry.EPoint;
 
28
import com.sun.electric.database.geometry.ERectangle;
 
29
import com.sun.electric.database.geometry.Poly.Type;
 
30
import com.sun.electric.technology.DRCTemplate;
 
31
import com.sun.electric.technology.EdgeH;
 
32
import com.sun.electric.technology.EdgeV;
 
33
import com.sun.electric.technology.Technology.TechPoint;
 
34
import com.sun.electric.tool.Job;
 
35
 
 
36
import java.awt.Color;
 
37
import java.io.IOException;
 
38
import java.io.InputStream;
 
39
import java.io.PrintWriter;
 
40
import java.io.Serializable;
 
41
import java.io.StringReader;
 
42
import java.io.StringWriter;
 
43
import java.net.URL;
 
44
import java.net.URLConnection;
 
45
import java.util.ArrayList;
 
46
import java.util.Arrays;
 
47
import java.util.Calendar;
 
48
import java.util.Collections;
 
49
import java.util.Date;
 
50
import java.util.HashMap;
 
51
import java.util.LinkedHashMap;
 
52
import java.util.List;
 
53
import java.util.Map;
 
54
 
 
55
import javax.xml.XMLConstants;
 
56
import javax.xml.parsers.SAXParser;
 
57
import javax.xml.parsers.SAXParserFactory;
 
58
 
 
59
import javax.xml.validation.Schema;
 
60
import javax.xml.validation.SchemaFactory;
 
61
import org.xml.sax.Attributes;
 
62
import org.xml.sax.InputSource;
 
63
import org.xml.sax.Locator;
 
64
import org.xml.sax.SAXException;
 
65
import org.xml.sax.SAXParseException;
 
66
import org.xml.sax.helpers.DefaultHandler;
 
67
 
 
68
/**
 
69
 *
 
70
 */
 
71
public class XmlParam {
 
72
 
 
73
    public static class Technology implements Serializable {
 
74
        public String techName;
 
75
        public String className;
 
76
        public String shortTechName;
 
77
        public String description;
 
78
        public int minNumMetals;
 
79
        public int maxNumMetals;
 
80
        public int defaultNumMetals;
 
81
        public double scaleValue;
 
82
        public boolean scaleRelevant;
 
83
        public String defaultFoundry;
 
84
        public double minResistance;
 
85
        public double minCapacitance;
 
86
        private final LinkedHashMap<String,Layer> layers = new LinkedHashMap<String,Layer>();
 
87
        public final List<ArcProto> arcs = new ArrayList<ArcProto>();
 
88
        public final List<PrimitiveNode> nodes = new ArrayList<PrimitiveNode>();
 
89
        public final List<SpiceHeader> spiceHeaders = new ArrayList<SpiceHeader>();
 
90
        public final List<DisplayStyle> displayStyles = new ArrayList<DisplayStyle>();
 
91
        public MenuPalette menuPalette;
 
92
        public final LinkedHashMap<String,RuleSet> ruleSets = new LinkedHashMap<String,RuleSet>();
 
93
        public final List<Foundry> foundries = new ArrayList<Foundry>();
 
94
 
 
95
        public Layer newLayer(String name) {
 
96
            if (name == null)
 
97
                throw new NullPointerException();
 
98
            if (layers.containsKey(name))
 
99
                throw new IllegalArgumentException("Duplicate Layer " + name);
 
100
            Layer layer = new Layer(name);
 
101
            layers.put(name, layer);
 
102
            return layer;
 
103
        }
 
104
        
 
105
        public RuleSet newRuleSet(String name) {
 
106
            if (name == null)
 
107
                throw new NullPointerException();
 
108
            if (ruleSets.containsKey(name))
 
109
                throw new IllegalArgumentException("Duplicate RuleSet " + name);
 
110
            RuleSet ruleSet = new RuleSet(name);
 
111
            ruleSets.put(name, ruleSet);
 
112
            return ruleSet;
 
113
        }
 
114
        
 
115
        public Layer findLayer(String name) {
 
116
            return layers.get(name);
 
117
        }
 
118
 
 
119
        public ArcProto findArc(String name) {
 
120
            for (ArcProto arc: arcs) {
 
121
                if (arc.name.equals(name))
 
122
                    return arc;
 
123
            }
 
124
            return null;
 
125
        }
 
126
 
 
127
        public PrimitiveNode findNode(String name) {
 
128
            for (PrimitiveNode node: nodes) {
 
129
                if (node.name.equals(name))
 
130
                    return node;
 
131
            }
 
132
            return null;
 
133
        }
 
134
 
 
135
        public void writeXml(String fileName) {
 
136
            try {
 
137
                PrintWriter out = new PrintWriter(fileName);
 
138
                Writer writer = new Writer(out);
 
139
                writer.writeTechnology(this);
 
140
                out.close();
 
141
                System.out.println("Wrote " + fileName);
 
142
                System.out.println(" (Add this file to the 'Added Technologies' Project Settings to install it in Electric)");
 
143
            } catch (IOException e) {
 
144
                System.out.println("Error creating " + fileName);
 
145
            }
 
146
        }
 
147
    }
 
148
 
 
149
    public static class Layer implements Serializable {
 
150
        public final String name;
 
151
        public com.sun.electric.technology.Layer.Function function;
 
152
        public int extraFunction;
 
153
        public String cif;
 
154
        public String skill;
 
155
        public double resistance;
 
156
        public double capacitance;
 
157
        public double edgeCapacitance;
 
158
        public PureLayerNode pureLayerNode;
 
159
        
 
160
        private Layer(String name) {
 
161
            this.name = name;
 
162
        }
 
163
    }
 
164
 
 
165
    public static class PureLayerNode implements Serializable {
 
166
        public String name;
 
167
        public String oldName;
 
168
        public Type style;
 
169
        public String port;
 
170
        public final List<String> portArcs = new ArrayList<String>();
 
171
    }
 
172
 
 
173
    public static class ArcProto implements Serializable {
 
174
        public String name;
 
175
        public String oldName;
 
176
        public com.sun.electric.technology.ArcProto.Function function;
 
177
        public boolean wipable;
 
178
        public boolean curvable;
 
179
        public boolean special;
 
180
        public boolean notUsed;
 
181
        public boolean skipSizeInPalette;
 
182
 
 
183
        public boolean extended;
 
184
        public boolean fixedAngle;
 
185
        public int angleIncrement;
 
186
        public double antennaRatio;
 
187
        public double elibWidthOffset;
 
188
        public final List<ArcLayer> arcLayers = new ArrayList<ArcLayer>();
 
189
        public ArcPin arcPin;
 
190
    }
 
191
 
 
192
    public static class ArcPin implements Serializable {
 
193
        public String name;
 
194
        public String portName;
 
195
        public double elibSize;
 
196
        public final List<String> portArcs = new ArrayList<String>();
 
197
    }
 
198
 
 
199
    public static class ArcLayer implements Serializable {
 
200
        public String layer;
 
201
        public final Distance extend = new Distance();
 
202
        public Type style;
 
203
    }
 
204
 
 
205
    public static class PrimitiveNode implements Serializable {
 
206
        public String name;
 
207
        public String oldName;
 
208
        public boolean shrinkArcs;
 
209
        public boolean square;
 
210
        public boolean canBeZeroSize;
 
211
        public boolean wipes;
 
212
        public boolean lockable;
 
213
        public boolean edgeSelect;
 
214
        public boolean skipSizeInPalette;
 
215
        public boolean notUsed;
 
216
        public boolean lowVt;
 
217
        public boolean highVt;
 
218
        public boolean nativeBit;
 
219
        public boolean od18;
 
220
        public boolean od25;
 
221
        public boolean od33;
 
222
 
 
223
        public com.sun.electric.technology.PrimitiveNode.Function function;
 
224
        public EPoint diskOffset;
 
225
        public final Distance defaultWidth = new Distance();
 
226
        public final Distance defaultHeight = new Distance();
 
227
        public ERectangle nodeBase;
 
228
        public final List<NodeLayer> nodeLayers = new ArrayList<NodeLayer>();
 
229
        public final List<PrimitivePort> ports = new ArrayList<PrimitivePort>();
 
230
        public int specialType;
 
231
        public double[] specialValues;
 
232
        public NodeSizeRule nodeSizeRule;
 
233
        public String spiceTemplate;
 
234
    }
 
235
 
 
236
    public static class NodeLayer implements Serializable {
 
237
        public String layer;
 
238
        public Type style;
 
239
        public int portNum;
 
240
        public boolean inLayers;
 
241
        public boolean inElectricalLayers;
 
242
        public int representation;
 
243
        public final Distance lx = new Distance();
 
244
        public final Distance hx = new Distance();
 
245
        public final Distance ly = new Distance();
 
246
        public final Distance hy = new Distance();
 
247
        public final List<TechPoint> techPoints = new ArrayList<TechPoint>();
 
248
        public double sizex, sizey, sep1d, sep2d;
 
249
        public String sizeRule, sepRule, sepRule2D;
 
250
        public double lWidth, rWidth, tExtent, bExtent;
 
251
    }
 
252
 
 
253
    public static class NodeSizeRule implements Serializable {
 
254
        public double width;
 
255
        public double height;
 
256
        public String rule;
 
257
    }
 
258
 
 
259
    public static class PrimitivePort implements Serializable {
 
260
        public String name;
 
261
        public int portAngle;
 
262
        public int portRange;
 
263
        public int portTopology;
 
264
        public final Distance lx = new Distance();
 
265
        public final Distance hx = new Distance();
 
266
        public final Distance ly = new Distance();
 
267
        public final Distance hy = new Distance();
 
268
        public final List<String> portArcs = new ArrayList<String>();
 
269
    }
 
270
 
 
271
    public static class SpiceHeader implements Serializable {
 
272
        public int level;
 
273
        public final List<String> spiceLines = new ArrayList<String>();
 
274
    }
 
275
 
 
276
    public static class DisplayStyle implements Serializable {
 
277
        public String name;
 
278
        public final List<Color> transparentLayers = new ArrayList<Color>();
 
279
        private final LinkedHashMap<Layer,LayerDisplayStyle> layerStylesInternal = new LinkedHashMap<Layer,LayerDisplayStyle>();
 
280
        public final Map<Layer,LayerDisplayStyle> layerStyles = Collections.unmodifiableMap(layerStylesInternal);
 
281
        
 
282
        public LayerDisplayStyle newLayer(Layer layer) {
 
283
            LayerDisplayStyle lds = new LayerDisplayStyle(layer);
 
284
            LayerDisplayStyle old = layerStylesInternal.put(layer, lds);
 
285
            assert old == null;
 
286
            return lds;
 
287
        }
 
288
    }
 
289
    
 
290
    public static class LayerDisplayStyle implements Serializable {
 
291
        public final Layer layer;
 
292
        public EGraphics desc;
 
293
        public String mode3D;
 
294
        public double factor3D;
 
295
        
 
296
        private LayerDisplayStyle(Layer layer) {
 
297
            this.layer = layer;
 
298
        }
 
299
    }
 
300
    
 
301
    public static class MenuPalette implements Serializable {
 
302
        public int numColumns;
 
303
        public List<List<Object>> menuBoxes = new ArrayList<List<Object>>();
 
304
 
 
305
        public String writeXml() {
 
306
            StringWriter sw = new StringWriter();
 
307
            PrintWriter out = new PrintWriter(sw);
 
308
            OneLineWriter writer = new OneLineWriter(out);
 
309
            writer.writeMenuPaletteXml(this);
 
310
            out.close();
 
311
            return sw.getBuffer().toString();
 
312
        }
 
313
    }
 
314
 
 
315
    public static class MenuNodeInst implements Serializable {
 
316
        public String protoName;
 
317
        public com.sun.electric.technology.PrimitiveNode.Function function;
 
318
        public String text;
 
319
        public double fontSize;
 
320
        public int rotation;
 
321
    }
 
322
 
 
323
    public static class MenuCell implements Serializable {
 
324
        public String cellName;
 
325
//        public String text;
 
326
//        public double fontSize;
 
327
    }
 
328
 
 
329
    public static class Distance implements Serializable {
 
330
        public double k;
 
331
        public double lambdaValue;
 
332
        public final List<DistanceRule> terms = new ArrayList<DistanceRule>();
 
333
 
 
334
        public void assign(Distance d) {
 
335
            k = d.k;
 
336
            lambdaValue = d.lambdaValue;
 
337
            for (DistanceRule term: d.terms)
 
338
                terms.add(term.clone());
 
339
        }
 
340
 
 
341
        public void assign(com.sun.electric.technology.Technology.Distance d) {
 
342
            k = d.k;
 
343
            lambdaValue = d.lambdaValue;
 
344
            for (com.sun.electric.technology.Technology.DistanceRule term: d.terms)
 
345
                terms.add(new DistanceRule(term));
 
346
        }
 
347
 
 
348
        public Distance clone() {
 
349
            Distance d = new Distance();
 
350
            d.assign(this);
 
351
            return d;
 
352
        }
 
353
 
 
354
        public double getLambda(DistanceContext context) {
 
355
            double value = lambdaValue;
 
356
            for (DistanceRule term: terms)
 
357
                value += term.getLambda(context);
 
358
            return value;
 
359
        }
 
360
        private void writeXml(Writer writer, boolean multiLine) {
 
361
            for (DistanceRule term: terms) {
 
362
                term.writeXml(writer);
 
363
                if (multiLine)
 
364
                    writer.l();
 
365
            }
 
366
            if (lambdaValue != 0) {
 
367
                writer.bcpe(XmlKeyword.lambda, lambdaValue);
 
368
                if (multiLine)
 
369
                    writer.l();
 
370
            }
 
371
        }
 
372
        public void addLambda(double value) {
 
373
            lambdaValue += value;
 
374
        }
 
375
        public void addRule(String ruleName, double k) {
 
376
            addRule(ruleName, null, k);
 
377
        }
 
378
        public void addRule(String ruleName, Layer layer, double k) {
 
379
            addRule(ruleName, layer, null, k);
 
380
        }
 
381
        public void addRule(String ruleName, Layer layer, Layer layer2, double k) {
 
382
            terms.add(new DistanceRule(ruleName, layer, layer2, k));
 
383
        }
 
384
        public boolean isEmpty() { return lambdaValue == 0 && terms.isEmpty(); }
 
385
    }
 
386
 
 
387
    public static interface DistanceContext {
 
388
        public double getRule(String ruleName);
 
389
    }
 
390
 
 
391
    public static class DistanceRule implements Serializable, Cloneable {
 
392
        final String ruleName;
 
393
        final Layer layer;
 
394
        final Layer layer2;
 
395
        final double k;
 
396
 
 
397
        public DistanceRule(com.sun.electric.technology.Technology.DistanceRule oldRule) {
 
398
            this(oldRule.ruleName, null, null, oldRule.k);
 
399
        }
 
400
        
 
401
        private DistanceRule(String ruleName, Layer layer, Layer layer2, double k) {
 
402
            this.ruleName = ruleName;
 
403
            this.layer = layer;
 
404
            this.layer2 = layer2;
 
405
            this.k = k;
 
406
        }
 
407
        
 
408
        public DistanceRule clone() {
 
409
            try {
 
410
                return (DistanceRule)super.clone();
 
411
            } catch (CloneNotSupportedException e) {
 
412
                throw new AssertionError();
 
413
            }
 
414
        }
 
415
 
 
416
        private void writeXml(Writer writer) {
 
417
            writer.b(XmlKeyword.rule);
 
418
            writer.a("ruleName", ruleName);
 
419
            if (layer != null) {
 
420
                writer.a("layer", layer.name);
 
421
                if (layer2 != null)
 
422
                    writer.a("layer2", layer2.name);
 
423
            }
 
424
            if (k != 1)
 
425
                writer.a("k", k);
 
426
            writer.e();
 
427
        }
 
428
 
 
429
        private double getLambda(DistanceContext context) {
 
430
            return context.getRule(ruleName)*k;
 
431
        }
 
432
    }
 
433
    
 
434
    public static class RuleSet implements Serializable {
 
435
        public final String name;
 
436
        public final Map<String,Map<Layer,Distance>> layerRules = new LinkedHashMap<String,Map<Layer,Distance>>();
 
437
        
 
438
        private RuleSet(String name) {
 
439
            this.name = name;
 
440
        }
 
441
        
 
442
        public Map<Layer,Distance> newLayerRule(String ruleName) {
 
443
            if (ruleName == null)
 
444
                throw new NullPointerException();
 
445
            if (layerRules.containsKey(ruleName))
 
446
                throw new IllegalArgumentException("Duplicate LayerRule " + ruleName);
 
447
            Map<Layer,Distance> layerRule = new LinkedHashMap<Layer,Distance>();
 
448
            layerRules.put(ruleName, layerRule);
 
449
            return layerRule;
 
450
        }
 
451
    }
 
452
 
 
453
    public static class Foundry implements Serializable {
 
454
        public String name;
 
455
        public final Map<String,String> layerGds = new LinkedHashMap<String,String>();
 
456
        public final List<DRCTemplate> rules = new ArrayList<DRCTemplate>();
 
457
    }
 
458
 
 
459
    private XmlParam() {}
 
460
 
 
461
    private static enum XmlKeyword {
 
462
        technology,
 
463
        shortName(true),
 
464
        description(true),
 
465
        numMetals,
 
466
        scale,
 
467
        defaultFoundry,
 
468
        minResistance,
 
469
        minCapacitance,
 
470
        layer,
 
471
        display3D,
 
472
        cifLayer,
 
473
        skillLayer,
 
474
        parasitics,
 
475
        pureLayerNode,
 
476
 
 
477
        arcProto,
 
478
        oldName(true),
 
479
        wipable,
 
480
        curvable,
 
481
        special,
 
482
        notUsed,
 
483
        skipSizeInPalette,
 
484
 
 
485
        extended(true),
 
486
        fixedAngle(true),
 
487
        angleIncrement(true),
 
488
        antennaRatio(true),
 
489
        elibWidthOffset(true),
 
490
 
 
491
        arcLayer,
 
492
        arcPin,
 
493
 
 
494
        primitiveNode,
 
495
        //oldName(true),
 
496
        shrinkArcs,
 
497
        square,
 
498
        canBeZeroSize,
 
499
        wipes,
 
500
        lockable,
 
501
        edgeSelect,
 
502
//        skipSizeInPalette,
 
503
//        notUsed,
 
504
        lowVt,
 
505
        highVt,
 
506
        nativeBit,
 
507
        od18,
 
508
        od25,
 
509
        od33,
 
510
        diskOffset,
 
511
        defaultWidth,
 
512
        defaultHeight,
 
513
        nodeBase,
 
514
        nodeLayer,
 
515
        box,
 
516
        multicutbox,
 
517
        serpbox,
 
518
        lambdaBox,
 
519
        points,
 
520
        techPoint,
 
521
        primitivePort,
 
522
        portAngle,
 
523
        portTopology(true),
 
524
//        techPoint,
 
525
        portArc(true),
 
526
        polygonal,
 
527
        serpTrans,
 
528
        specialValue(true),
 
529
        minSizeRule,
 
530
        spiceTemplate,
 
531
        spiceHeader,
 
532
        spiceLine,
 
533
        
 
534
        displayStyle,
 
535
        transparentLayer,
 
536
        r(true),
 
537
        g(true),
 
538
        b(true),
 
539
        transparentColor,
 
540
        opaqueColor,
 
541
        patternedOnDisplay(true),
 
542
        patternedOnPrinter(true),
 
543
        pattern(true),
 
544
        outlined(true),
 
545
        opacity(true),
 
546
        foreground(true),
 
547
        
 
548
        menuPalette,
 
549
        menuBox,
 
550
        menuArc(true),
 
551
        menuNode(true),
 
552
        menuCell,
 
553
        menuText(true),
 
554
        menuNodeInst,
 
555
        menuNodeText,
 
556
        lambda(true),
 
557
        rule,
 
558
        
 
559
        ruleSet,
 
560
        layerRule,
 
561
        Foundry,
 
562
        layerGds,
 
563
        LayerRule,
 
564
        LayersRule,
 
565
        NodeLayersRule,
 
566
        NodeRule;
 
567
 
 
568
        private final boolean hasText;
 
569
 
 
570
        private XmlKeyword() {
 
571
            hasText = false;
 
572
        };
 
573
        private XmlKeyword(boolean hasText) {
 
574
            this.hasText = hasText;
 
575
        }
 
576
    };
 
577
 
 
578
    private static final HashMap<String,XmlKeyword> xmlKeywords = new HashMap<String,XmlKeyword>();
 
579
    static {
 
580
        for (XmlKeyword k: XmlKeyword.class.getEnumConstants())
 
581
            xmlKeywords.put(k.name(), k);
 
582
    }
 
583
 
 
584
    private static Schema schema = null;
 
585
 
 
586
    private static synchronized void loadTechnologySchema() throws SAXException {
 
587
        if (schema != null) return;
 
588
        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
 
589
        URL technologySchemaUrl = Technology.class.getResource("xml/TechnologyParam.xsd");
 
590
        if (technologySchemaUrl != null)
 
591
            schema = schemaFactory.newSchema(technologySchemaUrl);
 
592
        else
 
593
        {
 
594
            System.err.println("Schema file TechnologyParam.xsd, working without XML schema");
 
595
            System.out.println("Schema file TechnologyParam.xsd, working without XML schema");
 
596
        }
 
597
    }
 
598
 
 
599
    public static Technology parseTechnology(URL fileURL) {
 
600
//        System.out.println("Memory usage " + Main.getMemoryUsage() + " bytes");
 
601
        SAXParserFactory factory = SAXParserFactory.newInstance();
 
602
        factory.setNamespaceAware(true);
 
603
        try {
 
604
            if (schema == null)
 
605
                loadTechnologySchema();
 
606
            factory.setSchema(schema);
 
607
    //        factory.setValidating(true);
 
608
    //        System.out.println("Memory usage " + Main.getMemoryUsage() + " bytes");
 
609
            // create the parser
 
610
            long startTime = System.currentTimeMillis();
 
611
            SAXParser parser = factory.newSAXParser();
 
612
            URLConnection urlCon = fileURL.openConnection();
 
613
            InputStream inputStream = urlCon.getInputStream();
 
614
 
 
615
            XMLReader handler = new XMLReader();
 
616
            parser.parse(inputStream, handler);
 
617
            if (Job.getDebug())
 
618
            {
 
619
                long stopTime = System.currentTimeMillis();
 
620
                System.out.println("Loading technology " + fileURL + " ... " + (stopTime - startTime) + " msec");
 
621
            }
 
622
            return handler.tech;
 
623
        } catch (SAXParseException e) {
 
624
            String msg = "Error parsing Xml technology:\n" +
 
625
                    e.getMessage() + "\n" +
 
626
                    " Line " + e.getLineNumber() + " column " + e.getColumnNumber() + " of " + fileURL;
 
627
            msg = msg.replaceAll("\"http://electric.sun.com/Technology\":", "");
 
628
            System.out.println(msg);
 
629
            Job.getUserInterface().showErrorMessage(msg, "Error parsing Xml technology");
 
630
        } catch (Exception e) {
 
631
            String msg = "Error loading Xml technology " + fileURL + " :\n"
 
632
                   + e.getMessage() + "\n";
 
633
            System.out.println(msg);
 
634
            Job.getUserInterface().showErrorMessage(msg, "Error loading Xml technology");
 
635
        }
 
636
        return null;
 
637
    }
 
638
 
 
639
    /**
 
640
     * Method to parse a string of XML that describes the component menu in a Technology Editing context.
 
641
     * Normal parsing of XML returns objects in the Xml class, but
 
642
     * this method returns objects in a given Technology-Editor world.
 
643
     * @param xml the XML string
 
644
     * @param nodes the PrimitiveNode objects describing nodes in the technology.
 
645
     * @param arcs the ArcProto objects describing arcs in the technology.
 
646
     * @return the MenuPalette describing the component menu.
 
647
     */
 
648
    public static MenuPalette parseComponentMenuXMLTechEdit(String xml, List<PrimitiveNode> nodes, List<ArcProto> arcs)
 
649
    {
 
650
        SAXParserFactory factory = SAXParserFactory.newInstance();
 
651
        factory.setNamespaceAware(true);
 
652
        try
 
653
        {
 
654
            SAXParser parser = factory.newSAXParser();
 
655
            InputSource is = new InputSource(new StringReader(xml));
 
656
            XMLReader handler = new XMLReader(nodes, arcs);
 
657
            parser.parse(is, handler);
 
658
            return handler.tech.menuPalette;
 
659
        } catch (Exception e)
 
660
        {
 
661
            System.out.println("Error parsing XML component menu data");
 
662
            e.printStackTrace();
 
663
        }
 
664
        return null;
 
665
    }
 
666
 
 
667
    private static class XMLReader extends DefaultHandler {
 
668
        private static boolean DEBUG = false;
 
669
        private Locator locator;
 
670
 
 
671
        private Technology tech = new Technology();
 
672
        private Layer curLayer;
 
673
        private ArcProto curArc;
 
674
        private PrimitiveNode curNode;
 
675
        private NodeLayer curNodeLayer;
 
676
        private PrimitivePort curPort;
 
677
        private int curSpecialValueIndex;
 
678
        private ArrayList<Object> curMenuBox;
 
679
        private MenuNodeInst curMenuNodeInst;
 
680
        private MenuCell curMenuCell;
 
681
        private Distance curDistance;
 
682
        private SpiceHeader curSpiceHeader;
 
683
        
 
684
        private DisplayStyle curDisplayStyle;
 
685
        private int curTransparent = 0;
 
686
        private int curR;
 
687
        private int curG;
 
688
        private int curB;
 
689
        private LayerDisplayStyle curLayerDisplayStyle;
 
690
        private boolean patternedOnDisplay;
 
691
        private boolean patternedOnPrinter;
 
692
        private final int[] pattern = new int[16];
 
693
        private int curPatternIndex;
 
694
        private EGraphics.Outline outline;
 
695
        private double opacity;
 
696
        private boolean foreground;
 
697
        
 
698
        private RuleSet curRuleSet;
 
699
        private Map<Layer,Distance> curLayerRule;
 
700
        private Foundry curFoundry;
 
701
 
 
702
        private boolean acceptCharacters;
 
703
        private StringBuilder charBuffer = new StringBuilder();
 
704
        private Attributes attributes;
 
705
 
 
706
        XMLReader() {
 
707
        }
 
708
 
 
709
        XMLReader(List<PrimitiveNode> nodes, List<ArcProto> arcs)
 
710
        {
 
711
                for(ArcProto xap : arcs)
 
712
                tech.arcs.add(xap);
 
713
                for(PrimitiveNode xnp : nodes)
 
714
                tech.nodes.add(xnp);
 
715
        }
 
716
 
 
717
        private void beginCharacters() {
 
718
            assert !acceptCharacters;
 
719
            acceptCharacters = true;
 
720
            assert charBuffer.length() == 0;
 
721
        }
 
722
        private String endCharacters() {
 
723
            assert acceptCharacters;
 
724
            String s = charBuffer.toString();
 
725
            charBuffer.setLength(0);
 
726
            acceptCharacters = false;
 
727
            return s;
 
728
        }
 
729
 
 
730
 
 
731
        ////////////////////////////////////////////////////////////////////
 
732
        // Default implementation of the EntityResolver interface.
 
733
        ////////////////////////////////////////////////////////////////////
 
734
 
 
735
        /**
 
736
         * Resolve an external entity.
 
737
         *
 
738
         * <p>Always return null, so that the parser will use the system
 
739
         * identifier provided in the XML document.  This method implements
 
740
         * the SAX default behaviour: application writers can override it
 
741
         * in a subclass to do special translations such as catalog lookups
 
742
         * or URI redirection.</p>
 
743
         *
 
744
         * @param publicId The public identifier, or null if none is
 
745
         *                 available.
 
746
         * @param systemId The system identifier provided in the XML
 
747
         *                 document.
 
748
         * @return The new input source, or null to require the
 
749
         *         default behaviour.
 
750
         * @exception java.io.IOException If there is an error setting
 
751
         *            up the new input source.
 
752
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
753
         *            wrapping another exception.
 
754
         * @see org.xml.sax.EntityResolver#resolveEntity
 
755
         */
 
756
        public InputSource resolveEntity(String publicId, String systemId)
 
757
        throws IOException, SAXException {
 
758
            return null;
 
759
        }
 
760
 
 
761
 
 
762
 
 
763
        ////////////////////////////////////////////////////////////////////
 
764
        // Default implementation of DTDHandler interface.
 
765
        ////////////////////////////////////////////////////////////////////
 
766
 
 
767
 
 
768
        /**
 
769
         * Receive notification of a notation declaration.
 
770
         *
 
771
         * <p>By default, do nothing.  Application writers may override this
 
772
         * method in a subclass if they wish to keep track of the notations
 
773
         * declared in a document.</p>
 
774
         *
 
775
         * @param name The notation name.
 
776
         * @param publicId The notation public identifier, or null if not
 
777
         *                 available.
 
778
         * @param systemId The notation system identifier.
 
779
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
780
         *            wrapping another exception.
 
781
         * @see org.xml.sax.DTDHandler#notationDecl
 
782
         */
 
783
        public void notationDecl(String name, String publicId, String systemId)
 
784
        throws SAXException {
 
785
//            int x = 0;
 
786
        }
 
787
 
 
788
 
 
789
        /**
 
790
         * Receive notification of an unparsed entity declaration.
 
791
         *
 
792
         * <p>By default, do nothing.  Application writers may override this
 
793
         * method in a subclass to keep track of the unparsed entities
 
794
         * declared in a document.</p>
 
795
         *
 
796
         * @param name The entity name.
 
797
         * @param publicId The entity public identifier, or null if not
 
798
         *                 available.
 
799
         * @param systemId The entity system identifier.
 
800
         * @param notationName The name of the associated notation.
 
801
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
802
         *            wrapping another exception.
 
803
         * @see org.xml.sax.DTDHandler#unparsedEntityDecl
 
804
         */
 
805
        public void unparsedEntityDecl(String name, String publicId,
 
806
                String systemId, String notationName)
 
807
                throws SAXException {
 
808
//            int x = 0;
 
809
        }
 
810
 
 
811
 
 
812
 
 
813
        ////////////////////////////////////////////////////////////////////
 
814
        // Default implementation of ContentHandler interface.
 
815
        ////////////////////////////////////////////////////////////////////
 
816
 
 
817
 
 
818
        /**
 
819
         * Receive a Locator object for document events.
 
820
         *
 
821
         * <p>By default, do nothing.  Application writers may override this
 
822
         * method in a subclass if they wish to store the locator for use
 
823
         * with other document events.</p>
 
824
         *
 
825
         * @param locator A locator for all SAX document events.
 
826
         * @see org.xml.sax.ContentHandler#setDocumentLocator
 
827
         * @see org.xml.sax.Locator
 
828
         */
 
829
        public void setDocumentLocator(Locator locator) {
 
830
            this.locator = locator;
 
831
        }
 
832
 
 
833
        private void printLocator() {
 
834
            System.out.println("publicId=" + locator.getPublicId() + " systemId=" + locator.getSystemId() +
 
835
                    " line=" + locator.getLineNumber() + " column=" + locator.getColumnNumber());
 
836
        }
 
837
 
 
838
 
 
839
        /**
 
840
         * Receive notification of the beginning of the document.
 
841
         *
 
842
         * <p>By default, do nothing.  Application writers may override this
 
843
         * method in a subclass to take specific actions at the beginning
 
844
         * of a document (such as allocating the root node of a tree or
 
845
         * creating an output file).</p>
 
846
         *
 
847
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
848
         *            wrapping another exception.
 
849
         * @see org.xml.sax.ContentHandler#startDocument
 
850
         */
 
851
        public void startDocument()
 
852
        throws SAXException {
 
853
            if (DEBUG) {
 
854
                System.out.println("startDocument");
 
855
            }
 
856
        }
 
857
 
 
858
 
 
859
        /**
 
860
         * Receive notification of the end of the document.
 
861
         *
 
862
         * <p>By default, do nothing.  Application writers may override this
 
863
         * method in a subclass to take specific actions at the end
 
864
         * of a document (such as finalising a tree or closing an output
 
865
         * file).</p>
 
866
         *
 
867
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
868
         *            wrapping another exception.
 
869
         * @see org.xml.sax.ContentHandler#endDocument
 
870
         */
 
871
        public void endDocument()
 
872
        throws SAXException {
 
873
            if (DEBUG) {
 
874
                System.out.println("endDocument");
 
875
            }
 
876
        }
 
877
 
 
878
 
 
879
        /**
 
880
         * Receive notification of the start of a Namespace mapping.
 
881
         *
 
882
         * <p>By default, do nothing.  Application writers may override this
 
883
         * method in a subclass to take specific actions at the start of
 
884
         * each Namespace prefix scope (such as storing the prefix mapping).</p>
 
885
         *
 
886
         * @param prefix The Namespace prefix being declared.
 
887
         * @param uri The Namespace URI mapped to the prefix.
 
888
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
889
         *            wrapping another exception.
 
890
         * @see org.xml.sax.ContentHandler#startPrefixMapping
 
891
         */
 
892
        public void startPrefixMapping(String prefix, String uri)
 
893
        throws SAXException {
 
894
            if (DEBUG) {
 
895
                System.out.println("startPrefixMapping prefix=" + prefix + " uri=" + uri);
 
896
            }
 
897
        }
 
898
 
 
899
 
 
900
        /**
 
901
         * Receive notification of the end of a Namespace mapping.
 
902
         *
 
903
         * <p>By default, do nothing.  Application writers may override this
 
904
         * method in a subclass to take specific actions at the end of
 
905
         * each prefix mapping.</p>
 
906
         *
 
907
         * @param prefix The Namespace prefix being declared.
 
908
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
909
         *            wrapping another exception.
 
910
         * @see org.xml.sax.ContentHandler#endPrefixMapping
 
911
         */
 
912
        public void endPrefixMapping(String prefix)
 
913
        throws SAXException {
 
914
            if (DEBUG) {
 
915
                System.out.println("endPrefixMapping prefix=" + prefix);
 
916
            }
 
917
        }
 
918
 
 
919
 
 
920
        /**
 
921
         * Receive notification of the start of an element.
 
922
         *
 
923
         * <p>By default, do nothing.  Application writers may override this
 
924
         * method in a subclass to take specific actions at the start of
 
925
         * each element (such as allocating a new tree node or writing
 
926
         * output to a file).</p>
 
927
         *
 
928
         * @param uri The Namespace URI, or the empty string if the
 
929
         *        element has no Namespace URI or if Namespace
 
930
         *        processing is not being performed.
 
931
         * @param localName The local name (without prefix), or the
 
932
         *        empty string if Namespace processing is not being
 
933
         *        performed.
 
934
         * @param qName The qualified name (with prefix), or the
 
935
         *        empty string if qualified names are not available.
 
936
         * @param attributes The attributes attached to the element.  If
 
937
         *        there are no attributes, it shall be an empty
 
938
         *        Attributes object.
 
939
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
940
         *            wrapping another exception.
 
941
         * @see org.xml.sax.ContentHandler#startElement
 
942
         */
 
943
        public void startElement(String uri, String localName,
 
944
                String qName, Attributes attributes)
 
945
                throws SAXException {
 
946
            boolean dump = false;
 
947
            XmlKeyword key = xmlKeywords.get(localName);
 
948
//            System.out.print("<" + key.name());
 
949
            this.attributes = attributes;
 
950
            switch (key) {
 
951
                case technology:
 
952
                    tech.techName = a("name");
 
953
                    tech.className = a_("class");
 
954
//                    dump = true;
 
955
                    break;
 
956
                case numMetals:
 
957
                    tech.minNumMetals = Integer.parseInt(a("min"));
 
958
                    tech.maxNumMetals = Integer.parseInt(a("max"));
 
959
                    tech.defaultNumMetals = Integer.parseInt(a("default"));
 
960
                    break;
 
961
                case scale:
 
962
                    tech.scaleValue = Double.parseDouble(a("value"));
 
963
                    tech.scaleRelevant = Boolean.parseBoolean(a("relevant"));
 
964
                    break;
 
965
                case defaultFoundry:
 
966
                    tech.defaultFoundry = a("value");
 
967
                    break;
 
968
                case minResistance:
 
969
                    tech.minResistance = Double.parseDouble(a("value"));
 
970
                    break;
 
971
                case minCapacitance:
 
972
                    tech.minCapacitance = Double.parseDouble(a("value"));
 
973
                    break;
 
974
                case layer:
 
975
                    if (curDisplayStyle != null) {
 
976
                        curLayerDisplayStyle = curDisplayStyle.newLayer(tech.findLayer(a("name")));
 
977
                        curTransparent = 0;
 
978
                        curR = curG = curB = 0;
 
979
                        patternedOnDisplay = false;
 
980
                        patternedOnPrinter = false;
 
981
                        Arrays.fill(pattern, 0);
 
982
                        curPatternIndex = 0;
 
983
//                      EGraphics.Outline outline = null;
 
984
                    } else if (curLayerRule != null) {
 
985
                        curDistance = new Distance();
 
986
                        Distance old = curLayerRule.put(tech.findLayer(a("name")), curDistance);
 
987
                        if (old == null)
 
988
                            throw new IllegalArgumentException("Duplicate layer " + a("name"));
 
989
                    } else {
 
990
                        curLayer = tech.newLayer(a("name"));
 
991
                        curLayer.function = com.sun.electric.technology.Layer.Function.valueOf(a("fun"));
 
992
                        String extraFunStr = a_("extraFun");
 
993
                        if (extraFunStr != null) {
 
994
                            if (extraFunStr.equals("depletion_heavy"))
 
995
                                curLayer.extraFunction = com.sun.electric.technology.Layer.Function.DEPLETION|com.sun.electric.technology.Layer.Function.HEAVY;
 
996
                            else if (extraFunStr.equals("depletion_light"))
 
997
                                curLayer.extraFunction = com.sun.electric.technology.Layer.Function.DEPLETION|com.sun.electric.technology.Layer.Function.LIGHT;
 
998
                            else if (extraFunStr.equals("enhancement_heavy"))
 
999
                                curLayer.extraFunction = com.sun.electric.technology.Layer.Function.ENHANCEMENT|com.sun.electric.technology.Layer.Function.HEAVY;
 
1000
                            else if (extraFunStr.equals("enhancement_light"))
 
1001
                                curLayer.extraFunction = com.sun.electric.technology.Layer.Function.ENHANCEMENT|com.sun.electric.technology.Layer.Function.LIGHT;
 
1002
                            else
 
1003
                                curLayer.extraFunction = com.sun.electric.technology.Layer.Function.parseExtraName(extraFunStr);
 
1004
                        }
 
1005
                    }
 
1006
                    break;
 
1007
                case cifLayer:
 
1008
                    curLayer.cif = a("cif");
 
1009
                    break;
 
1010
                case skillLayer:
 
1011
                    curLayer.skill = a("skill");
 
1012
                    break;
 
1013
                case parasitics:
 
1014
                    curLayer.resistance = Double.parseDouble(a("resistance"));
 
1015
                    curLayer.capacitance = Double.parseDouble(a("capacitance"));
 
1016
                    curLayer.edgeCapacitance = Double.parseDouble(a("edgeCapacitance"));
 
1017
                    break;
 
1018
                case pureLayerNode:
 
1019
                    curLayer.pureLayerNode = new PureLayerNode();
 
1020
                    curLayer.pureLayerNode.name = a("name");
 
1021
                    String styleStr = a_("style");
 
1022
                    curLayer.pureLayerNode.style = styleStr != null ? Type.valueOf(styleStr) : Type.FILLED;
 
1023
                    curLayer.pureLayerNode.port = a("port");
 
1024
                    break;
 
1025
                case arcProto:
 
1026
                    curArc = new ArcProto();
 
1027
                    curArc.name = a("name");
 
1028
                    curArc.function = com.sun.electric.technology.ArcProto.Function.valueOf(a("fun"));
 
1029
                    break;
 
1030
                case wipable:
 
1031
                    curArc.wipable = true;
 
1032
                    break;
 
1033
                case curvable:
 
1034
                    curArc.curvable = true;
 
1035
                    break;
 
1036
                case special:
 
1037
                    curArc.special = true;
 
1038
                    break;
 
1039
                case notUsed:
 
1040
                    if (curArc != null)
 
1041
                        curArc.notUsed = true;
 
1042
                    if (curNode != null)
 
1043
                        curNode.notUsed = true;
 
1044
                    break;
 
1045
                case skipSizeInPalette:
 
1046
                    if (curArc != null)
 
1047
                        curArc.skipSizeInPalette = true;
 
1048
                    if (curNode != null)
 
1049
                        curNode.skipSizeInPalette = true;
 
1050
                    break;
 
1051
                case arcLayer:
 
1052
                    ArcLayer arcLay = new ArcLayer();
 
1053
                    arcLay.layer = a("layer");
 
1054
                    curDistance = arcLay.extend;
 
1055
                    arcLay.style = Type.valueOf(a("style"));
 
1056
                    curArc.arcLayers.add(arcLay);
 
1057
                    break;
 
1058
                case arcPin:
 
1059
                    curArc.arcPin = new ArcPin();
 
1060
                    curArc.arcPin.name = a("name");
 
1061
                    curArc.arcPin.portName = a("port");
 
1062
                    curArc.arcPin.elibSize = Double.valueOf(a("elibSize"));
 
1063
                    break;
 
1064
                case primitiveNode:
 
1065
                    curNode = new PrimitiveNode();
 
1066
                    curNode.name = a("name");
 
1067
                    curNode.function = com.sun.electric.technology.PrimitiveNode.Function.valueOf(a("fun"));
 
1068
                    break;
 
1069
                case shrinkArcs:
 
1070
                    curNode.shrinkArcs = true;
 
1071
                    break;
 
1072
                case square:
 
1073
                    curNode.square = true;
 
1074
                    break;
 
1075
                case canBeZeroSize:
 
1076
                    curNode.canBeZeroSize = true;
 
1077
                    break;
 
1078
                case wipes:
 
1079
                    curNode.wipes = true;
 
1080
                    break;
 
1081
                case lockable:
 
1082
                    curNode.lockable = true;
 
1083
                    break;
 
1084
                case edgeSelect:
 
1085
                    curNode.edgeSelect = true;
 
1086
                    break;
 
1087
                case lowVt:
 
1088
                    curNode.lowVt = true;
 
1089
                    break;
 
1090
                case highVt:
 
1091
                    curNode.highVt = true;
 
1092
                    break;
 
1093
                case nativeBit:
 
1094
                    curNode.nativeBit = true;
 
1095
                    break;
 
1096
                case od18:
 
1097
                    curNode.od18 = true;
 
1098
                    break;
 
1099
                case od25:
 
1100
                    curNode.od25 = true;
 
1101
                    break;
 
1102
                case od33:
 
1103
                    curNode.od33 = true;
 
1104
                    break;
 
1105
                case diskOffset:
 
1106
                    curNode.diskOffset = EPoint.fromLambda(Double.parseDouble(a("x")), Double.parseDouble(a("y")));
 
1107
                    break;
 
1108
                case defaultWidth:
 
1109
                    curDistance = curNode.defaultWidth;
 
1110
                    break;
 
1111
                case defaultHeight:
 
1112
                    curDistance = curNode.defaultHeight;
 
1113
                    break;
 
1114
                case nodeBase:
 
1115
                    double lx = Double.parseDouble(a("lx"));
 
1116
                    double hx = Double.parseDouble(a("hx"));
 
1117
                    double ly = Double.parseDouble(a("ly"));
 
1118
                    double hy = Double.parseDouble(a("hy"));
 
1119
                    curNode.nodeBase = ERectangle.fromLambda(lx, ly, hx - lx, hy - ly);
 
1120
                    break;
 
1121
                case nodeLayer:
 
1122
                    curNodeLayer = new NodeLayer();
 
1123
                    curNodeLayer.layer = a("layer");
 
1124
                    curNodeLayer.style = Type.valueOf(a("style"));
 
1125
                    String portNum = a_("portNum");
 
1126
                    if (portNum != null)
 
1127
                        curNodeLayer.portNum = Integer.parseInt(portNum);
 
1128
                    String electrical = a_("electrical");
 
1129
                    if (electrical != null) {
 
1130
                        if (Boolean.parseBoolean(electrical))
 
1131
                            curNodeLayer.inElectricalLayers = true;
 
1132
                        else
 
1133
                            curNodeLayer.inLayers = true;
 
1134
                    } else {
 
1135
                        curNodeLayer.inElectricalLayers = curNodeLayer.inLayers = true;
 
1136
                    }
 
1137
                    break;
 
1138
                case box:
 
1139
                    if (curNodeLayer != null) {
 
1140
                        curNodeLayer.representation = com.sun.electric.technology.Technology.NodeLayer.BOX;
 
1141
                        curNodeLayer.lx.k = da_("klx", -1);
 
1142
                        curNodeLayer.hx.k = da_("khx", 1);
 
1143
                        curNodeLayer.ly.k = da_("kly", -1);
 
1144
                        curNodeLayer.hy.k = da_("khy", 1);
 
1145
                    }
 
1146
                    if (curPort != null) {
 
1147
                        curPort.lx.k = da_("klx", -1);
 
1148
                        curPort.hx.k = da_("khx", 1);
 
1149
                        curPort.ly.k = da_("kly", -1);
 
1150
                        curPort.hy.k = da_("khy", 1);
 
1151
                    }
 
1152
                    break;
 
1153
                case points:
 
1154
                    curNodeLayer.representation = com.sun.electric.technology.Technology.NodeLayer.POINTS;
 
1155
                    break;
 
1156
                case multicutbox:
 
1157
                    curNodeLayer.representation = com.sun.electric.technology.Technology.NodeLayer.MULTICUTBOX;
 
1158
                    curNodeLayer.lx.k = da_("klx", -1);
 
1159
                    curNodeLayer.hx.k = da_("khx", 1);
 
1160
                    curNodeLayer.ly.k = da_("kly", -1);
 
1161
                    curNodeLayer.hy.k = da_("khy", 1);
 
1162
                    curNodeLayer.sizeRule = a("sizeRule");
 
1163
                    curNodeLayer.sepRule = a("sepRule");
 
1164
                    curNodeLayer.sepRule2D = a_("sepRule2D");
 
1165
                    break;
 
1166
                case serpbox:
 
1167
                    curNodeLayer.representation = com.sun.electric.technology.Technology.NodeLayer.BOX;
 
1168
                    curNodeLayer.lx.k = da_("klx", -1);
 
1169
                    curNodeLayer.hx.k = da_("khx", 1);
 
1170
                    curNodeLayer.ly.k = da_("kly", -1);
 
1171
                    curNodeLayer.hy.k = da_("khy", 1);
 
1172
                    curNodeLayer.lWidth = Double.parseDouble(a("lWidth"));
 
1173
                    curNodeLayer.rWidth = Double.parseDouble(a("rWidth"));
 
1174
                    curNodeLayer.tExtent = Double.parseDouble(a("tExtent"));
 
1175
                    curNodeLayer.bExtent = Double.parseDouble(a("bExtent"));
 
1176
                    break;
 
1177
                case lambdaBox:
 
1178
                    if (curNodeLayer != null) {
 
1179
                        curNodeLayer.lx.addLambda(Double.parseDouble(a("klx")));
 
1180
                        curNodeLayer.hx.addLambda(Double.parseDouble(a("khx")));
 
1181
                        curNodeLayer.ly.addLambda(Double.parseDouble(a("kly")));
 
1182
                        curNodeLayer.hy.addLambda(Double.parseDouble(a("khy")));
 
1183
                    }
 
1184
                    if (curPort != null) {
 
1185
                        curPort.lx.addLambda(Double.parseDouble(a("klx")));
 
1186
                        curPort.hx.addLambda(Double.parseDouble(a("khx")));
 
1187
                        curPort.ly.addLambda(Double.parseDouble(a("kly")));
 
1188
                        curPort.hy.addLambda(Double.parseDouble(a("khy")));
 
1189
                    }
 
1190
                    break;
 
1191
                case techPoint:
 
1192
                    double xm = Double.parseDouble(a("xm"));
 
1193
                    double xa = Double.parseDouble(a("xa"));
 
1194
                    double ym = Double.parseDouble(a("ym"));
 
1195
                    double ya = Double.parseDouble(a("ya"));
 
1196
                    TechPoint p = new TechPoint(new EdgeH(xm, xa), new EdgeV(ym, ya));
 
1197
                    if (curNodeLayer != null)
 
1198
                        curNodeLayer.techPoints.add(p);
 
1199
                    break;
 
1200
                case primitivePort:
 
1201
                    curPort = new PrimitivePort();
 
1202
                    curPort.name = a("name");
 
1203
                    break;
 
1204
                case portAngle:
 
1205
                    curPort.portAngle = Integer.parseInt(a("primary"));
 
1206
                    curPort.portRange = Integer.parseInt(a("range"));
 
1207
                    break;
 
1208
                case polygonal:
 
1209
                    curNode.specialType = com.sun.electric.technology.PrimitiveNode.POLYGONAL;
 
1210
                    break;
 
1211
                case serpTrans:
 
1212
                    curNode.specialType = com.sun.electric.technology.PrimitiveNode.SERPTRANS;
 
1213
                    curNode.specialValues = new double[6];
 
1214
                    curSpecialValueIndex = 0;
 
1215
                    break;
 
1216
                case minSizeRule:
 
1217
                    curNode.nodeSizeRule = new NodeSizeRule();
 
1218
                    curNode.nodeSizeRule.width = Double.parseDouble(a("width"));
 
1219
                    curNode.nodeSizeRule.height = Double.parseDouble(a("height"));
 
1220
                    curNode.nodeSizeRule.rule = a("rule");
 
1221
                    break;
 
1222
                case spiceTemplate:
 
1223
                        curNode.spiceTemplate = a("value");
 
1224
                        break;
 
1225
                case spiceHeader:
 
1226
                    curSpiceHeader = new SpiceHeader();
 
1227
                    curSpiceHeader.level = Integer.parseInt(a("level"));
 
1228
                    tech.spiceHeaders.add(curSpiceHeader);
 
1229
                    break;
 
1230
                case spiceLine:
 
1231
                    curSpiceHeader.spiceLines.add(a("line"));
 
1232
                    break;
 
1233
                    
 
1234
                case displayStyle:
 
1235
                    curDisplayStyle = new DisplayStyle();
 
1236
                    curDisplayStyle.name = a("name");
 
1237
                    tech.displayStyles.add(curDisplayStyle);
 
1238
                    break;
 
1239
                case transparentLayer:
 
1240
                    curTransparent = Integer.parseInt(a("transparent"));
 
1241
                    curR = curG = curB = 0;
 
1242
                    break;
 
1243
                case transparentColor:
 
1244
                    curTransparent = Integer.parseInt(a("transparent"));
 
1245
                    if (curTransparent > 0) {
 
1246
                        Color color = curDisplayStyle.transparentLayers.get(curTransparent - 1);
 
1247
                        curR = color.getRed();
 
1248
                        curG = color.getGreen();
 
1249
                        curB = color.getBlue();
 
1250
                    }
 
1251
                    break;
 
1252
                case opaqueColor:
 
1253
                    curR = Integer.parseInt(a("r"));
 
1254
                    curG = Integer.parseInt(a("g"));
 
1255
                    curB = Integer.parseInt(a("b"));
 
1256
                    break;
 
1257
                case display3D:
 
1258
                    curLayerDisplayStyle.mode3D = a("mode");
 
1259
                    curLayerDisplayStyle.factor3D = Double.parseDouble(a("factor"));
 
1260
                    break;
 
1261
                    
 
1262
                case menuPalette:
 
1263
                    tech.menuPalette = new MenuPalette();
 
1264
                    tech.menuPalette.numColumns = Integer.parseInt(a("numColumns"));
 
1265
                    break;
 
1266
                case menuBox:
 
1267
                    curMenuBox = new ArrayList<Object>();
 
1268
                    tech.menuPalette.menuBoxes.add(curMenuBox);
 
1269
                    break;
 
1270
                case menuCell:
 
1271
                    curMenuCell = new MenuCell();
 
1272
                    curMenuCell.cellName = a("cellName");
 
1273
                    break;
 
1274
                case menuNodeInst:
 
1275
                    curMenuNodeInst = new MenuNodeInst();
 
1276
                    curMenuNodeInst.protoName = a("protoName");
 
1277
                    curMenuNodeInst.function =  com.sun.electric.technology.PrimitiveNode.Function.valueOf(a("function"));
 
1278
                    String rotField = a_("rotation");
 
1279
                    if (rotField != null) curMenuNodeInst.rotation = Integer.parseInt(rotField);
 
1280
                    break;
 
1281
                case menuNodeText:
 
1282
                    curMenuNodeInst.text = a("text");
 
1283
                    curMenuNodeInst.fontSize = Double.parseDouble(a("size"));
 
1284
                    break;
 
1285
                case rule:
 
1286
                    String kStr = a_("k");
 
1287
                    Layer layer = null;
 
1288
                    Layer layer2 = null;
 
1289
                    String layerStr = a_("layer");
 
1290
                    if (layerStr != null) {
 
1291
                        layer = tech.findLayer(layerStr);
 
1292
                        assert layer != null;
 
1293
                    }
 
1294
                    String layerStr2 = layerStr != null ? a_("layer2") : null;
 
1295
                    if (layerStr2 != null) {
 
1296
                        layer2 = tech.findLayer(layerStr2);
 
1297
                        assert layer2 != null;
 
1298
                    }
 
1299
                    curDistance.addRule(a("ruleName"), layer, layer2, kStr != null ? Double.valueOf(kStr) : 1);
 
1300
                    break;
 
1301
                case ruleSet:
 
1302
                    curRuleSet = tech.newRuleSet(a("ruleName"));
 
1303
                    break;
 
1304
                case layerRule:
 
1305
                    curLayerRule = curRuleSet.newLayerRule(a("ruleName"));
 
1306
                    break;
 
1307
                case Foundry:
 
1308
                    curFoundry = new Foundry();
 
1309
                    curFoundry.name = a("name");
 
1310
                    tech.foundries.add(curFoundry);
 
1311
                    break;
 
1312
                case layerGds:
 
1313
                    curFoundry.layerGds.put(a("layer"), a("gds"));
 
1314
                    break;
 
1315
                case LayerRule:
 
1316
                case LayersRule:
 
1317
                case NodeLayersRule:
 
1318
                case NodeRule:
 
1319
                    DRCTemplate.parseXmlElement(curFoundry.rules, key.name(), attributes);
 
1320
                    break;
 
1321
                default:
 
1322
                    assert key.hasText;
 
1323
                    beginCharacters();
 
1324
//                    System.out.print(">");
 
1325
                    return;
 
1326
            }
 
1327
            assert !key.hasText;
 
1328
//            System.out.println(">");
 
1329
            if (dump) {
 
1330
                System.out.println("startElement uri=" + uri + " localName=" + localName + " qName=" + qName);
 
1331
                for (int i = 0; i < attributes.getLength(); i++) {
 
1332
                    System.out.println("\tattribute " + i + " uri=" + attributes.getURI(i) +
 
1333
                            " localName=" + attributes.getLocalName(i) + " QName=" + attributes.getQName(i) +
 
1334
                            " type=" + attributes.getType(i) + " value=<" + attributes.getValue(i) + ">");
 
1335
                }
 
1336
            }
 
1337
        }
 
1338
 
 
1339
        private double da_(String attrName, double defaultValue) {
 
1340
            String s = a_(attrName);
 
1341
            return s != null ? Double.parseDouble(s) : defaultValue;
 
1342
        }
 
1343
 
 
1344
        private String a(String attrName) {
 
1345
            String v = attributes.getValue(attrName);
 
1346
//            System.out.print(" " + attrName + "=\"" + v + "\"");
 
1347
            return v;
 
1348
        }
 
1349
 
 
1350
        private String a_(String attrName) {
 
1351
            String v = attributes.getValue(attrName);
 
1352
            if (v == null) return null;
 
1353
//            System.out.print(" " + attrName + "=\"" + v + "\"");
 
1354
            return v;
 
1355
        }
 
1356
 
 
1357
 
 
1358
        /**
 
1359
         * Receive notification of the end of an element.
 
1360
         *
 
1361
         * <p>By default, do nothing.  Application writers may override this
 
1362
         * method in a subclass to take specific actions at the end of
 
1363
         * each element (such as finalising a tree node or writing
 
1364
         * output to a file).</p>
 
1365
         *
 
1366
         * @param uri The Namespace URI, or the empty string if the
 
1367
         *        element has no Namespace URI or if Namespace
 
1368
         *        processing is not being performed.
 
1369
         * @param localName The local name (without prefix), or the
 
1370
         *        empty string if Namespace processing is not being
 
1371
         *        performed.
 
1372
         * @param qName The qualified name (with prefix), or the
 
1373
         *        empty string if qualified names are not available.
 
1374
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
1375
         *            wrapping another exception.
 
1376
         * @see org.xml.sax.ContentHandler#endElement
 
1377
         */
 
1378
        public void endElement(String uri, String localName, String qName)
 
1379
        throws SAXException {
 
1380
            XmlKeyword key = xmlKeywords.get(localName);
 
1381
            if (key.hasText) {
 
1382
                String text = endCharacters();
 
1383
//                System.out.println(text + "</" + localName + ">");
 
1384
                switch (key) {
 
1385
                    case shortName:
 
1386
                        tech.shortTechName = text;
 
1387
                        break;
 
1388
                    case description:
 
1389
                        tech.description = text;
 
1390
                        break;
 
1391
                    case oldName:
 
1392
                        if (curLayer != null)
 
1393
                            curLayer.pureLayerNode.oldName = text;
 
1394
                        if (curArc != null)
 
1395
                            curArc.oldName = text;
 
1396
                        if (curNode != null)
 
1397
                            curNode.oldName = text;
 
1398
                        break;
 
1399
                    case extended:
 
1400
                        curArc.extended = Boolean.parseBoolean(text);
 
1401
                        break;
 
1402
                    case fixedAngle:
 
1403
                        curArc.fixedAngle = Boolean.parseBoolean(text);
 
1404
                        break;
 
1405
                    case wipable:
 
1406
                        curArc.wipable = Boolean.parseBoolean(text);
 
1407
                        break;
 
1408
                    case angleIncrement:
 
1409
                        curArc.angleIncrement = Integer.parseInt(text);
 
1410
                        break;
 
1411
                    case antennaRatio:
 
1412
                        curArc.antennaRatio = Double.parseDouble(text);
 
1413
                        break;
 
1414
                    case elibWidthOffset:
 
1415
                        curArc.elibWidthOffset = Double.parseDouble(text);
 
1416
                        break;
 
1417
                    case portTopology:
 
1418
                        curPort.portTopology = Integer.parseInt(text);
 
1419
                        break;
 
1420
                    case portArc:
 
1421
                        if (curLayer != null && curLayer.pureLayerNode != null)
 
1422
                            curLayer.pureLayerNode.portArcs.add(text);
 
1423
                        if (curArc != null && curArc.arcPin != null)
 
1424
                            curArc.arcPin.portArcs.add(text);
 
1425
                        if (curPort != null)
 
1426
                            curPort.portArcs.add(text);
 
1427
                        break;
 
1428
                    case specialValue:
 
1429
                        curNode.specialValues[curSpecialValueIndex++] = Double.parseDouble(text);
 
1430
                        break;
 
1431
                        
 
1432
                    case r:
 
1433
                        curR = Integer.parseInt(text);
 
1434
                        break;
 
1435
                    case g:
 
1436
                        curG = Integer.parseInt(text);
 
1437
                        break;
 
1438
                    case b:
 
1439
                        curB = Integer.parseInt(text);
 
1440
                        break;
 
1441
                    case patternedOnDisplay:
 
1442
                        patternedOnDisplay = Boolean.parseBoolean(text);
 
1443
                        break;
 
1444
                    case patternedOnPrinter:
 
1445
                        patternedOnPrinter = Boolean.parseBoolean(text);
 
1446
                        break;
 
1447
                    case pattern:
 
1448
                        int p = 0;
 
1449
                        assert text.length() == 16;
 
1450
                        for (int j = 0; j < text.length(); j++) {
 
1451
                            if (text.charAt(text.length() - j - 1) != ' ')
 
1452
                                p |= (1 << j);
 
1453
                        }
 
1454
                        pattern[curPatternIndex++] = p;
 
1455
                        break;
 
1456
                    case outlined:
 
1457
                        outline = EGraphics.Outline.valueOf(text);
 
1458
                        break;
 
1459
                    case opacity:
 
1460
                        opacity = Double.parseDouble(text);
 
1461
                        break;
 
1462
                    case foreground:
 
1463
                        foreground = Boolean.parseBoolean(text);
 
1464
                        break;
 
1465
                        
 
1466
                    case menuArc:
 
1467
                        curMenuBox.add(tech.findArc(text));
 
1468
                        break;
 
1469
                    case menuNode:
 
1470
                        curMenuBox.add(tech.findNode(text));
 
1471
                        break;
 
1472
                    case menuText:
 
1473
                        curMenuBox.add(text);
 
1474
                        break;
 
1475
                    case lambda:
 
1476
                        curDistance.addLambda(Double.parseDouble(text));
 
1477
                        break;
 
1478
                    default:
 
1479
                        assert false;
 
1480
                }
 
1481
                return;
 
1482
            }
 
1483
//            System.out.println("</" + localName + ">");
 
1484
            switch (key) {
 
1485
                case technology:
 
1486
                    break;
 
1487
                case layer:
 
1488
                    if (curDisplayStyle != null) {
 
1489
                        assert curPatternIndex == pattern.length;
 
1490
                        curLayerDisplayStyle.desc = new EGraphics(patternedOnDisplay, patternedOnPrinter, outline, curTransparent,
 
1491
                            curR, curG, curB, opacity, foreground, pattern.clone());
 
1492
                        curLayerDisplayStyle = null;
 
1493
                    } else if (curLayerRule != null) {
 
1494
                        curDistance = null;
 
1495
                    } else {
 
1496
                        curLayer = null;
 
1497
                    }
 
1498
                    break;
 
1499
                case arcProto:
 
1500
                    tech.arcs.add(curArc);
 
1501
                    curArc = null;
 
1502
                    break;
 
1503
                case primitiveNode:
 
1504
                    tech.nodes.add(curNode);
 
1505
                    curNode = null;
 
1506
                    break;
 
1507
                case nodeLayer:
 
1508
                    curNode.nodeLayers.add(curNodeLayer);
 
1509
                    curNodeLayer = null;
 
1510
                    break;
 
1511
                case primitivePort:
 
1512
                    curNode.ports.add(curPort);
 
1513
                    curPort = null;
 
1514
                    break;
 
1515
                case menuNodeInst:
 
1516
                        curMenuBox.add(curMenuNodeInst);
 
1517
                    curMenuNodeInst = null;
 
1518
                    break;
 
1519
                    
 
1520
                case displayStyle:
 
1521
                    curDisplayStyle = null;
 
1522
                    break;
 
1523
                case transparentLayer:
 
1524
                    while (curTransparent > curDisplayStyle.transparentLayers.size())
 
1525
                        curDisplayStyle.transparentLayers.add(null);
 
1526
                    Color oldColor = curDisplayStyle.transparentLayers.set(curTransparent - 1, new Color(curR, curG, curB));
 
1527
                    assert oldColor == null;
 
1528
                    break;
 
1529
                    
 
1530
                case menuCell:
 
1531
                        curMenuBox.add("LOADCELL " + curMenuCell.cellName);
 
1532
//                      curMenuBox.add(curMenuCell);
 
1533
                    curMenuCell = null;
 
1534
                    break;
 
1535
                    
 
1536
                case ruleSet:
 
1537
                    curRuleSet = null;
 
1538
                    break;
 
1539
                case layerRule:
 
1540
                    curLayerRule = null;
 
1541
                    break;
 
1542
 
 
1543
                case numMetals:
 
1544
                case scale:
 
1545
                case defaultFoundry:
 
1546
                case minResistance:
 
1547
                case minCapacitance:
 
1548
                case cifLayer:
 
1549
                case skillLayer:
 
1550
                case parasitics:
 
1551
                case pureLayerNode:
 
1552
 
 
1553
                case wipable:
 
1554
                case curvable:
 
1555
                case special:
 
1556
                case notUsed:
 
1557
                case skipSizeInPalette:
 
1558
                case arcLayer:
 
1559
                case arcPin:
 
1560
 
 
1561
                case shrinkArcs:
 
1562
                case square:
 
1563
                case canBeZeroSize:
 
1564
                case wipes:
 
1565
                case lockable:
 
1566
                case edgeSelect:
 
1567
                case lowVt:
 
1568
                case highVt:
 
1569
                case nativeBit:
 
1570
                case od18:
 
1571
                case od25:
 
1572
                case od33:
 
1573
                case diskOffset:
 
1574
 
 
1575
                case defaultWidth:
 
1576
                case defaultHeight:
 
1577
                case nodeBase:
 
1578
                case box:
 
1579
                case points:
 
1580
                case multicutbox:
 
1581
                case serpbox:
 
1582
                case lambdaBox:
 
1583
                case techPoint:
 
1584
                case portAngle:
 
1585
                case polygonal:
 
1586
                case serpTrans:
 
1587
                case minSizeRule:
 
1588
                    
 
1589
                case spiceHeader:
 
1590
                case spiceLine:
 
1591
                case spiceTemplate:
 
1592
                    
 
1593
                case transparentColor:
 
1594
                case opaqueColor:
 
1595
                case display3D:
 
1596
                    
 
1597
                case menuPalette:
 
1598
                case menuBox:
 
1599
                case menuNodeText:
 
1600
                case rule:
 
1601
                case Foundry:
 
1602
                case layerGds:
 
1603
                case LayerRule:
 
1604
                case LayersRule:
 
1605
                case NodeLayersRule:
 
1606
                case NodeRule:
 
1607
                    break;
 
1608
                default:
 
1609
                    assert false;
 
1610
            }
 
1611
        }
 
1612
 
 
1613
 
 
1614
        /**
 
1615
         * Receive notification of character data inside an element.
 
1616
         *
 
1617
         * <p>By default, do nothing.  Application writers may override this
 
1618
         * method to take specific actions for each chunk of character data
 
1619
         * (such as adding the data to a node or buffer, or printing it to
 
1620
         * a file).</p>
 
1621
         *
 
1622
         * @param ch The characters.
 
1623
         * @param start The start position in the character array.
 
1624
         * @param length The number of characters to use from the
 
1625
         *               character array.
 
1626
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
1627
         *            wrapping another exception.
 
1628
         * @see org.xml.sax.ContentHandler#characters
 
1629
         */
 
1630
        public void characters(char ch[], int start, int length)
 
1631
        throws SAXException {
 
1632
            if (acceptCharacters) {
 
1633
                charBuffer.append(ch, start, length);
 
1634
            } else {
 
1635
                boolean nonBlank = false;
 
1636
                for (int i = 0; i < length; i++) {
 
1637
                    char c = ch[start + i];
 
1638
                    nonBlank = nonBlank || c != ' ' && c != '\n';
 
1639
                }
 
1640
                if (nonBlank) {
 
1641
                    System.out.print("characters size=" + ch.length + " start=" + start + " length=" + length + " {");
 
1642
                    for (int i = 0; i < length; i++)
 
1643
                        System.out.print(ch[start + i]);
 
1644
                    System.out.println("}");
 
1645
                }
 
1646
            }
 
1647
        }
 
1648
 
 
1649
 
 
1650
        /**
 
1651
         * Receive notification of ignorable whitespace in element content.
 
1652
         *
 
1653
         * <p>By default, do nothing.  Application writers may override this
 
1654
         * method to take specific actions for each chunk of ignorable
 
1655
         * whitespace (such as adding data to a node or buffer, or printing
 
1656
         * it to a file).</p>
 
1657
         *
 
1658
         * @param ch The whitespace characters.
 
1659
         * @param start The start position in the character array.
 
1660
         * @param length The number of characters to use from the
 
1661
         *               character array.
 
1662
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
1663
         *            wrapping another exception.
 
1664
         * @see org.xml.sax.ContentHandler#ignorableWhitespace
 
1665
         */
 
1666
        public void ignorableWhitespace(char ch[], int start, int length)
 
1667
        throws SAXException {
 
1668
//            int x = 0;
 
1669
        }
 
1670
 
 
1671
 
 
1672
        /**
 
1673
         * Receive notification of a processing instruction.
 
1674
         *
 
1675
         * <p>By default, do nothing.  Application writers may override this
 
1676
         * method in a subclass to take specific actions for each
 
1677
         * processing instruction, such as setting status variables or
 
1678
         * invoking other methods.</p>
 
1679
         *
 
1680
         * @param target The processing instruction target.
 
1681
         * @param data The processing instruction data, or null if
 
1682
         *             none is supplied.
 
1683
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
1684
         *            wrapping another exception.
 
1685
         * @see org.xml.sax.ContentHandler#processingInstruction
 
1686
         */
 
1687
        public void processingInstruction(String target, String data)
 
1688
        throws SAXException {
 
1689
//            int x = 0;
 
1690
        }
 
1691
 
 
1692
 
 
1693
        /**
 
1694
         * Receive notification of a skipped entity.
 
1695
         *
 
1696
         * <p>By default, do nothing.  Application writers may override this
 
1697
         * method in a subclass to take specific actions for each
 
1698
         * processing instruction, such as setting status variables or
 
1699
         * invoking other methods.</p>
 
1700
         *
 
1701
         * @param name The name of the skipped entity.
 
1702
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
1703
         *            wrapping another exception.
 
1704
         * @see org.xml.sax.ContentHandler#processingInstruction
 
1705
         */
 
1706
        public void skippedEntity(String name)
 
1707
        throws SAXException {
 
1708
//            int x = 0;
 
1709
        }
 
1710
 
 
1711
 
 
1712
 
 
1713
        ////////////////////////////////////////////////////////////////////
 
1714
        // Default implementation of the ErrorHandler interface.
 
1715
        ////////////////////////////////////////////////////////////////////
 
1716
 
 
1717
 
 
1718
        /**
 
1719
         * Receive notification of a parser warning.
 
1720
         *
 
1721
         * <p>The default implementation does nothing.  Application writers
 
1722
         * may override this method in a subclass to take specific actions
 
1723
         * for each warning, such as inserting the message in a log file or
 
1724
         * printing it to the console.</p>
 
1725
         *
 
1726
         * @param e The warning information encoded as an exception.
 
1727
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
1728
         *            wrapping another exception.
 
1729
         * @see org.xml.sax.ErrorHandler#warning
 
1730
         * @see org.xml.sax.SAXParseException
 
1731
         */
 
1732
        public void warning(SAXParseException e)
 
1733
        throws SAXException {
 
1734
            System.out.println("warning publicId=" + e.getPublicId() + " systemId=" + e.getSystemId() +
 
1735
                    " line=" + e.getLineNumber() + " column=" + e.getColumnNumber() + " message=" + e.getMessage() + " exception=" + e.getException());
 
1736
        }
 
1737
 
 
1738
 
 
1739
        /**
 
1740
         * Receive notification of a recoverable parser error.
 
1741
         *
 
1742
         * <p>The default implementation does nothing.  Application writers
 
1743
         * may override this method in a subclass to take specific actions
 
1744
         * for each error, such as inserting the message in a log file or
 
1745
         * printing it to the console.</p>
 
1746
         *
 
1747
         * @param e The error information encoded as an exception.
 
1748
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
1749
         *            wrapping another exception.
 
1750
         * @see org.xml.sax.ErrorHandler#warning
 
1751
         * @see org.xml.sax.SAXParseException
 
1752
         */
 
1753
        public void error(SAXParseException e)
 
1754
        throws SAXException {
 
1755
//            System.out.println("error publicId=" + e.getPublicId() + " systemId=" + e.getSystemId() +
 
1756
//                    " line=" + e.getLineNumber() + " column=" + e.getColumnNumber() + " message=" + e.getMessage() + " exception=" + e.getException());
 
1757
            throw e;
 
1758
        }
 
1759
 
 
1760
 
 
1761
        /**
 
1762
         * Report a fatal XML parsing error.
 
1763
         *
 
1764
         * <p>The default implementation throws a SAXParseException.
 
1765
         * Application writers may override this method in a subclass if
 
1766
         * they need to take specific actions for each fatal error (such as
 
1767
         * collecting all of the errors into a single report): in any case,
 
1768
         * the application must stop all regular processing when this
 
1769
         * method is invoked, since the document is no longer reliable, and
 
1770
         * the parser may no longer report parsing events.</p>
 
1771
         *
 
1772
         * @param e The error information encoded as an exception.
 
1773
         * @exception org.xml.sax.SAXException Any SAX exception, possibly
 
1774
         *            wrapping another exception.
 
1775
         * @see org.xml.sax.ErrorHandler#fatalError
 
1776
         * @see org.xml.sax.SAXParseException
 
1777
         */
 
1778
        public void fatalError(SAXParseException e)
 
1779
        throws SAXException {
 
1780
//            System.out.println("fatal error publicId=" + e.getPublicId() + " systemId=" + e.getSystemId() +
 
1781
//                    " line=" + e.getLineNumber() + " column=" + e.getColumnNumber() + " message=" + e.getMessage() + " exception=" + e.getException());
 
1782
            throw e;
 
1783
        }
 
1784
 
 
1785
    }
 
1786
 
 
1787
    private static class Writer {
 
1788
        private static final int INDENT_WIDTH = 4;
 
1789
        protected final PrintWriter out;
 
1790
        private int indent;
 
1791
        protected boolean indentEmitted;
 
1792
 
 
1793
        private Writer(PrintWriter out) {
 
1794
            this.out = out;
 
1795
        }
 
1796
 
 
1797
        private void writeTechnology(Technology t) {
 
1798
            Calendar cal = Calendar.getInstance();
 
1799
            cal.setTime(new Date());
 
1800
 
 
1801
            header();
 
1802
 
 
1803
            pl("");
 
1804
            out.println("<!--");
 
1805
            pl(" *");
 
1806
            pl(" * Electric(tm) VLSI Design System");
 
1807
            pl(" *");
 
1808
            pl(" * File: " + t.techName + ".xml");
 
1809
            pl(" * " + t.techName + " technology description");
 
1810
            pl(" * Generated automatically from a library");
 
1811
            pl(" *");
 
1812
            pl(" * Copyright (c) " + cal.get(Calendar.YEAR) + " Sun Microsystems and Static Free Software");
 
1813
            pl(" *");
 
1814
            pl(" * Electric(tm) is free software; you can redistribute it and/or modify");
 
1815
            pl(" * it under the terms of the GNU General Public License as published by");
 
1816
            pl(" * the Free Software Foundation; either version 3 of the License, or");
 
1817
            pl(" * (at your option) any later version.");
 
1818
            pl(" *");
 
1819
            pl(" * Electric(tm) is distributed in the hope that it will be useful,");
 
1820
            pl(" * but WITHOUT ANY WARRANTY; without even the implied warranty of");
 
1821
            pl(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the");
 
1822
            pl(" * GNU General Public License for more details.");
 
1823
            pl(" *");
 
1824
            pl(" * You should have received a copy of the GNU General Public License");
 
1825
            pl(" * along with Electric(tm); see the file COPYING.  If not, write to");
 
1826
            pl(" * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,");
 
1827
            pl(" * Boston, Mass 02111-1307, USA.");
 
1828
            pl(" */");
 
1829
            out.println("-->");
 
1830
            l();
 
1831
 
 
1832
            b(XmlKeyword.technology); a("name", t.techName); a("class", t.className); l();
 
1833
            a("xmlns", "http://electric.sun.com/Technology"); l();
 
1834
            a("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); l();
 
1835
            a("xsi:schemaLocation", "http://electric.sun.com/Technology ../../technology/xml/TechnologyParam.xsd"); cl();
 
1836
            l();
 
1837
 
 
1838
            bcpel(XmlKeyword.shortName, t.shortTechName);
 
1839
            bcpel(XmlKeyword.description, t.description);
 
1840
            b(XmlKeyword.numMetals); a("min", t.minNumMetals); a("max", t.maxNumMetals); a("default", t.defaultNumMetals); el();
 
1841
            b(XmlKeyword.scale); a("value", t.scaleValue); a("relevant", t.scaleRelevant); el();
 
1842
            b(XmlKeyword.defaultFoundry); a("value", t.defaultFoundry); el();
 
1843
            b(XmlKeyword.minResistance); a("value", t.minResistance); el();
 
1844
            b(XmlKeyword.minCapacitance); a("value", t.minCapacitance); el();
 
1845
//        printlnAttribute("  gateLengthSubtraction", gi.gateShrinkage);
 
1846
//        printlnAttribute("  gateInclusion", gi.includeGateInResistance);
 
1847
//        printlnAttribute("  groundNetInclusion", gi.includeGround);
 
1848
            l();
 
1849
 
 
1850
            comment("**************************************** LAYERS ****************************************");
 
1851
            for (Layer li: t.layers.values()) {
 
1852
                writeXml(li);
 
1853
            }
 
1854
 
 
1855
            comment("******************** ARCS ********************");
 
1856
            for (ArcProto ai: t.arcs) {
 
1857
                writeXml(ai);
 
1858
                l();
 
1859
            }
 
1860
 
 
1861
            comment("******************** NODES ********************");
 
1862
            for (PrimitiveNode ni: t.nodes) {
 
1863
                writeXml(ni);
 
1864
                l();
 
1865
            }
 
1866
 
 
1867
            for (SpiceHeader spiceHeader: t.spiceHeaders)
 
1868
                writeSpiceHeaderXml(spiceHeader);
 
1869
            
 
1870
            for (DisplayStyle displayStyle: t.displayStyles)
 
1871
                writeDisplayStyleXml(displayStyle);
 
1872
 
 
1873
            writeMenuPaletteXml(t.menuPalette);
 
1874
 
 
1875
            for (RuleSet ruleSet: t.ruleSets.values())
 
1876
                writeXml(ruleSet);
 
1877
            
 
1878
            for (Foundry foundry: t.foundries)
 
1879
                writeFoundryXml(foundry);
 
1880
 
 
1881
            el(XmlKeyword.technology);
 
1882
        }
 
1883
 
 
1884
        private void writeXml(Layer li) {
 
1885
            String funString = null;
 
1886
            int funExtra = li.extraFunction;
 
1887
            if (funExtra != 0) {
 
1888
                final int deplEnhMask = com.sun.electric.technology.Layer.Function.DEPLETION|com.sun.electric.technology.Layer.Function.ENHANCEMENT;
 
1889
                if ((funExtra&deplEnhMask) != 0) {
 
1890
                    funString = com.sun.electric.technology.Layer.Function.getExtraName(funExtra&(deplEnhMask));
 
1891
                    funExtra &= ~deplEnhMask;
 
1892
                    if (funExtra != 0)
 
1893
                        funString += "_" + com.sun.electric.technology.Layer.Function.getExtraName(funExtra);
 
1894
                } else {
 
1895
                    funString = com.sun.electric.technology.Layer.Function.getExtraName(funExtra);
 
1896
                }
 
1897
            }
 
1898
            b(XmlKeyword.layer); a("name", li.name); a("fun", li.function.name()); a("extraFun", funString); cl();
 
1899
 
 
1900
            if (li.cif != null && li.cif.length() > 0) {
 
1901
                b(XmlKeyword.cifLayer); a("cif", li.cif); el();
 
1902
            }
 
1903
            if (li.skill != null && li.skill.length() > 0) {
 
1904
                b(XmlKeyword.skillLayer); a("skill", li.skill); el();
 
1905
            }
 
1906
 
 
1907
            // write the SPICE information
 
1908
            if (li.resistance != 0 || li.capacitance != 0 || li.edgeCapacitance != 0) {
 
1909
                b(XmlKeyword.parasitics); a("resistance", li.resistance); a("capacitance", li.capacitance); a("edgeCapacitance", li.edgeCapacitance); el();
 
1910
            }
 
1911
            if (li.pureLayerNode != null) {
 
1912
                String nodeName = li.pureLayerNode.name;
 
1913
                Type style = li.pureLayerNode.style;
 
1914
                String styleStr = style == Type.FILLED ? null : style.name();
 
1915
                String portName = li.pureLayerNode.port;
 
1916
                b(XmlKeyword.pureLayerNode); a("name", nodeName); a("style", styleStr); a("port", portName);
 
1917
                if (li.pureLayerNode.oldName == null && li.pureLayerNode.portArcs.isEmpty()) {
 
1918
                    el();
 
1919
                } else {
 
1920
                    cl();
 
1921
                    bcpel(XmlKeyword.oldName, li.pureLayerNode.oldName);
 
1922
                    for (String portArc: li.pureLayerNode.portArcs)
 
1923
                        bcpel(XmlKeyword.portArc, portArc);
 
1924
                    el(XmlKeyword.pureLayerNode);
 
1925
                }
 
1926
            }
 
1927
            el(XmlKeyword.layer);
 
1928
            l();
 
1929
        }
 
1930
 
 
1931
        private void writeXml(ArcProto ai) {
 
1932
            b(XmlKeyword.arcProto); a("name", ai.name); a("fun", ai.function.getConstantName()); cl();
 
1933
            bcpel(XmlKeyword.oldName, ai.oldName);
 
1934
 
 
1935
            if (ai.wipable)
 
1936
                bel(XmlKeyword.wipable);
 
1937
            if (ai.curvable)
 
1938
                bel(XmlKeyword.curvable);
 
1939
            if (ai.special)
 
1940
                bel(XmlKeyword.special);
 
1941
            if (ai.notUsed)
 
1942
                bel(XmlKeyword.notUsed);
 
1943
            if (ai.skipSizeInPalette)
 
1944
                bel(XmlKeyword.skipSizeInPalette);
 
1945
            bcpel(XmlKeyword.extended, ai.extended);
 
1946
            bcpel(XmlKeyword.fixedAngle, ai.fixedAngle);
 
1947
            bcpel(XmlKeyword.angleIncrement, ai.angleIncrement);
 
1948
            if (ai.antennaRatio != 0)
 
1949
                bcpel(XmlKeyword.antennaRatio, ai.antennaRatio);
 
1950
            if (ai.elibWidthOffset != 0)
 
1951
                bcpel(XmlKeyword.elibWidthOffset, ai.elibWidthOffset);
 
1952
 
 
1953
            for (ArcLayer al: ai.arcLayers) {
 
1954
                String style = al.style == Type.FILLED ? "FILLED" : "CLOSED";
 
1955
                b(XmlKeyword.arcLayer); a("layer", al.layer); a("style", style);
 
1956
                if (al.extend.isEmpty()) {
 
1957
                    el();
 
1958
                } else {
 
1959
                    cl();
 
1960
                    writeDistance(al.extend);
 
1961
                    el(XmlKeyword.arcLayer);
 
1962
                }
 
1963
            }
 
1964
            if (ai.arcPin != null) {
 
1965
                b(XmlKeyword.arcPin); a("name", ai.arcPin.name); a("port", ai.arcPin.portName); a("elibSize", ai.arcPin.elibSize);
 
1966
                if (ai.arcPin.portArcs.isEmpty()) {
 
1967
                    el();
 
1968
                } else {
 
1969
                    cl();
 
1970
                    for (String portArc: ai.arcPin.portArcs)
 
1971
                        bcpel(XmlKeyword.portArc, portArc);
 
1972
                    el(XmlKeyword.arcPin);
 
1973
                }
 
1974
            }
 
1975
            el(XmlKeyword.arcProto);
 
1976
        }
 
1977
 
 
1978
        private void writeXml(PrimitiveNode ni) {
 
1979
            b(XmlKeyword.primitiveNode); a("name", ni.name); a("fun", ni.function.name()); cl();
 
1980
            bcpel(XmlKeyword.oldName, ni.oldName);
 
1981
 
 
1982
            if (ni.shrinkArcs)
 
1983
                bel(XmlKeyword.shrinkArcs);
 
1984
            if (ni.square)
 
1985
                bel(XmlKeyword.square);
 
1986
            if (ni.canBeZeroSize)
 
1987
                bel(XmlKeyword.canBeZeroSize);
 
1988
            if (ni.wipes)
 
1989
                bel(XmlKeyword.wipes);
 
1990
            if (ni.lockable)
 
1991
                bel(XmlKeyword.lockable);
 
1992
            if (ni.edgeSelect)
 
1993
                bel(XmlKeyword.edgeSelect);
 
1994
            if (ni.skipSizeInPalette)
 
1995
                bel(XmlKeyword.skipSizeInPalette);
 
1996
            if (ni.notUsed)
 
1997
                bel(XmlKeyword.notUsed);
 
1998
            if (ni.lowVt)
 
1999
                bel(XmlKeyword.lowVt);
 
2000
            if (ni.highVt)
 
2001
                bel(XmlKeyword.highVt);
 
2002
            if (ni.nativeBit)
 
2003
                bel(XmlKeyword.nativeBit);
 
2004
            if (ni.od18)
 
2005
                bel(XmlKeyword.od18);
 
2006
            if (ni.od25)
 
2007
                bel(XmlKeyword.od25);
 
2008
            if (ni.od33)
 
2009
                bel(XmlKeyword.od33);
 
2010
 
 
2011
            if (ni.diskOffset != null) {
 
2012
                b(XmlKeyword.diskOffset); a("x", ni.diskOffset.getLambdaX()); a("y", ni.diskOffset.getLambdaY()); el();
 
2013
            }
 
2014
 
 
2015
            if (!ni.defaultWidth.isEmpty()) {
 
2016
                bcl(XmlKeyword.defaultWidth);
 
2017
                writeDistance(ni.defaultWidth);
 
2018
                el(XmlKeyword.defaultWidth);
 
2019
            }
 
2020
 
 
2021
            if (!ni.defaultHeight.isEmpty()) {
 
2022
                bcl(XmlKeyword.defaultHeight);
 
2023
                writeDistance(ni.defaultHeight);
 
2024
                el(XmlKeyword.defaultHeight);
 
2025
            }
 
2026
 
 
2027
            if (ni.nodeBase != null) {
 
2028
                double lx = ni.nodeBase.getLambdaMinX();
 
2029
                double hx = ni.nodeBase.getLambdaMaxX();
 
2030
                double ly = ni.nodeBase.getLambdaMinY();
 
2031
                double hy = ni.nodeBase.getLambdaMaxY();
 
2032
                b(XmlKeyword.nodeBase); a("lx", lx); a("hx", hx); a("ly", ly); a("hy", hy); el();
 
2033
            }
 
2034
 
 
2035
            for(int j=0; j<ni.nodeLayers.size(); j++) {
 
2036
                NodeLayer nl = ni.nodeLayers.get(j);
 
2037
                b(XmlKeyword.nodeLayer); a("layer", nl.layer); a("style", nl.style.name());
 
2038
                if (nl.portNum != 0) a("portNum", Integer.valueOf(nl.portNum));
 
2039
                if (!(nl.inLayers && nl.inElectricalLayers))
 
2040
                    a("electrical", nl.inElectricalLayers);
 
2041
                cl();
 
2042
                switch (nl.representation) {
 
2043
                    case com.sun.electric.technology.Technology.NodeLayer.BOX:
 
2044
                        if (ni.specialType == com.sun.electric.technology.PrimitiveNode.SERPTRANS) {
 
2045
                            writeBox(XmlKeyword.serpbox, nl.lx, nl.hx, nl.ly, nl.hy);
 
2046
                            a("lWidth", nl.lWidth); a("rWidth", nl.rWidth); a("tExtent", nl.tExtent); a("bExtent", nl.bExtent); cl();
 
2047
                            writeLambdaBox(nl.lx, nl.hx, nl.ly, nl.hy);
 
2048
                            el(XmlKeyword.serpbox);
 
2049
                        } else {
 
2050
                            writeBox(XmlKeyword.box, nl.lx, nl.hx, nl.ly, nl.hy); cl();
 
2051
                            writeLambdaBox(nl.lx, nl.hx, nl.ly, nl.hy);
 
2052
                            el(XmlKeyword.box);
 
2053
                        }
 
2054
                        break;
 
2055
                    case com.sun.electric.technology.Technology.NodeLayer.POINTS:
 
2056
                        b(XmlKeyword.points); el();
 
2057
                        break;
 
2058
                    case com.sun.electric.technology.Technology.NodeLayer.MULTICUTBOX:
 
2059
                        writeBox(XmlKeyword.multicutbox, nl.lx, nl.hx, nl.ly, nl.hy);
 
2060
                        a("sizeRule", nl.sizeRule); a("sepRule", nl.sepRule); a("sepRule2D", nl.sepRule2D);
 
2061
                        if (nl.lx.isEmpty() && nl.hx.isEmpty() && nl.ly.isEmpty() && nl.hy.isEmpty()) {
 
2062
                            el();
 
2063
                        } else {
 
2064
                            cl();
 
2065
                            writeLambdaBox(nl.lx, nl.hx, nl.ly, nl.hy);
 
2066
                            el(XmlKeyword.multicutbox);
 
2067
                        }
 
2068
                        break;
 
2069
                }
 
2070
                for (TechPoint tp: nl.techPoints) {
 
2071
                    double xm = tp.getX().getMultiplier();
 
2072
                    double xa = tp.getX().getAdder();
 
2073
                    double ym = tp.getY().getMultiplier();
 
2074
                    double ya = tp.getY().getAdder();
 
2075
                    b(XmlKeyword.techPoint); a("xm", xm); a("xa", xa); a("ym", ym); a("ya", ya); el();
 
2076
                }
 
2077
                el(XmlKeyword.nodeLayer);
 
2078
            }
 
2079
            for (int j = 0; j < ni.ports.size(); j++) {
 
2080
                PrimitivePort pd = ni.ports.get(j);
 
2081
                b(XmlKeyword.primitivePort); a("name", pd.name); cl();
 
2082
                b(XmlKeyword.portAngle); a("primary", pd.portAngle); a("range", pd.portRange); el();
 
2083
                bcpel(XmlKeyword.portTopology, pd.portTopology);
 
2084
 
 
2085
                writeBox(XmlKeyword.box, pd.lx, pd.hx, pd.ly, pd.hy); cl();
 
2086
                writeLambdaBox(pd.lx, pd.hx, pd.ly, pd.hy);
 
2087
                el(XmlKeyword.box);
 
2088
 
 
2089
                for (String portArc: pd.portArcs)
 
2090
                    bcpel(XmlKeyword.portArc, portArc);
 
2091
                el(XmlKeyword.primitivePort);
 
2092
            }
 
2093
            switch (ni.specialType) {
 
2094
                case com.sun.electric.technology.PrimitiveNode.POLYGONAL:
 
2095
                    bel(XmlKeyword.polygonal);
 
2096
                    break;
 
2097
                case com.sun.electric.technology.PrimitiveNode.SERPTRANS:
 
2098
                    b(XmlKeyword.serpTrans); cl();
 
2099
                    for (int i = 0; i < 6; i++) {
 
2100
                        bcpel(XmlKeyword.specialValue, ni.specialValues[i]);
 
2101
                    }
 
2102
                    el(XmlKeyword.serpTrans);
 
2103
                    break;
 
2104
            }
 
2105
            if (ni.nodeSizeRule != null) {
 
2106
                NodeSizeRule r = ni.nodeSizeRule;
 
2107
                b(XmlKeyword.minSizeRule); a("width", r.width); a("height", r.height); a("rule", r.rule); el();
 
2108
            }
 
2109
            if (ni.spiceTemplate != null)
 
2110
            {
 
2111
                b(XmlKeyword.spiceTemplate); a("value", ni.spiceTemplate); el();
 
2112
            }
 
2113
 
 
2114
            el(XmlKeyword.primitiveNode);
 
2115
        }
 
2116
 
 
2117
        private void writeDistance(Distance d) {
 
2118
            d.writeXml(this, true);
 
2119
        }
 
2120
 
 
2121
        private void writeBox(XmlKeyword keyword, Distance lx, Distance hx, Distance ly, Distance hy) {
 
2122
            b(keyword);
 
2123
            if (lx.k != -1) a("klx", lx.k);
 
2124
            if (hx.k != 1) a("khx", hx.k);
 
2125
            if (ly.k != -1) a("kly", ly.k);
 
2126
            if (hy.k != 1) a("khy", hy.k);
 
2127
        }
 
2128
 
 
2129
        private void writeLambdaBox(Distance lx, Distance hx, Distance ly, Distance hy) {
 
2130
            double lxv = lx.getLambda(EMPTY_CONTEXT);
 
2131
            double hxv = hx.getLambda(EMPTY_CONTEXT);
 
2132
            double lyv = ly.getLambda(EMPTY_CONTEXT);
 
2133
            double hyv = hy.getLambda(EMPTY_CONTEXT);
 
2134
//            if (lxv == 0 && hxv == 0 && lyv == 0 && hyv == 0) return;
 
2135
            b(XmlKeyword.lambdaBox); a("klx", lxv); a("khx", hxv); a("kly", lyv); a("khy", hyv); el();
 
2136
        }
 
2137
 
 
2138
        private void writeSpiceHeaderXml(SpiceHeader spiceHeader) {
 
2139
            b(XmlKeyword.spiceHeader); a("level", spiceHeader.level); cl();
 
2140
            for (String line: spiceHeader.spiceLines) {
 
2141
                b(XmlKeyword.spiceLine); a("line", line); el();
 
2142
            }
 
2143
            el(XmlKeyword.spiceHeader);
 
2144
            l();
 
2145
        }
 
2146
        
 
2147
        private void writeDisplayStyleXml(DisplayStyle displayStyle) {
 
2148
            b(XmlKeyword.displayStyle); a("name", displayStyle.name); cl();
 
2149
            
 
2150
            if (displayStyle.transparentLayers.size() != 0) {
 
2151
                comment("Transparent layers");
 
2152
                for (int i = 0; i < displayStyle.transparentLayers.size(); i++) {
 
2153
                    Color color = displayStyle.transparentLayers.get(i);
 
2154
                    b(XmlKeyword.transparentLayer); a("transparent", i + 1); cl();
 
2155
                    bcpel(XmlKeyword.r, color.getRed());
 
2156
                    bcpel(XmlKeyword.g, color.getGreen());
 
2157
                    bcpel(XmlKeyword.b, color.getBlue());
 
2158
                    el(XmlKeyword.transparentLayer);
 
2159
                }
 
2160
                l();
 
2161
            }
 
2162
            
 
2163
            for (LayerDisplayStyle l: displayStyle.layerStyles.values()) {
 
2164
                b(XmlKeyword.layer); a("name", l.layer.name); cl();
 
2165
                EGraphics desc = l.desc;
 
2166
                if (desc.getTransparentLayer() > 0) {
 
2167
                    b(XmlKeyword.transparentColor); a("transparent", desc.getTransparentLayer()); el();
 
2168
                } else {
 
2169
                    Color color = desc.getColor();
 
2170
                    b(XmlKeyword.opaqueColor); a("r", color.getRed()); a("g", color.getGreen()); a("b", color.getBlue()); el();
 
2171
                }
 
2172
 
 
2173
                bcpel(XmlKeyword.patternedOnDisplay, desc.isPatternedOnDisplay());
 
2174
                bcpel(XmlKeyword.patternedOnPrinter, desc.isPatternedOnPrinter());
 
2175
 
 
2176
                int [] pattern = desc.getPattern();
 
2177
                for(int j=0; j<16; j++) {
 
2178
                    String p = "";
 
2179
                    for(int k=0; k<16; k++)
 
2180
                        p += (pattern[j] & (1 << (15-k))) != 0 ? 'X' : ' ';
 
2181
                    bcpel(XmlKeyword.pattern, p);
 
2182
                }
 
2183
 
 
2184
                if (desc.getOutlined() != null)
 
2185
                    bcpel(XmlKeyword.outlined, desc.getOutlined().getConstName());
 
2186
                bcpel(XmlKeyword.opacity, desc.getOpacity());
 
2187
                bcpel(XmlKeyword.foreground, desc.getForeground());
 
2188
                
 
2189
                // write the 3D information
 
2190
                if (l.mode3D != null) {
 
2191
                    b(XmlKeyword.display3D); a("mode", l.mode3D); a("factor", l.factor3D); el();
 
2192
                }
 
2193
 
 
2194
                el(XmlKeyword.layer);
 
2195
            }
 
2196
 
 
2197
            el(XmlKeyword.displayStyle);
 
2198
            l();
 
2199
        }
 
2200
 
 
2201
        public void writeMenuPaletteXml(MenuPalette menuPalette) {
 
2202
            if (menuPalette == null) return;
 
2203
            b(XmlKeyword.menuPalette); a("numColumns", menuPalette.numColumns); cl();
 
2204
            for (int i = 0; i < menuPalette.menuBoxes.size(); i++) {
 
2205
                if (i % menuPalette.numColumns == 0)
 
2206
                    l();
 
2207
                writeMenuBoxXml(menuPalette.menuBoxes.get(i));
 
2208
            }
 
2209
            l();
 
2210
            el(XmlKeyword.menuPalette);
 
2211
            l();
 
2212
        }
 
2213
 
 
2214
        private void writeMenuBoxXml(List<Object> list) {
 
2215
            b(XmlKeyword.menuBox);
 
2216
            if (list.size() == 0) {
 
2217
                el();
 
2218
                return;
 
2219
            }
 
2220
            cl();
 
2221
            for (Object o: list) {
 
2222
                if (o instanceof ArcProto) {
 
2223
                    bcpel(XmlKeyword.menuArc, ((ArcProto)o).name);
 
2224
                } else if (o instanceof PrimitiveNode) {
 
2225
                    bcpel(XmlKeyword.menuNode, ((PrimitiveNode)o).name);
 
2226
                } else if (o instanceof MenuCell) {
 
2227
                    MenuCell cell = (MenuCell)o;
 
2228
                    b(XmlKeyword.menuCell); a("cellName", cell.cellName); el();
 
2229
                } else if (o instanceof MenuNodeInst) {
 
2230
                    MenuNodeInst ni = (MenuNodeInst)o;
 
2231
                    b(XmlKeyword.menuNodeInst); a("protoName", ni.protoName); a("function", ni.function.name());
 
2232
                    if (ni.rotation != 0) a("rotation", ni.rotation);
 
2233
                    if (ni.text == null) {
 
2234
                        el();
 
2235
                    } else {
 
2236
                        cl();
 
2237
                        b(XmlKeyword.menuNodeText); a("text", ni.text); a("size", ni.fontSize); el();
 
2238
                        el(XmlKeyword.menuNodeInst);
 
2239
                    }
 
2240
                } else {
 
2241
                        if (o == null) bel(XmlKeyword.menuText); else
 
2242
                                bcpel(XmlKeyword.menuText, o);
 
2243
                }
 
2244
            }
 
2245
            el(XmlKeyword.menuBox);
 
2246
        }
 
2247
        
 
2248
        private void writeXml(RuleSet ruleSet) {
 
2249
            b(XmlKeyword.ruleSet); a("name", ruleSet.name); cl();
 
2250
            for (Map.Entry<String,Map<Layer,Distance>> e: ruleSet.layerRules.entrySet())
 
2251
                writeLayerRuleXml(e.getKey(), e.getValue());
 
2252
            el(XmlKeyword.ruleSet);
 
2253
            l();
 
2254
        }
 
2255
        
 
2256
        private void writeLayerRuleXml(String ruleName, Map<Layer,Distance> sizes) {
 
2257
            if (sizes.isEmpty()) return;
 
2258
            b(XmlKeyword.layerRule); a("ruleName", ruleName); cl();
 
2259
            int maxNameLength = 0;
 
2260
            for (Layer l: sizes.keySet())
 
2261
                maxNameLength = Math.max(maxNameLength, l.name.length());
 
2262
            for (Map.Entry<Layer,Distance> e: sizes.entrySet()) {
 
2263
                String layerName = e.getKey().name;
 
2264
                Distance d = e.getValue();
 
2265
                b(XmlKeyword.layer); a("name", layerName); c();
 
2266
                s(maxNameLength - layerName.length());
 
2267
                d.writeXml(this, false);
 
2268
                el(XmlKeyword.layer);
 
2269
            }
 
2270
            el(XmlKeyword.layerRule);
 
2271
        }
 
2272
 
 
2273
        private void writeFoundryXml(Foundry foundry) {
 
2274
            b(XmlKeyword.Foundry); a("name", foundry.name); cl();
 
2275
            l();
 
2276
            for (Map.Entry<String,String> e: foundry.layerGds.entrySet()) {
 
2277
                b(XmlKeyword.layerGds); a("layer", e.getKey()); a("gds", e.getValue()); el();
 
2278
            }
 
2279
            l();
 
2280
            for (DRCTemplate rule: foundry.rules)
 
2281
                DRCTemplate.exportDRCRule(out, rule);
 
2282
            el(XmlKeyword.Foundry);
 
2283
        }
 
2284
 
 
2285
        private void header() {
 
2286
            checkIndent();
 
2287
            out.print("<?xml"); a("version", "1.0"); a("encoding", "UTF-8"); out.println("?>");
 
2288
        }
 
2289
 
 
2290
        private void comment(String s) {
 
2291
            checkIndent();
 
2292
            out.print("<!-- "); p(s); out.print(" -->"); l();
 
2293
        }
 
2294
 
 
2295
        /**
 
2296
         * Print attribute.
 
2297
         */
 
2298
        private void a(String name, Object value) {
 
2299
            checkIndent();
 
2300
            if (value == null) return;
 
2301
            out.print(" " + name + "=\"");
 
2302
            p(value.toString());
 
2303
            out.print("\"");
 
2304
        }
 
2305
 
 
2306
        private void bcpe(XmlKeyword key, Object v) {
 
2307
            if (v == null) return;
 
2308
            b(key); c(); p(v.toString()); e(key);
 
2309
        }
 
2310
 
 
2311
        private void bcpel(XmlKeyword key, Object v) {
 
2312
            if (v == null) return;
 
2313
            b(key); c(); p(v.toString()); el(key);
 
2314
        }
 
2315
 
 
2316
        private void bcl(XmlKeyword key) {
 
2317
            b(key); cl();
 
2318
        }
 
2319
 
 
2320
        private void bel(XmlKeyword key) {
 
2321
            b(key); el();
 
2322
        }
 
2323
 
 
2324
        /**
 
2325
         * Print text with replacement of special chars.
 
2326
         */
 
2327
        private void pl(String s) {
 
2328
            checkIndent();
 
2329
            p(s); l();
 
2330
        }
 
2331
 
 
2332
        /**
 
2333
         * Print text with replacement of special chars.
 
2334
         */
 
2335
        protected void p(String s) {
 
2336
            assert indentEmitted;
 
2337
            for (int i = 0; i < s.length(); i++) {
 
2338
                char c = s.charAt(i);
 
2339
                switch (c) {
 
2340
                    case '<':
 
2341
                        out.print("&lt;");
 
2342
                        break;
 
2343
                    case '>':
 
2344
                        out.print("&gt;");
 
2345
                        break;
 
2346
                    case '&':
 
2347
                        out.print("&amp;");
 
2348
                        break;
 
2349
                    case '\'':
 
2350
                        out.print("&apos;");
 
2351
                        break;
 
2352
                    case '"':
 
2353
                        out.print("quot;");
 
2354
                        break;
 
2355
                    default:
 
2356
                        out.print(c);
 
2357
                }
 
2358
            }
 
2359
        }
 
2360
 
 
2361
        /**
 
2362
         * Print element name, and indent.
 
2363
         */
 
2364
        private void b(XmlKeyword key) {
 
2365
            checkIndent();
 
2366
            out.print('<');
 
2367
            out.print(key.name());
 
2368
            indent += INDENT_WIDTH;
 
2369
        }
 
2370
 
 
2371
        private void cl() {
 
2372
            assert indentEmitted;
 
2373
            out.print('>');
 
2374
            l();
 
2375
        }
 
2376
 
 
2377
        private void c() {
 
2378
            assert indentEmitted;
 
2379
            out.print('>');
 
2380
        }
 
2381
 
 
2382
        private void el() {
 
2383
            e(); l();
 
2384
        }
 
2385
 
 
2386
        private void el(XmlKeyword key) {
 
2387
            e(key); l();
 
2388
        }
 
2389
 
 
2390
        private void e() {
 
2391
            assert indentEmitted;
 
2392
            out.print("/>");
 
2393
            indent -= INDENT_WIDTH;
 
2394
        }
 
2395
 
 
2396
        private void e(XmlKeyword key) {
 
2397
            indent -= INDENT_WIDTH;
 
2398
            checkIndent();
 
2399
            out.print("</");
 
2400
            out.print(key.name());
 
2401
            out.print(">");
 
2402
        }
 
2403
 
 
2404
        protected void checkIndent() {
 
2405
            if (indentEmitted) return;
 
2406
            s(indent);
 
2407
            indentEmitted = true;
 
2408
        }
 
2409
        
 
2410
        protected void s(int numSpaces) {
 
2411
            for (int i = 0; i < numSpaces; i++)
 
2412
                out.print(' ');
 
2413
        }
 
2414
 
 
2415
        /**
 
2416
         *  Print new line.
 
2417
         */
 
2418
        protected void l() {
 
2419
            out.println();
 
2420
            indentEmitted = false;
 
2421
        }
 
2422
    }
 
2423
 
 
2424
    public static DistanceContext EMPTY_CONTEXT = new DistanceContext() {
 
2425
        public double getRule(String ruleName) {
 
2426
            throw new UnsupportedOperationException();
 
2427
        }
 
2428
    };
 
2429
 
 
2430
    /**
 
2431
     * Class to write the XML without multiple lines and indentation.
 
2432
     * Useful when the XML is to be a single string.
 
2433
     */
 
2434
        private static class OneLineWriter extends Writer
 
2435
        {
 
2436
                private OneLineWriter(PrintWriter out)
 
2437
                {
 
2438
                        super(out);
 
2439
                }
 
2440
 
 
2441
                /**
 
2442
                 * Print text without replacement of special chars.
 
2443
                 */
 
2444
        @Override
 
2445
                protected void p(String s)
 
2446
                {
 
2447
                        for (int i = 0; i < s.length(); i++)
 
2448
                                out.print(s.charAt(i));
 
2449
                }
 
2450
 
 
2451
        @Override
 
2452
                protected void checkIndent() { indentEmitted = true; }
 
2453
 
 
2454
                /**
 
2455
                 * Do not print new line.
 
2456
                 */
 
2457
        @Override
 
2458
                protected void l() { indentEmitted = false; }
 
2459
        }
 
2460
}