0001: /*
0002:
0003: Licensed to the Apache Software Foundation (ASF) under one or more
0004: contributor license agreements. See the NOTICE file distributed with
0005: this work for additional information regarding copyright ownership.
0006: The ASF licenses this file to You under the Apache License, Version 2.0
0007: (the "License"); you may not use this file except in compliance with
0008: the License. You may obtain a copy of the License at
0009:
0010: http://www.apache.org/licenses/LICENSE-2.0
0011:
0012: Unless required by applicable law or agreed to in writing, software
0013: distributed under the License is distributed on an "AS IS" BASIS,
0014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015: See the License for the specific language governing permissions and
0016: limitations under the License.
0017:
0018: */
0019: package org.apache.batik.parser;
0020:
0021: import java.io.IOException;
0022:
0023: import org.apache.batik.xml.XMLUtilities;
0024:
0025: /**
0026: * This class represents an event-based parser for the SVG
0027: * fragment identifiers.
0028: *
0029: * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
0030: * @version $Id: FragmentIdentifierParser.java 502167 2007-02-01 09:26:51Z dvholten $
0031: */
0032: public class FragmentIdentifierParser extends NumberParser {
0033:
0034: /**
0035: * The buffer used for numbers.
0036: */
0037: protected char[] buffer = new char[16];
0038:
0039: /**
0040: * The buffer size.
0041: */
0042: protected int bufferSize;
0043:
0044: /**
0045: * The FragmentIdentifierHandler.
0046: */
0047: protected FragmentIdentifierHandler fragmentIdentifierHandler;
0048:
0049: /**
0050: * Creates a new FragmentIdentifier parser.
0051: */
0052: public FragmentIdentifierParser() {
0053: fragmentIdentifierHandler = DefaultFragmentIdentifierHandler.INSTANCE;
0054: }
0055:
0056: /**
0057: * Allows an application to register a fragment identifier handler.
0058: *
0059: * <p>If the application does not register a handler, all
0060: * events reported by the parser will be silently ignored.
0061: *
0062: * <p>Applications may register a new or different handler in the
0063: * middle of a parse, and the parser must begin using the new
0064: * handler immediately.</p>
0065: * @param handler The transform list handler.
0066: */
0067: public void setFragmentIdentifierHandler(
0068: FragmentIdentifierHandler handler) {
0069: fragmentIdentifierHandler = handler;
0070: }
0071:
0072: /**
0073: * Returns the points handler in use.
0074: */
0075: public FragmentIdentifierHandler getFragmentIdentifierHandler() {
0076: return fragmentIdentifierHandler;
0077: }
0078:
0079: /**
0080: * Parses the current reader.
0081: */
0082: protected void doParse() throws ParseException, IOException {
0083: bufferSize = 0;
0084:
0085: current = reader.read();
0086:
0087: fragmentIdentifierHandler.startFragmentIdentifier();
0088:
0089: ident: {
0090: String id = null;
0091:
0092: switch (current) {
0093: case 'x':
0094: bufferize();
0095: current = reader.read();
0096: if (current != 'p') {
0097: parseIdentifier();
0098: break;
0099: }
0100: bufferize();
0101: current = reader.read();
0102: if (current != 'o') {
0103: parseIdentifier();
0104: break;
0105: }
0106: bufferize();
0107: current = reader.read();
0108: if (current != 'i') {
0109: parseIdentifier();
0110: break;
0111: }
0112: bufferize();
0113: current = reader.read();
0114: if (current != 'n') {
0115: parseIdentifier();
0116: break;
0117: }
0118: bufferize();
0119: current = reader.read();
0120: if (current != 't') {
0121: parseIdentifier();
0122: break;
0123: }
0124: bufferize();
0125: current = reader.read();
0126: if (current != 'e') {
0127: parseIdentifier();
0128: break;
0129: }
0130: bufferize();
0131: current = reader.read();
0132: if (current != 'r') {
0133: parseIdentifier();
0134: break;
0135: }
0136: bufferize();
0137: current = reader.read();
0138: if (current != '(') {
0139: parseIdentifier();
0140: break;
0141: }
0142: bufferSize = 0;
0143: current = reader.read();
0144: if (current != 'i') {
0145: reportCharacterExpectedError('i', current);
0146: break ident;
0147: }
0148: current = reader.read();
0149: if (current != 'd') {
0150: reportCharacterExpectedError('d', current);
0151: break ident;
0152: }
0153: current = reader.read();
0154: if (current != '(') {
0155: reportCharacterExpectedError('(', current);
0156: break ident;
0157: }
0158: current = reader.read();
0159: if (current != '"' && current != '\'') {
0160: reportCharacterExpectedError('\'', current);
0161: break ident;
0162: }
0163: char q = (char) current;
0164: current = reader.read();
0165: parseIdentifier();
0166:
0167: id = getBufferContent();
0168: bufferSize = 0;
0169: fragmentIdentifierHandler.idReference(id);
0170:
0171: if (current != q) {
0172: reportCharacterExpectedError(q, current);
0173: break ident;
0174: }
0175: current = reader.read();
0176: if (current != ')') {
0177: reportCharacterExpectedError(')', current);
0178: break ident;
0179: }
0180: current = reader.read();
0181: if (current != ')') {
0182: reportCharacterExpectedError(')', current);
0183: }
0184: break ident;
0185:
0186: case 's':
0187: bufferize();
0188: current = reader.read();
0189: if (current != 'v') {
0190: parseIdentifier();
0191: break;
0192: }
0193: bufferize();
0194: current = reader.read();
0195: if (current != 'g') {
0196: parseIdentifier();
0197: break;
0198: }
0199: bufferize();
0200: current = reader.read();
0201: if (current != 'V') {
0202: parseIdentifier();
0203: break;
0204: }
0205: bufferize();
0206: current = reader.read();
0207: if (current != 'i') {
0208: parseIdentifier();
0209: break;
0210: }
0211: bufferize();
0212: current = reader.read();
0213: if (current != 'e') {
0214: parseIdentifier();
0215: break;
0216: }
0217: bufferize();
0218: current = reader.read();
0219: if (current != 'w') {
0220: parseIdentifier();
0221: break;
0222: }
0223: bufferize();
0224: current = reader.read();
0225: if (current != '(') {
0226: parseIdentifier();
0227: break;
0228: }
0229: bufferSize = 0;
0230: current = reader.read();
0231: parseViewAttributes();
0232:
0233: if (current != ')') {
0234: reportCharacterExpectedError(')', current);
0235: }
0236: break ident;
0237:
0238: default:
0239: if (current == -1
0240: || !XMLUtilities
0241: .isXMLNameFirstCharacter((char) current)) {
0242: break ident;
0243: }
0244: bufferize();
0245: current = reader.read();
0246: parseIdentifier();
0247: }
0248: id = getBufferContent();
0249: fragmentIdentifierHandler.idReference(id);
0250: }
0251:
0252: fragmentIdentifierHandler.endFragmentIdentifier();
0253: }
0254:
0255: /**
0256: * Parses the svgView attributes.
0257: */
0258: protected void parseViewAttributes() throws ParseException,
0259: IOException {
0260: boolean first = true;
0261: loop: for (;;) {
0262: switch (current) {
0263: case -1:
0264: case ')':
0265: if (first) {
0266: reportUnexpectedCharacterError(current);
0267: break loop;
0268: }
0269: // fallthrough
0270: default:
0271: break loop;
0272: case ';':
0273: if (first) {
0274: reportUnexpectedCharacterError(current);
0275: break loop;
0276: }
0277: current = reader.read();
0278: break;
0279: case 'v':
0280: first = false;
0281: current = reader.read();
0282: if (current != 'i') {
0283: reportCharacterExpectedError('i', current);
0284: break loop;
0285: }
0286: current = reader.read();
0287: if (current != 'e') {
0288: reportCharacterExpectedError('e', current);
0289: break loop;
0290: }
0291: current = reader.read();
0292: if (current != 'w') {
0293: reportCharacterExpectedError('w', current);
0294: break loop;
0295: }
0296: current = reader.read();
0297:
0298: switch (current) {
0299: case 'B':
0300: current = reader.read();
0301: if (current != 'o') {
0302: reportCharacterExpectedError('o', current);
0303: break loop;
0304: }
0305: current = reader.read();
0306: if (current != 'x') {
0307: reportCharacterExpectedError('x', current);
0308: break loop;
0309: }
0310: current = reader.read();
0311: if (current != '(') {
0312: reportCharacterExpectedError('(', current);
0313: break loop;
0314: }
0315: current = reader.read();
0316:
0317: float x = parseFloat();
0318: if (current != ',') {
0319: reportCharacterExpectedError(',', current);
0320: break loop;
0321: }
0322: current = reader.read();
0323:
0324: float y = parseFloat();
0325: if (current != ',') {
0326: reportCharacterExpectedError(',', current);
0327: break loop;
0328: }
0329: current = reader.read();
0330:
0331: float w = parseFloat();
0332: if (current != ',') {
0333: reportCharacterExpectedError(',', current);
0334: break loop;
0335: }
0336: current = reader.read();
0337:
0338: float h = parseFloat();
0339: if (current != ')') {
0340: reportCharacterExpectedError(')', current);
0341: break loop;
0342: }
0343: current = reader.read();
0344: fragmentIdentifierHandler.viewBox(x, y, w, h);
0345: if (current != ')' && current != ';') {
0346: reportCharacterExpectedError(')', current);
0347: break loop;
0348: }
0349: break;
0350:
0351: case 'T':
0352: current = reader.read();
0353: if (current != 'a') {
0354: reportCharacterExpectedError('a', current);
0355: break loop;
0356: }
0357: current = reader.read();
0358: if (current != 'r') {
0359: reportCharacterExpectedError('r', current);
0360: break loop;
0361: }
0362: current = reader.read();
0363: if (current != 'g') {
0364: reportCharacterExpectedError('g', current);
0365: break loop;
0366: }
0367: current = reader.read();
0368: if (current != 'e') {
0369: reportCharacterExpectedError('e', current);
0370: break loop;
0371: }
0372: current = reader.read();
0373: if (current != 't') {
0374: reportCharacterExpectedError('t', current);
0375: break loop;
0376: }
0377: current = reader.read();
0378: if (current != '(') {
0379: reportCharacterExpectedError('(', current);
0380: break loop;
0381: }
0382: current = reader.read();
0383:
0384: fragmentIdentifierHandler.startViewTarget();
0385:
0386: id: for (;;) {
0387: bufferSize = 0;
0388: if (current == -1
0389: || !XMLUtilities
0390: .isXMLNameFirstCharacter((char) current)) {
0391: reportUnexpectedCharacterError(current);
0392: break loop;
0393: }
0394: bufferize();
0395: current = reader.read();
0396: parseIdentifier();
0397: String s = getBufferContent();
0398:
0399: fragmentIdentifierHandler.viewTarget(s);
0400:
0401: bufferSize = 0;
0402: switch (current) {
0403: case ')':
0404: current = reader.read();
0405: break id;
0406: case ',':
0407: case ';':
0408: current = reader.read();
0409: break;
0410: default:
0411: reportUnexpectedCharacterError(current);
0412: break loop;
0413: }
0414: }
0415:
0416: fragmentIdentifierHandler.endViewTarget();
0417: break;
0418:
0419: default:
0420: reportUnexpectedCharacterError(current);
0421: break loop;
0422: }
0423: break;
0424: case 'p':
0425: first = false;
0426: current = reader.read();
0427: if (current != 'r') {
0428: reportCharacterExpectedError('r', current);
0429: break loop;
0430: }
0431: current = reader.read();
0432: if (current != 'e') {
0433: reportCharacterExpectedError('e', current);
0434: break loop;
0435: }
0436: current = reader.read();
0437: if (current != 's') {
0438: reportCharacterExpectedError('s', current);
0439: break loop;
0440: }
0441: current = reader.read();
0442: if (current != 'e') {
0443: reportCharacterExpectedError('e', current);
0444: break loop;
0445: }
0446: current = reader.read();
0447: if (current != 'r') {
0448: reportCharacterExpectedError('r', current);
0449: break loop;
0450: }
0451: current = reader.read();
0452: if (current != 'v') {
0453: reportCharacterExpectedError('v', current);
0454: break loop;
0455: }
0456: current = reader.read();
0457: if (current != 'e') {
0458: reportCharacterExpectedError('e', current);
0459: break loop;
0460: }
0461: current = reader.read();
0462: if (current != 'A') {
0463: reportCharacterExpectedError('A', current);
0464: break loop;
0465: }
0466: current = reader.read();
0467: if (current != 's') {
0468: reportCharacterExpectedError('s', current);
0469: break loop;
0470: }
0471: current = reader.read();
0472: if (current != 'p') {
0473: reportCharacterExpectedError('p', current);
0474: break loop;
0475: }
0476: current = reader.read();
0477: if (current != 'e') {
0478: reportCharacterExpectedError('e', current);
0479: break loop;
0480: }
0481: current = reader.read();
0482: if (current != 'c') {
0483: reportCharacterExpectedError('c', current);
0484: break loop;
0485: }
0486: current = reader.read();
0487: if (current != 't') {
0488: reportCharacterExpectedError('t', current);
0489: break loop;
0490: }
0491: current = reader.read();
0492: if (current != 'R') {
0493: reportCharacterExpectedError('R', current);
0494: break loop;
0495: }
0496: current = reader.read();
0497: if (current != 'a') {
0498: reportCharacterExpectedError('a', current);
0499: break loop;
0500: }
0501: current = reader.read();
0502: if (current != 't') {
0503: reportCharacterExpectedError('t', current);
0504: break loop;
0505: }
0506: current = reader.read();
0507: if (current != 'i') {
0508: reportCharacterExpectedError('i', current);
0509: break loop;
0510: }
0511: current = reader.read();
0512: if (current != 'o') {
0513: reportCharacterExpectedError('o', current);
0514: break loop;
0515: }
0516: current = reader.read();
0517: if (current != '(') {
0518: reportCharacterExpectedError('(', current);
0519: break loop;
0520: }
0521: current = reader.read();
0522:
0523: parsePreserveAspectRatio();
0524:
0525: if (current != ')') {
0526: reportCharacterExpectedError(')', current);
0527: break loop;
0528: }
0529: current = reader.read();
0530: break;
0531:
0532: case 't':
0533: first = false;
0534: current = reader.read();
0535: if (current != 'r') {
0536: reportCharacterExpectedError('r', current);
0537: break loop;
0538: }
0539: current = reader.read();
0540: if (current != 'a') {
0541: reportCharacterExpectedError('a', current);
0542: break loop;
0543: }
0544: current = reader.read();
0545: if (current != 'n') {
0546: reportCharacterExpectedError('n', current);
0547: break loop;
0548: }
0549: current = reader.read();
0550: if (current != 's') {
0551: reportCharacterExpectedError('s', current);
0552: break loop;
0553: }
0554: current = reader.read();
0555: if (current != 'f') {
0556: reportCharacterExpectedError('f', current);
0557: break loop;
0558: }
0559: current = reader.read();
0560: if (current != 'o') {
0561: reportCharacterExpectedError('o', current);
0562: break loop;
0563: }
0564: current = reader.read();
0565: if (current != 'r') {
0566: reportCharacterExpectedError('r', current);
0567: break loop;
0568: }
0569: current = reader.read();
0570: if (current != 'm') {
0571: reportCharacterExpectedError('m', current);
0572: break loop;
0573: }
0574: current = reader.read();
0575: if (current != '(') {
0576: reportCharacterExpectedError('(', current);
0577: break loop;
0578: }
0579:
0580: fragmentIdentifierHandler.startTransformList();
0581:
0582: tloop: for (;;) {
0583: try {
0584: current = reader.read();
0585: switch (current) {
0586: case ',':
0587: break;
0588: case 'm':
0589: parseMatrix();
0590: break;
0591: case 'r':
0592: parseRotate();
0593: break;
0594: case 't':
0595: parseTranslate();
0596: break;
0597: case 's':
0598: current = reader.read();
0599: switch (current) {
0600: case 'c':
0601: parseScale();
0602: break;
0603: case 'k':
0604: parseSkew();
0605: break;
0606: default:
0607: reportUnexpectedCharacterError(current);
0608: skipTransform();
0609: }
0610: break;
0611: default:
0612: break tloop;
0613: }
0614: } catch (ParseException e) {
0615: errorHandler.error(e);
0616: skipTransform();
0617: }
0618: }
0619:
0620: fragmentIdentifierHandler.endTransformList();
0621: break;
0622:
0623: case 'z':
0624: first = false;
0625: current = reader.read();
0626: if (current != 'o') {
0627: reportCharacterExpectedError('o', current);
0628: break loop;
0629: }
0630: current = reader.read();
0631: if (current != 'o') {
0632: reportCharacterExpectedError('o', current);
0633: break loop;
0634: }
0635: current = reader.read();
0636: if (current != 'm') {
0637: reportCharacterExpectedError('m', current);
0638: break loop;
0639: }
0640: current = reader.read();
0641: if (current != 'A') {
0642: reportCharacterExpectedError('A', current);
0643: break loop;
0644: }
0645: current = reader.read();
0646: if (current != 'n') {
0647: reportCharacterExpectedError('n', current);
0648: break loop;
0649: }
0650: current = reader.read();
0651: if (current != 'd') {
0652: reportCharacterExpectedError('d', current);
0653: break loop;
0654: }
0655: current = reader.read();
0656: if (current != 'P') {
0657: reportCharacterExpectedError('P', current);
0658: break loop;
0659: }
0660: current = reader.read();
0661: if (current != 'a') {
0662: reportCharacterExpectedError('a', current);
0663: break loop;
0664: }
0665: current = reader.read();
0666: if (current != 'n') {
0667: reportCharacterExpectedError('n', current);
0668: break loop;
0669: }
0670: current = reader.read();
0671: if (current != '(') {
0672: reportCharacterExpectedError('(', current);
0673: break loop;
0674: }
0675: current = reader.read();
0676:
0677: switch (current) {
0678: case 'm':
0679: current = reader.read();
0680: if (current != 'a') {
0681: reportCharacterExpectedError('a', current);
0682: break loop;
0683: }
0684: current = reader.read();
0685: if (current != 'g') {
0686: reportCharacterExpectedError('g', current);
0687: break loop;
0688: }
0689: current = reader.read();
0690: if (current != 'n') {
0691: reportCharacterExpectedError('n', current);
0692: break loop;
0693: }
0694: current = reader.read();
0695: if (current != 'i') {
0696: reportCharacterExpectedError('i', current);
0697: break loop;
0698: }
0699: current = reader.read();
0700: if (current != 'f') {
0701: reportCharacterExpectedError('f', current);
0702: break loop;
0703: }
0704: current = reader.read();
0705: if (current != 'y') {
0706: reportCharacterExpectedError('y', current);
0707: break loop;
0708: }
0709: current = reader.read();
0710: fragmentIdentifierHandler.zoomAndPan(true);
0711: break;
0712:
0713: case 'd':
0714: current = reader.read();
0715: if (current != 'i') {
0716: reportCharacterExpectedError('i', current);
0717: break loop;
0718: }
0719: current = reader.read();
0720: if (current != 's') {
0721: reportCharacterExpectedError('s', current);
0722: break loop;
0723: }
0724: current = reader.read();
0725: if (current != 'a') {
0726: reportCharacterExpectedError('a', current);
0727: break loop;
0728: }
0729: current = reader.read();
0730: if (current != 'b') {
0731: reportCharacterExpectedError('b', current);
0732: break loop;
0733: }
0734: current = reader.read();
0735: if (current != 'l') {
0736: reportCharacterExpectedError('l', current);
0737: break loop;
0738: }
0739: current = reader.read();
0740: if (current != 'e') {
0741: reportCharacterExpectedError('e', current);
0742: break loop;
0743: }
0744: current = reader.read();
0745: fragmentIdentifierHandler.zoomAndPan(false);
0746: break;
0747:
0748: default:
0749: reportUnexpectedCharacterError(current);
0750: break loop;
0751: }
0752:
0753: if (current != ')') {
0754: reportCharacterExpectedError(')', current);
0755: break loop;
0756: }
0757: current = reader.read();
0758: }
0759: }
0760: }
0761:
0762: /**
0763: * Parses an identifier.
0764: */
0765: protected void parseIdentifier() throws ParseException, IOException {
0766: for (;;) {
0767: if (current == -1
0768: || !XMLUtilities.isXMLNameCharacter((char) current)) {
0769: break;
0770: }
0771: bufferize();
0772: current = reader.read();
0773: }
0774: }
0775:
0776: /**
0777: * Returns the content of the buffer.
0778: */
0779: protected String getBufferContent() {
0780: return new String(buffer, 0, bufferSize);
0781: }
0782:
0783: /**
0784: * Adds the current character to the buffer.
0785: * If necessary, the buffer grows.
0786: */
0787: protected void bufferize() {
0788: if (bufferSize >= buffer.length) {
0789: char[] t = new char[buffer.length * 2];
0790: System.arraycopy(buffer, 0, t, 0, bufferSize);
0791: buffer = t;
0792: }
0793: buffer[bufferSize++] = (char) current;
0794: }
0795:
0796: /**
0797: * Skips the whitespaces in the current reader.
0798: */
0799: protected void skipSpaces() throws IOException {
0800: if (current == ',') {
0801: current = reader.read();
0802: }
0803: }
0804:
0805: /**
0806: * Skips the whitespaces and an optional comma.
0807: */
0808: protected void skipCommaSpaces() throws IOException {
0809: if (current == ',') {
0810: current = reader.read();
0811: }
0812: }
0813:
0814: /**
0815: * Parses a matrix transform. 'm' is assumed to be the current character.
0816: */
0817: protected void parseMatrix() throws ParseException, IOException {
0818: current = reader.read();
0819:
0820: // Parse 'atrix wsp? ( wsp?'
0821: if (current != 'a') {
0822: reportCharacterExpectedError('a', current);
0823: skipTransform();
0824: return;
0825: }
0826: current = reader.read();
0827: if (current != 't') {
0828: reportCharacterExpectedError('t', current);
0829: skipTransform();
0830: return;
0831: }
0832: current = reader.read();
0833: if (current != 'r') {
0834: reportCharacterExpectedError('r', current);
0835: skipTransform();
0836: return;
0837: }
0838: current = reader.read();
0839: if (current != 'i') {
0840: reportCharacterExpectedError('i', current);
0841: skipTransform();
0842: return;
0843: }
0844: current = reader.read();
0845: if (current != 'x') {
0846: reportCharacterExpectedError('x', current);
0847: skipTransform();
0848: return;
0849: }
0850: current = reader.read();
0851: skipSpaces();
0852: if (current != '(') {
0853: reportCharacterExpectedError('(', current);
0854: skipTransform();
0855: return;
0856: }
0857: current = reader.read();
0858: skipSpaces();
0859:
0860: float a = parseFloat();
0861: skipCommaSpaces();
0862: float b = parseFloat();
0863: skipCommaSpaces();
0864: float c = parseFloat();
0865: skipCommaSpaces();
0866: float d = parseFloat();
0867: skipCommaSpaces();
0868: float e = parseFloat();
0869: skipCommaSpaces();
0870: float f = parseFloat();
0871:
0872: skipSpaces();
0873: if (current != ')') {
0874: reportCharacterExpectedError(')', current);
0875: skipTransform();
0876: return;
0877: }
0878:
0879: fragmentIdentifierHandler.matrix(a, b, c, d, e, f);
0880: }
0881:
0882: /**
0883: * Parses a rotate transform. 'r' is assumed to be the current character.
0884: */
0885: protected void parseRotate() throws ParseException, IOException {
0886: current = reader.read();
0887:
0888: // Parse 'otate wsp? ( wsp?'
0889: if (current != 'o') {
0890: reportCharacterExpectedError('o', current);
0891: skipTransform();
0892: return;
0893: }
0894: current = reader.read();
0895: if (current != 't') {
0896: reportCharacterExpectedError('t', current);
0897: skipTransform();
0898: return;
0899: }
0900: current = reader.read();
0901: if (current != 'a') {
0902: reportCharacterExpectedError('a', current);
0903: skipTransform();
0904: return;
0905: }
0906: current = reader.read();
0907: if (current != 't') {
0908: reportCharacterExpectedError('t', current);
0909: skipTransform();
0910: return;
0911: }
0912: current = reader.read();
0913: if (current != 'e') {
0914: reportCharacterExpectedError('e', current);
0915: skipTransform();
0916: return;
0917: }
0918: current = reader.read();
0919: skipSpaces();
0920:
0921: if (current != '(') {
0922: reportCharacterExpectedError('(', current);
0923: skipTransform();
0924: return;
0925: }
0926: current = reader.read();
0927: skipSpaces();
0928:
0929: float theta = parseFloat();
0930: skipSpaces();
0931:
0932: switch (current) {
0933: case ')':
0934: fragmentIdentifierHandler.rotate(theta);
0935: return;
0936: case ',':
0937: current = reader.read();
0938: skipSpaces();
0939: }
0940:
0941: float cx = parseFloat();
0942: skipCommaSpaces();
0943: float cy = parseFloat();
0944:
0945: skipSpaces();
0946: if (current != ')') {
0947: reportCharacterExpectedError(')', current);
0948: skipTransform();
0949: return;
0950: }
0951:
0952: fragmentIdentifierHandler.rotate(theta, cx, cy);
0953: }
0954:
0955: /**
0956: * Parses a translate transform. 't' is assumed to be
0957: * the current character.
0958: */
0959: protected void parseTranslate() throws ParseException, IOException {
0960: current = reader.read();
0961:
0962: // Parse 'ranslate wsp? ( wsp?'
0963: if (current != 'r') {
0964: reportCharacterExpectedError('r', current);
0965: skipTransform();
0966: return;
0967: }
0968: current = reader.read();
0969: if (current != 'a') {
0970: reportCharacterExpectedError('a', current);
0971: skipTransform();
0972: return;
0973: }
0974: current = reader.read();
0975: if (current != 'n') {
0976: reportCharacterExpectedError('n', current);
0977: skipTransform();
0978: return;
0979: }
0980: current = reader.read();
0981: if (current != 's') {
0982: reportCharacterExpectedError('s', current);
0983: skipTransform();
0984: return;
0985: }
0986: current = reader.read();
0987: if (current != 'l') {
0988: reportCharacterExpectedError('l', current);
0989: skipTransform();
0990: return;
0991: }
0992: current = reader.read();
0993: if (current != 'a') {
0994: reportCharacterExpectedError('a', current);
0995: skipTransform();
0996: return;
0997: }
0998: current = reader.read();
0999: if (current != 't') {
1000: reportCharacterExpectedError('t', current);
1001: skipTransform();
1002: return;
1003: }
1004: current = reader.read();
1005: if (current != 'e') {
1006: reportCharacterExpectedError('e', current);
1007: skipTransform();
1008: return;
1009: }
1010: current = reader.read();
1011: skipSpaces();
1012: if (current != '(') {
1013: reportCharacterExpectedError('(', current);
1014: skipTransform();
1015: return;
1016: }
1017: current = reader.read();
1018: skipSpaces();
1019:
1020: float tx = parseFloat();
1021: skipSpaces();
1022:
1023: switch (current) {
1024: case ')':
1025: fragmentIdentifierHandler.translate(tx);
1026: return;
1027: case ',':
1028: current = reader.read();
1029: skipSpaces();
1030: }
1031:
1032: float ty = parseFloat();
1033:
1034: skipSpaces();
1035: if (current != ')') {
1036: reportCharacterExpectedError(')', current);
1037: skipTransform();
1038: return;
1039: }
1040:
1041: fragmentIdentifierHandler.translate(tx, ty);
1042: }
1043:
1044: /**
1045: * Parses a scale transform. 'c' is assumed to be the current character.
1046: */
1047: protected void parseScale() throws ParseException, IOException {
1048: current = reader.read();
1049:
1050: // Parse 'ale wsp? ( wsp?'
1051: if (current != 'a') {
1052: reportCharacterExpectedError('a', current);
1053: skipTransform();
1054: return;
1055: }
1056: current = reader.read();
1057: if (current != 'l') {
1058: reportCharacterExpectedError('l', current);
1059: skipTransform();
1060: return;
1061: }
1062: current = reader.read();
1063: if (current != 'e') {
1064: reportCharacterExpectedError('e', current);
1065: skipTransform();
1066: return;
1067: }
1068: current = reader.read();
1069: skipSpaces();
1070: if (current != '(') {
1071: reportCharacterExpectedError('(', current);
1072: skipTransform();
1073: return;
1074: }
1075: current = reader.read();
1076: skipSpaces();
1077:
1078: float sx = parseFloat();
1079: skipSpaces();
1080:
1081: switch (current) {
1082: case ')':
1083: fragmentIdentifierHandler.scale(sx);
1084: return;
1085: case ',':
1086: current = reader.read();
1087: skipSpaces();
1088: }
1089:
1090: float sy = parseFloat();
1091:
1092: skipSpaces();
1093: if (current != ')') {
1094: reportCharacterExpectedError(')', current);
1095: skipTransform();
1096: return;
1097: }
1098:
1099: fragmentIdentifierHandler.scale(sx, sy);
1100: }
1101:
1102: /**
1103: * Parses a skew transform. 'e' is assumed to be the current character.
1104: */
1105: protected void parseSkew() throws ParseException, IOException {
1106: current = reader.read();
1107:
1108: // Parse 'ew[XY] wsp? ( wsp?'
1109: if (current != 'e') {
1110: reportCharacterExpectedError('e', current);
1111: skipTransform();
1112: return;
1113: }
1114: current = reader.read();
1115: if (current != 'w') {
1116: reportCharacterExpectedError('w', current);
1117: skipTransform();
1118: return;
1119: }
1120: current = reader.read();
1121:
1122: boolean skewX = false;
1123: switch (current) {
1124: case 'X':
1125: skewX = true;
1126: // fall-through
1127: case 'Y':
1128: break;
1129: default:
1130: reportCharacterExpectedError('X', current);
1131: skipTransform();
1132: return;
1133: }
1134: current = reader.read();
1135: skipSpaces();
1136: if (current != '(') {
1137: reportCharacterExpectedError('(', current);
1138: skipTransform();
1139: return;
1140: }
1141: current = reader.read();
1142: skipSpaces();
1143:
1144: float sk = parseFloat();
1145:
1146: skipSpaces();
1147: if (current != ')') {
1148: reportCharacterExpectedError(')', current);
1149: skipTransform();
1150: return;
1151: }
1152:
1153: if (skewX) {
1154: fragmentIdentifierHandler.skewX(sk);
1155: } else {
1156: fragmentIdentifierHandler.skewY(sk);
1157: }
1158: }
1159:
1160: /**
1161: * Skips characters in the given reader until a ')' is encountered.
1162: */
1163: protected void skipTransform() throws IOException {
1164: loop: for (;;) {
1165: current = reader.read();
1166: switch (current) {
1167: case ')':
1168: break loop;
1169: default:
1170: if (current == -1) {
1171: break loop;
1172: }
1173: }
1174: }
1175: }
1176:
1177: /**
1178: * Parses a PreserveAspectRatio attribute.
1179: */
1180: protected void parsePreserveAspectRatio() throws ParseException,
1181: IOException {
1182: fragmentIdentifierHandler.startPreserveAspectRatio();
1183:
1184: align: switch (current) {
1185: case 'n':
1186: current = reader.read();
1187: if (current != 'o') {
1188: reportCharacterExpectedError('o', current);
1189: skipIdentifier();
1190: break align;
1191: }
1192: current = reader.read();
1193: if (current != 'n') {
1194: reportCharacterExpectedError('n', current);
1195: skipIdentifier();
1196: break align;
1197: }
1198: current = reader.read();
1199: if (current != 'e') {
1200: reportCharacterExpectedError('e', current);
1201: skipIdentifier();
1202: break align;
1203: }
1204: current = reader.read();
1205: skipSpaces();
1206: fragmentIdentifierHandler.none();
1207: break;
1208:
1209: case 'x':
1210: current = reader.read();
1211: if (current != 'M') {
1212: reportCharacterExpectedError('M', current);
1213: skipIdentifier();
1214: break;
1215: }
1216: current = reader.read();
1217: switch (current) {
1218: case 'a':
1219: current = reader.read();
1220: if (current != 'x') {
1221: reportCharacterExpectedError('x', current);
1222: skipIdentifier();
1223: break align;
1224: }
1225: current = reader.read();
1226: if (current != 'Y') {
1227: reportCharacterExpectedError('Y', current);
1228: skipIdentifier();
1229: break align;
1230: }
1231: current = reader.read();
1232: if (current != 'M') {
1233: reportCharacterExpectedError('M', current);
1234: skipIdentifier();
1235: break align;
1236: }
1237: current = reader.read();
1238: switch (current) {
1239: case 'a':
1240: current = reader.read();
1241: if (current != 'x') {
1242: reportCharacterExpectedError('x', current);
1243: skipIdentifier();
1244: break align;
1245: }
1246: fragmentIdentifierHandler.xMaxYMax();
1247: current = reader.read();
1248: break;
1249: case 'i':
1250: current = reader.read();
1251: switch (current) {
1252: case 'd':
1253: fragmentIdentifierHandler.xMaxYMid();
1254: current = reader.read();
1255: break;
1256: case 'n':
1257: fragmentIdentifierHandler.xMaxYMin();
1258: current = reader.read();
1259: break;
1260: default:
1261: reportUnexpectedCharacterError(current);
1262: skipIdentifier();
1263: break align;
1264: }
1265: }
1266: break;
1267: case 'i':
1268: current = reader.read();
1269: switch (current) {
1270: case 'd':
1271: current = reader.read();
1272: if (current != 'Y') {
1273: reportCharacterExpectedError('Y', current);
1274: skipIdentifier();
1275: break align;
1276: }
1277: current = reader.read();
1278: if (current != 'M') {
1279: reportCharacterExpectedError('M', current);
1280: skipIdentifier();
1281: break align;
1282: }
1283: current = reader.read();
1284: switch (current) {
1285: case 'a':
1286: current = reader.read();
1287: if (current != 'x') {
1288: reportCharacterExpectedError('x', current);
1289: skipIdentifier();
1290: break align;
1291: }
1292: fragmentIdentifierHandler.xMidYMax();
1293: current = reader.read();
1294: break;
1295: case 'i':
1296: current = reader.read();
1297: switch (current) {
1298: case 'd':
1299: fragmentIdentifierHandler.xMidYMid();
1300: current = reader.read();
1301: break;
1302: case 'n':
1303: fragmentIdentifierHandler.xMidYMin();
1304: current = reader.read();
1305: break;
1306: default:
1307: reportUnexpectedCharacterError(current);
1308: skipIdentifier();
1309: break align;
1310: }
1311: }
1312: break;
1313: case 'n':
1314: current = reader.read();
1315: if (current != 'Y') {
1316: reportCharacterExpectedError('Y', current);
1317: skipIdentifier();
1318: break align;
1319: }
1320: current = reader.read();
1321: if (current != 'M') {
1322: reportCharacterExpectedError('M', current);
1323: skipIdentifier();
1324: break align;
1325: }
1326: current = reader.read();
1327: switch (current) {
1328: case 'a':
1329: current = reader.read();
1330: if (current != 'x') {
1331: reportCharacterExpectedError('x', current);
1332: skipIdentifier();
1333: break align;
1334: }
1335: fragmentIdentifierHandler.xMinYMax();
1336: current = reader.read();
1337: break;
1338: case 'i':
1339: current = reader.read();
1340: switch (current) {
1341: case 'd':
1342: fragmentIdentifierHandler.xMinYMid();
1343: current = reader.read();
1344: break;
1345: case 'n':
1346: fragmentIdentifierHandler.xMinYMin();
1347: current = reader.read();
1348: break;
1349: default:
1350: reportUnexpectedCharacterError(current);
1351: skipIdentifier();
1352: break align;
1353: }
1354: }
1355: break;
1356: default:
1357: reportUnexpectedCharacterError(current);
1358: skipIdentifier();
1359: break align;
1360: }
1361: break;
1362: default:
1363: reportUnexpectedCharacterError(current);
1364: skipIdentifier();
1365: }
1366: break;
1367: default:
1368: if (current != -1) {
1369: reportUnexpectedCharacterError(current);
1370: skipIdentifier();
1371: }
1372: }
1373:
1374: skipCommaSpaces();
1375:
1376: switch (current) {
1377: case 'm':
1378: current = reader.read();
1379: if (current != 'e') {
1380: reportCharacterExpectedError('e', current);
1381: skipIdentifier();
1382: break;
1383: }
1384: current = reader.read();
1385: if (current != 'e') {
1386: reportCharacterExpectedError('e', current);
1387: skipIdentifier();
1388: break;
1389: }
1390: current = reader.read();
1391: if (current != 't') {
1392: reportCharacterExpectedError('t', current);
1393: skipIdentifier();
1394: break;
1395: }
1396: fragmentIdentifierHandler.meet();
1397: current = reader.read();
1398: break;
1399: case 's':
1400: current = reader.read();
1401: if (current != 'l') {
1402: reportCharacterExpectedError('l', current);
1403: skipIdentifier();
1404: break;
1405: }
1406: current = reader.read();
1407: if (current != 'i') {
1408: reportCharacterExpectedError('i', current);
1409: skipIdentifier();
1410: break;
1411: }
1412: current = reader.read();
1413: if (current != 'c') {
1414: reportCharacterExpectedError('c', current);
1415: skipIdentifier();
1416: break;
1417: }
1418: current = reader.read();
1419: if (current != 'e') {
1420: reportCharacterExpectedError('e', current);
1421: skipIdentifier();
1422: break;
1423: }
1424: fragmentIdentifierHandler.slice();
1425: current = reader.read();
1426: }
1427:
1428: fragmentIdentifierHandler.endPreserveAspectRatio();
1429: }
1430:
1431: /**
1432: * Skips characters in the given reader until a white space is encountered.
1433: */
1434: protected void skipIdentifier() throws IOException {
1435: loop: for (;;) {
1436: current = reader.read();
1437: switch (current) {
1438: case 0xD:
1439: case 0xA:
1440: case 0x20:
1441: case 0x9:
1442: current = reader.read();
1443: case -1:
1444: break loop;
1445: }
1446: }
1447: }
1448:
1449: }
|