001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: /*
042: * SVGAnimationRasterizer.java
043: *
044: * Created on November 30, 2005, 10:53 AM
045: */
046:
047: package org.netbeans.modules.mobility.svgcore.export;
048:
049: import com.sun.perseus.j2d.Box;
050: import com.sun.perseus.j2d.Transform;
051: import com.sun.perseus.model.ModelNode;
052: import com.sun.perseus.util.SVGConstants;
053: import java.awt.Dimension;
054: import java.awt.Rectangle;
055: import java.io.IOException;
056: import javax.microedition.m2g.SVGImage;
057: import javax.swing.ComboBoxModel;
058: import javax.swing.DefaultComboBoxModel;
059: import javax.swing.JComboBox;
060: import javax.swing.JComponent;
061: import javax.swing.JPanel;
062: import javax.swing.JSlider;
063: import javax.swing.JSpinner;
064: import javax.swing.SpinnerNumberModel;
065: import javax.swing.SwingUtilities;
066: import javax.swing.text.BadLocationException;
067: import org.netbeans.api.project.FileOwnerQuery;
068: import org.netbeans.api.project.Project;
069: import org.netbeans.modules.mobility.project.J2MEProject;
070: import org.netbeans.modules.mobility.svgcore.SVGDataObject;
071: import org.netbeans.modules.mobility.svgcore.composer.PerseusController;
072: import org.netbeans.modules.mobility.svgcore.composer.SVGObjectOutline;
073: import org.netbeans.modules.mobility.svgcore.composer.SceneManager;
074: import org.netbeans.modules.mobility.svgcore.export.ComponentGroup.ComponentWrapper;
075: import org.openide.filesystems.FileObject;
076: import org.w3c.dom.svg.SVGElement;
077: import org.w3c.dom.svg.SVGLocatableElement;
078: import org.w3c.dom.svg.SVGMatrix;
079: import org.w3c.dom.svg.SVGRect;
080: import org.w3c.dom.svg.SVGSVGElement;
081:
082: /**
083: *
084: * @author Pavel Benes
085: */
086: public abstract class SVGRasterizerPanel extends JPanel implements
087: AnimationRasterizer.Params {
088: protected final SVGDataObject m_dObj;
089: protected final String m_elementId;
090: protected final J2MEProject m_project;
091: protected final Dimension m_dim;
092: protected double m_ratio;
093: protected int m_overrideWidth = -1;
094: protected int m_overrideHeight = -1;
095: protected volatile boolean m_updateInProgress = false;
096: protected volatile SVGImage m_svgImage;
097: private SVGLocatableElement m_exportedElement = null;
098:
099: protected class SVGRasterizerComponentGroup extends ComponentGroup {
100: public SVGRasterizerComponentGroup(Object... comps) {
101: super (comps);
102: }
103:
104: public void refresh(JComponent source) {
105: updateImage(source, true);
106: }
107: };
108:
109: protected SVGRasterizerPanel(SVGDataObject dObj, String elementId)
110: throws IOException, BadLocationException {
111: m_dObj = dObj;
112: m_elementId = elementId;
113:
114: FileObject primaryFile = m_dObj.getPrimaryFile();
115:
116: Project p = FileOwnerQuery.getOwner(primaryFile);
117: if (p != null && p instanceof J2MEProject) {
118: m_project = (J2MEProject) p;
119: } else {
120: m_project = null;
121: }
122:
123: if (m_elementId == null && isInProject()) {
124: m_dim = ScreenSizeHelper.getCurrentDeviceScreenSize(
125: primaryFile, null);
126: } else {
127: getSVGImage();
128: m_dim = new Dimension(m_svgImage.getViewportWidth(),
129: m_svgImage.getViewportHeight());
130: }
131: }
132:
133: protected ComponentGroup createTimeGroup(JSpinner spinner,
134: final JSlider slider, boolean isStart) {
135: final float duration = m_dObj.getSceneManager()
136: .getAnimationDuration();
137: int p = Math.round(duration * 100);
138: slider.setMinimum(0);
139: slider.setMaximum(p);
140: ComponentWrapper sliderWrapper;
141:
142: if (!isStart) {
143: slider.setInverted(true);
144: sliderWrapper = new ComponentGroup.SliderWrapper(slider) {
145: public float getValue() {
146: return duration - super .getValue();
147: }
148:
149: public void setValue(float value) {
150: super .setValue(duration - value);
151: }
152: };
153: } else {
154: sliderWrapper = ComponentWrapper.wrap(slider);
155: }
156:
157: final SpinnerNumberModel model = new SpinnerNumberModel(
158: (double) (isStart ? 0 : duration), 0.0, duration, 1.0);
159: spinner.setModel(model);
160: return new SVGRasterizerComponentGroup(spinner, sliderWrapper);
161: }
162:
163: protected ComponentGroup createCompressionGroup(JComboBox combo,
164: JSpinner spinner) {
165: spinner.setModel(new SpinnerNumberModel(0, 0, 99, 1));
166: AnimationRasterizer.CompressionLevel defLevel = AnimationRasterizer.CompressionLevel.HIGH;
167: spinner.setValue(new Integer(defLevel.getRate()));
168: combo.setSelectedItem(defLevel);
169:
170: return new SVGRasterizerComponentGroup(
171: createComboWrapper(combo), spinner);
172: }
173:
174: protected final boolean isInProject() {
175: return m_project != null;
176: }
177:
178: protected ComponentGroup.ComponentWrapper createComboWrapper(
179: JComboBox combo) {
180: return new ComponentGroup.ComponentWrapper(combo) {
181: public float getValue() {
182: Object obj = ((JComboBox) m_delegate).getSelectedItem();
183: return ((AnimationRasterizer.CompressionLevel) obj)
184: .getRate();
185: }
186:
187: public void setValue(float value) {
188: int q = Math.round(value);
189: ((JComboBox) m_delegate)
190: .setSelectedItem(AnimationRasterizer.CompressionLevel
191: .getLevel(q));
192: }
193: };
194: }
195:
196: protected static float roundTime(float f) {
197: return Math.round(f * 100) / 100.0f;
198: }
199:
200: public final void setImageWidth(int w) {
201: m_overrideWidth = w;
202: }
203:
204: public final void setImageHeight(int h) {
205: m_overrideHeight = h;
206: }
207:
208: public float getEndTime() {
209: return 0;
210: }
211:
212: public float getFramesPerSecond() {
213: return 1;
214: }
215:
216: public double getRatio() {
217: return m_ratio;
218: }
219:
220: private void loadSVGImage() {
221: try {
222: m_svgImage = m_dObj.getModel().parseSVGImage();
223: } catch (Exception ex) {
224: SceneManager.error("Load of SVG image failed", ex); //NOI18N
225: }
226: }
227:
228: public final synchronized SVGImage getSVGImage()
229: throws IOException, BadLocationException {
230: if (m_svgImage == null) {
231: //TODO Revisit, update of the model will probably cause deadlock
232: if (SwingUtilities.isEventDispatchThread()) {
233: Thread th = new Thread() {
234: public void run() {
235: loadSVGImage();
236: }
237: };
238: th.start();
239: try {
240: th.join();
241: } catch (InterruptedException e) {
242: }
243: } else {
244: loadSVGImage();
245: }
246: assert m_svgImage != null;
247:
248: if (m_elementId != null) {
249: SVGSVGElement svg = (SVGSVGElement) m_svgImage
250: .getDocument().getDocumentElement();
251: SVGElement elem = PerseusController.hideAllButSubtree(
252: (ModelNode) svg, m_elementId);
253: if (elem != null && elem instanceof SVGLocatableElement) {
254: m_exportedElement = (SVGLocatableElement) elem;
255: SVGRect bBox = m_exportedElement.getBBox();
256: SVGMatrix screenCTM = m_exportedElement
257: .getScreenCTM();
258: float[][] coords = SVGObjectOutline
259: .transformRectangle(bBox,
260: (Transform) screenCTM,
261: new float[4][2]);
262: Rectangle rect1 = SVGObjectOutline
263: .getShapeBoundingBox(coords);
264:
265: // svg -> screen
266: SVGMatrix svgCTM = svg.getScreenCTM();
267:
268: // element -> svg -> screen
269: SVGMatrix eltCTM = m_exportedElement.getScreenCTM();
270:
271: // screen -> svg
272: SVGMatrix svgICTM = svgCTM.inverse();
273:
274: // elt-> svg matrix
275: SVGMatrix eltToSvg = svgICTM.mMultiply(eltCTM);
276:
277: coords = SVGObjectOutline.transformRectangle(
278: m_exportedElement.getBBox(),
279: (Transform) eltToSvg, new float[4][2]);
280: Rectangle rect2 = SVGObjectOutline
281: .getShapeBoundingBox(coords);
282:
283: bBox = new Box(rect2.x - 1, rect2.y - 1,
284: rect2.width + 2, rect2.height + 2);
285:
286: svg.setRectTrait(
287: SVGConstants.SVG_VIEW_BOX_ATTRIBUTE, bBox);
288: m_svgImage.setViewportWidth(Math.round(bBox
289: .getWidth()));
290: m_svgImage.setViewportHeight(Math.round(bBox
291: .getHeight()));
292: }
293: }
294: }
295: return m_svgImage;
296: }
297:
298: public final J2MEProject getProject() {
299: return m_project;
300: }
301:
302: public final String getElementId() {
303: return m_elementId;
304: }
305:
306: protected static ComboBoxModel createImageTypeComboBoxModel() {
307: ComboBoxModel model = new DefaultComboBoxModel(
308: AnimationRasterizer.ImageType.values());
309: return model;
310: }
311:
312: protected abstract void updateImage(JComponent source,
313: boolean isOutputChanged);
314: }
|