[Libreoffice-commits] .: filter/source
Thorsten Behrens
thorsten at kemper.freedesktop.org
Sun Sep 4 03:47:12 PDT 2011
filter/source/svg/js2hxx.py | 163
filter/source/svg/makefile.mk | 4
filter/source/svg/presentation_engine.js | 8320 +++++++++++++++++++++++++++++++
filter/source/svg/svgscript.hxx | 7465 ---------------------------
4 files changed, 8487 insertions(+), 7465 deletions(-)
New commits:
commit 66f05b5d5acc43e4615bc19045d3600ed93e328b
Author: Marco <mrcekets at gmail.com>
Date: Sun Sep 4 12:32:46 2011 +0200
Bin generated svgscript.hxx, add original file.
Removes the old auto-generated svgscript, and instead
generate it from the true source.
diff --git a/filter/source/svg/js2hxx.py b/filter/source/svg/js2hxx.py
new file mode 100755
index 0000000..0967dd6
--- /dev/null
+++ b/filter/source/svg/js2hxx.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+#
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# Major Contributor(s):
+# Copyright (C) 2011 Marco Cecchetti <mrcekets at gmail.com>
+#
+# All Rights Reserved.
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+#
+
+import os, sys
+
+MAX_LINES = 200
+VARIABLE_NAME = 'aSVGScript'
+
+def get_var_decl(n):
+ return 'static const char %s%d[] =' % ( VARIABLE_NAME, n )
+
+script_name = os.path.basename( sys.argv[0] )
+infile_name = sys.argv[1]
+outfile_name = sys.argv[2]
+
+
+# collect input JavaScript file lines
+if( not os.path.isfile( infile_name ) ):
+ print '%s: error: file "%s" not found' % ( script_name, infile_name )
+ sys.exit( -1 )
+
+infile = open( infile_name, 'r' )
+in_lines = [line.rstrip() for line in infile.readlines()]
+infile.close()
+
+
+valid_lines=[]
+is_multiline_comment = False
+lineNumber = 0
+emptyLineCount = 0
+for line in in_lines:
+ lineNumber += 1
+ index = line.find('"')
+ if( index != -1 ):
+ print '%s: warning: processed file contains \'"\' at %d:%d' % ( script_name, lineNumber, index )
+
+ sline = line.strip()
+
+ # strip comment lines except multilines comments that begins with one '/' and exactly 5 '*'
+ if( is_multiline_comment and sline.endswith( '*/' ) ):
+ is_multiline_comment = False
+ continue
+
+ if( is_multiline_comment ):
+ continue
+
+ if( sline.startswith( '//' ) ):
+ continue
+
+ if( sline.startswith( '/*' ) and sline.endswith( '*/' ) ):
+ continue
+
+ if( ( sline.startswith( '/*' ) and not sline.startswith( '/*****' ) )
+ or sline.startswith( '/******' ) ):
+ is_multiline_comment = True
+ continue
+
+ # append a 4 spaces indentation to each line
+ escaped_line = ' %s' % line
+ escaped_line = escaped_line.rstrip()
+
+ # no more than 2 consecutive empty lines
+ if( escaped_line == '' ):
+ emptyLineCount += 1
+ else:
+ emptyLineCount = 0
+
+ if( emptyLineCount > 2 ):
+ continue
+
+ # append to some escape sequence another '\'
+ escaped_line = escaped_line.replace( '\\', '\\\\' )
+ escaped_line = escaped_line.replace( '\n', '\\n')
+ escaped_line = escaped_line.replace( '\t', '\\t' )
+
+ valid_lines.append( escaped_line )
+
+
+# compute the number of needed fragments that is of C constant strings
+total_valid_lines = len (valid_lines) + 2
+total_fragments = total_valid_lines / MAX_LINES
+if( ( total_valid_lines % MAX_LINES ) != 0 ):
+ total_fragments += 1
+
+
+
+out_lines = []
+out_lines.append( '' )
+out_lines.append( '#define N_SVGSCRIPT_FRAGMENTS %d' % total_fragments )
+out_lines.append( '' )
+out_lines.append( get_var_decl( 0 ) )
+out_lines.append( '"<![CDATA[\\n\\' )
+i = 2
+fragment = 0
+for line in valid_lines:
+ out_lines.append( line + '\\n\\' )
+ if( i == MAX_LINES ):
+ i = 0
+ fragment += 1
+ out_lines.append( '";' )
+ out_lines.append( '' )
+ out_lines.append( get_var_decl( fragment ) )
+ out_lines.append( '"\\' )
+ i += 1
+
+out_lines.append( ']]>";' )
+out_lines.append( '' )
+
+
+outfile = open( outfile_name, 'w' )
+if( not os.path.isfile( outfile_name ) ):
+ print '%s: error: I cannot create file "%s"' % ( script_name, outfile_name )
+ sys.exit( -1 )
+
+
+# C++ header
+header_info = """
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* !! This file is auto-generated, do not edit !! */
+"""
+
+vim_setup = '/* vim:set shiftwidth=4 softtabstop=4 expandtab: */'
+
+outfile.write( header_info +'\n' )
+outfile.write( '\n' )
+
+for line in out_lines:
+ outfile.write( line + '\n' )
+
+outfile.write( '\n' )
+outfile.write( '\n' )
+outfile.write( vim_setup + '\n' )
+
+outfile.close()
+
+
+
diff --git a/filter/source/svg/makefile.mk b/filter/source/svg/makefile.mk
index 425eae9..b76db4d 100644
--- a/filter/source/svg/makefile.mk
+++ b/filter/source/svg/makefile.mk
@@ -108,6 +108,10 @@ $(INCCOM)$/tokens.cxx : $(MISC)$/tokens.gperf makefile.mk
ALLTAR : $(MISC)/svgfilter.component
+$(INCCOM)$/svgscript.hxx : presentation_engine.js js2hxx.py
+ js2hxx.py presentation_engine.js $@
+$(SLO)$/svgexport.obj : svgexport.cxx $(INCCOM)$/svgscript.hxx
+
$(MISC)/svgfilter.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \
svgfilter.component
$(XSLTPROC) --nonet --stringparam uri \
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
new file mode 100644
index 0000000..aa2835a
--- /dev/null
+++ b/filter/source/svg/presentation_engine.js
@@ -0,0 +1,8320 @@
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * - Presentation Engine - *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
+
+/**
+ * WARNING: any comment that should not be striped out by the script
+ * generating the C++ header file must starts with a '/' and exactly 5 '*'
+ * not striped examples: '/*****', '/***** *'
+ * striped examples: '/** ***' (not contiguous), '/******' (more than 5)
+ */
+
+
+
+/*****
+ * @licstart
+ *
+ * The following is the license notice for the part of JavaScript code of this
+ * page included between the '@jessyinkstart' and the '@jessyinkend' notes.
+ */
+
+/***** ******************************************************************
+ *
+ * Copyright 2008, 2009 Hannes Hochreiner
+ *
+ * The JavaScript code included between the start note '@jessyinkstart'
+ * and the end note '@jessyinkend' is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GNU GPL) as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option)
+ * any later version. The code is distributed WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
+ *
+ * As additional permission under GNU GPL version 3 section 7, you
+ * may distribute non-source (e.g., minimized or compacted) forms of
+ * that code without the copy of the GNU GPL normally required by
+ * section 4, provided you include this license notice and a URL
+ * through which recipients can access the Corresponding Source.
+ *
+ *************************************************************************/
+
+/*****
+ * You can find the complete source code of the JessyInk project at:
+ * @source http://code.google.com/p/jessyink/
+ */
+
+/*****
+ * @licend
+ *
+ * The above is the license notice for the part of JavaScript code of this
+ * page included between the '@jessyinkstart' and the '@jessyinkend' notes.
+ */
+
+
+
+/*****
+ * @jessyinkstart
+ *
+ * The following code is a derivative work of some parts of the JessyInk
+ * project.
+ * @source http://code.google.com/p/jessyink/
+ */
+
+
+/** Convenience function to get an element depending on whether it has a
+ * property with a particular name.
+ *
+ * @param node: element of the document
+ * @param name: attribute name
+ *
+ * @returns an array containing all the elements of the tree with root
+ * 'node' that own the property 'name'
+ */
+function getElementsByProperty( node, name )
+{
+ var elems = new Array();
+
+ if( node.getAttribute( name ) )
+ elems.push( node );
+
+ for( var counter = 0; counter < node.childNodes.length; ++counter )
+ {
+ if( node.childNodes[counter].nodeType == 1 )
+ {
+ var subElems = getElementsByProperty( node.childNodes[counter], name );
+ elems = elems.concat( subElems );
+ }
+ }
+ return elems;
+}
+
+/** Event handler for key press.
+ *
+ * @param aEvt the event
+ */
+function onKeyDown( aEvt )
+{
+ if ( !aEvt )
+ aEvt = window.event;
+
+ code = aEvt.keyCode || aEvt.charCode;
+
+ if ( !processingEffect && keyCodeDictionary[currentMode] && keyCodeDictionary[currentMode][code] )
+ return keyCodeDictionary[currentMode][code]();
+ else
+ document.onkeypress = onKeyPress;
+}
+//Set event handler for key down.
+document.onkeydown = onKeyDown;
+
+/** Event handler for key press.
+ *
+ * @param aEvt the event
+ */
+function onKeyPress( aEvt )
+{
+ document.onkeypress = null;
+
+ if ( !aEvt )
+ aEvt = window.event;
+
+ str = String.fromCharCode( aEvt.keyCode || aEvt.charCode );
+
+ if ( !processingEffect && charCodeDictionary[currentMode] && charCodeDictionary[currentMode][str] )
+ return charCodeDictionary[currentMode][str]();
+}
+
+/** Function to supply the default key code dictionary.
+ *
+ * @returns default key code dictionary
+ */
+function getDefaultKeyCodeDictionary()
+{
+ var keyCodeDict = new Object();
+
+ keyCodeDict[SLIDE_MODE] = new Object();
+ keyCodeDict[INDEX_MODE] = new Object();
+
+ // slide mode
+ keyCodeDict[SLIDE_MODE][LEFT_KEY]
+ = function() { return dispatchEffects(-1); };
+ keyCodeDict[SLIDE_MODE][RIGHT_KEY]
+ = function() { return dispatchEffects(1); };
+ keyCodeDict[SLIDE_MODE][UP_KEY]
+ = function() { return skipEffects(-1); };
+ keyCodeDict[SLIDE_MODE][DOWN_KEY]
+ = function() { return skipEffects(1); };
+ keyCodeDict[SLIDE_MODE][PAGE_UP_KEY]
+ = function() { return switchSlide( -1, true ); };
+ keyCodeDict[SLIDE_MODE][PAGE_DOWN_KEY]
+ = function() { return switchSlide( 1, true ); };
+ keyCodeDict[SLIDE_MODE][HOME_KEY]
+ = function() { return aSlideShow.displaySlide( 0, true ); };
+ keyCodeDict[SLIDE_MODE][END_KEY]
+ = function() { return aSlideShow.displaySlide( theMetaDoc.nNumberOfSlides - 1, true ); };
+ keyCodeDict[SLIDE_MODE][SPACE_KEY]
+ = function() { return dispatchEffects(1); };
+
+ // index mode
+ keyCodeDict[INDEX_MODE][LEFT_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex - 1 ); };
+ keyCodeDict[INDEX_MODE][RIGHT_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex + 1 ); };
+ keyCodeDict[INDEX_MODE][UP_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex - theSlideIndexPage.indexColumns ); };
+ keyCodeDict[INDEX_MODE][DOWN_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex + theSlideIndexPage.indexColumns ); };
+ keyCodeDict[INDEX_MODE][PAGE_UP_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex - theSlideIndexPage.getTotalThumbnails() ); };
+ keyCodeDict[INDEX_MODE][PAGE_DOWN_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex + theSlideIndexPage.getTotalThumbnails() ); };
+ keyCodeDict[INDEX_MODE][HOME_KEY]
+ = function() { return indexSetPageSlide( 0 ); };
+ keyCodeDict[INDEX_MODE][END_KEY]
+ = function() { return indexSetPageSlide( theMetaDoc.nNumberOfSlides - 1 ); };
+ keyCodeDict[INDEX_MODE][ENTER_KEY]
+ = function() { return toggleSlideIndex(); };
+ keyCodeDict[INDEX_MODE][SPACE_KEY]
+ = function() { return toggleSlideIndex(); };
+ keyCodeDict[INDEX_MODE][ESCAPE_KEY]
+ = function() { return abandonIndexMode(); };
+
+ return keyCodeDict;
+}
+
+/** Function to supply the default char code dictionary.
+ *
+ * @returns default char code dictionary
+ */
+function getDefaultCharCodeDictionary()
+{
+ var charCodeDict = new Object();
+
+ charCodeDict[SLIDE_MODE] = new Object();
+ charCodeDict[INDEX_MODE] = new Object();
+
+ // slide mode
+ charCodeDict[SLIDE_MODE]['i']
+ = function () { return toggleSlideIndex(); };
+
+ // index mode
+ charCodeDict[INDEX_MODE]['i']
+ = function () { return toggleSlideIndex(); };
+ charCodeDict[INDEX_MODE]['-']
+ = function () { return theSlideIndexPage.decreaseNumberOfColumns(); };
+ charCodeDict[INDEX_MODE]['=']
+ = function () { return theSlideIndexPage.increaseNumberOfColumns(); };
+ charCodeDict[INDEX_MODE]['+']
+ = function () { return theSlideIndexPage.increaseNumberOfColumns(); };
+ charCodeDict[INDEX_MODE]['0']
+ = function () { return theSlideIndexPage.resetNumberOfColumns(); };
+
+ return charCodeDict;
+}
+
+
+function slideOnMouseDown( aEvt )
+{
+ if (!aEvt)
+ aEvt = window.event;
+
+ var nOffset = 0;
+
+ if( aEvt.button == 0 )
+ nOffset = 1;
+ else if( aEvt.button == 2 )
+ nOffset = -1;
+
+ if( 0 != nOffset )
+ dispatchEffects( nOffset );
+}
+
+/** Event handler for mouse wheel events in slide mode.
+ * based on http://adomas.org/javascript-mouse-wheel/
+ *
+ * @param aEvt the event
+ */
+function slideOnMouseWheel(aEvt)
+{
+ var delta = 0;
+
+ if (!aEvt)
+ aEvt = window.event;
+
+ if (aEvt.wheelDelta)
+ { // IE Opera
+ delta = aEvt.wheelDelta/120;
+ }
+ else if (aEvt.detail)
+ { // MOZ
+ delta = -aEvt.detail/3;
+ }
+
+ if (delta > 0)
+ skipEffects(-1);
+ else if (delta < 0)
+ skipEffects(1);
+
+ if (aEvt.preventDefault)
+ aEvt.preventDefault();
+
+ aEvt.returnValue = false;
+}
+
+//Mozilla
+if( window.addEventListener )
+{
+ window.addEventListener( 'DOMMouseScroll', function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_WHEEL ); }, false );
+}
+
+//Opera Safari OK - may not work in IE
+window.onmousewheel
+ = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_WHEEL ); };
+
+/** Function to handle all mouse events.
+ *
+ * @param aEvt event
+ * @param anAction type of event (e.g. mouse up, mouse wheel)
+ */
+function mouseHandlerDispatch( aEvt, anAction )
+{
+ if( !aEvt )
+ aEvt = window.event;
+
+ var retVal = true;
+
+ if ( mouseHandlerDictionary[currentMode] && mouseHandlerDictionary[currentMode][anAction] )
+ {
+ var subRetVal = mouseHandlerDictionary[currentMode][anAction]( aEvt );
+
+ if( subRetVal != null && subRetVal != undefined )
+ retVal = subRetVal;
+ }
+
+ if( aEvt.preventDefault && !retVal )
+ aEvt.preventDefault();
+
+ aEvt.returnValue = retVal;
+
+ return retVal;
+}
+
+//Set mouse event handler.
+document.onmousedown = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_DOWN ); };
+//document.onmousemove = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_MOVE ); };
+
+/** Function to supply the default mouse handler dictionary.
+ *
+ * @returns default mouse handler dictionary
+ */
+function getDefaultMouseHandlerDictionary()
+{
+ var mouseHandlerDict = new Object();
+
+ mouseHandlerDict[SLIDE_MODE] = new Object();
+ mouseHandlerDict[INDEX_MODE] = new Object();
+
+ // slide mode
+ mouseHandlerDict[SLIDE_MODE][MOUSE_DOWN]
+ = function( aEvt ) { return slideOnMouseDown( aEvt ); };
+ mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL]
+ = function( aEvt ) { return slideOnMouseWheel( aEvt ); };
+
+ // index mode
+ mouseHandlerDict[INDEX_MODE][MOUSE_DOWN]
+ = function( aEvt ) { return toggleSlideIndex(); };
+
+ return mouseHandlerDict;
+}
+
+/** Function to set the page and active slide in index view.
+*
+* @param nIndex index of the active slide
+*
+* NOTE: To force a redraw,
+* set INDEX_OFFSET to -1 before calling indexSetPageSlide().
+*
+* This is necessary for zooming (otherwise the index might not
+* get redrawn) and when switching to index mode.
+*
+* INDEX_OFFSET = -1
+* indexSetPageSlide(activeSlide);
+*/
+function indexSetPageSlide( nIndex )
+{
+ var aMetaSlideSet = theMetaDoc.aMetaSlideSet;
+ nIndex = getSafeIndex( nIndex, 0, aMetaSlideSet.length - 1 );
+
+ //calculate the offset
+ var nSelectedThumbnailIndex = nIndex % theSlideIndexPage.getTotalThumbnails();
+ var offset = nIndex - nSelectedThumbnailIndex;
+
+ if( offset < 0 )
+ offset = 0;
+
+ //if different from kept offset, then record and change the page
+ if( offset != INDEX_OFFSET )
+ {
+ INDEX_OFFSET = offset;
+ displayIndex( INDEX_OFFSET );
+ }
+
+ //set the selected thumbnail and the current slide
+ theSlideIndexPage.setSelection( nSelectedThumbnailIndex );
+}
+
+
+/*****
+ * @jessyinkend
+ *
+ * The above code is a derivative work of some parts of the JessyInk project.
+ * @source http://code.google.com/p/jessyink/
+ */
+
+
+
+
+
+/*****
+ * @licstart
+ *
+ * The following is the license notice for the part of JavaScript code of this
+ * page included between the '@stdlibstart' and the '@stdlibend' notes.
+ */
+
+/***** ******************************************************************
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Free Software Foundation, Inc.
+ *
+ * The code included between the start note '@stdlibstart' and the end
+ * note '@stdlibend' is a derivative work of the GNU ISO C++ Library.
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Under Section 7 of GPL version 3, you are granted additional
+ * permissions described in the GCC Runtime Library Exception, version
+ * 3.1, as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License and
+ * a copy of the GCC Runtime Library Exception along with this program;
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************/
+
+/*****
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided 'as is' without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation. Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided 'as is' without express or implied warranty.
+ *
+ ************************************************************************/
+
+/*****
+ * @licend
+ *
+ * The above is the license notice for the part of JavaScript code of this
+ * page included between the '@stdlibstart' and the '@stdlibend' notes.
+ */
+
+
+
+/*****
+ * @stdlibstart
+ *
+ * The following code is a porting, performed on August 2011, of a part of
+ * the C++ code included into the source file stl_queue.h that is part of
+ * the GNU ISO C++ Library.
+ */
+
+
+function PriorityQueue( aCompareFunc )
+{
+ this.aSequence = new Array();
+ this.aCompareFunc = aCompareFunc;
+}
+
+PriorityQueue.prototype.top = function()
+{
+ return this.aSequence[0];
+};
+
+PriorityQueue.prototype.isEmpty = function()
+{
+ return ( this.size() === 0 );
+};
+
+PriorityQueue.prototype.size = function()
+{
+ return this.aSequence.length;
+};
+
+PriorityQueue.prototype.push = function( aValue )
+{
+ this.implPushHeap( 0, this.aSequence.length, 0, aValue );
+};
+
+PriorityQueue.prototype.clear = function()
+{
+ return this.aSequence = new Array();
+};
+
+
+PriorityQueue.prototype.pop = function()
+{
+ if( this.isEmpty() )
+ return;
+
+ var nLast = this.aSequence.length - 1;
+ var aValue = this.aSequence[ nLast ];
+ this.aSequence[ nLast ] = this.aSequence[ 0 ];
+ this.implAdjustHeap( 0, 0, nLast, aValue );
+ this.aSequence.pop();
+};
+
+PriorityQueue.prototype.implAdjustHeap = function( nFirst, nHoleIndex, nLength, aValue )
+{
+ var nTopIndex = nHoleIndex;
+ var nSecondChild = nHoleIndex;
+
+ while( nSecondChild < Math.floor( ( nLength - 1 ) / 2 ) )
+ {
+ nSecondChild = 2 * ( nSecondChild + 1 );
+ if( this.aCompareFunc( this.aSequence[ nFirst + nSecondChild ],
+ this.aSequence[ nFirst + nSecondChild - 1] ) )
+ {
+ --nSecondChild;
+ }
+ this.aSequence[ nFirst + nHoleIndex ] = this.aSequence[ nFirst + nSecondChild ];
+ nHoleIndex = nSecondChild;
+ }
+
+ if( ( ( nLength & 1 ) === 0 ) && ( nSecondChild === Math.floor( ( nLength - 2 ) / 2 ) ) )
+ {
+ nSecondChild = 2 * ( nSecondChild + 1 );
+ this.aSequence[ nFirst + nHoleIndex ] = this.aSequence[ nFirst + nSecondChild - 1];
+ nHoleIndex = nSecondChild - 1;
+ }
+
+ this.implPushHeap( nFirst, nHoleIndex, nTopIndex, aValue );
+};
+
+PriorityQueue.prototype.implPushHeap = function( nFirst, nHoleIndex, nTopIndex, aValue )
+{
+ var nParent = Math.floor( ( nHoleIndex - 1 ) / 2 );
+
+ while( ( nHoleIndex > nTopIndex ) &&
+ this.aCompareFunc( this.aSequence[ nFirst + nParent ], aValue ) )
+ {
+ this.aSequence[ nFirst + nHoleIndex ] = this.aSequence[ nFirst + nParent ];
+ nHoleIndex = nParent;
+ nParent = Math.floor( ( nHoleIndex - 1 ) / 2 );
+ }
+ this.aSequence[ nFirst + nHoleIndex ] = aValue;
+};
+
+
+/*****
+ * @stdlibend
+ *
+ * The above code is a porting, performed on August 2011, of a part of
+ * the C++ code included into the source file stl_queue.h that is part of
+ * the GNU ISO C++ Library.
+ */
+
+
+
+
+
+/*****
+ * @licstart
+ *
+ * The following is the license notice for the part of JavaScript code of
+ * this page included between the '@libreofficestart' and the '@libreofficeend'
+ * notes.
+ */
+
+/***** ******************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/*****
+ * @licend
+ *
+ * The above is the license notice for the part of JavaScript code of
+ * this page included between the '@libreofficestart' and the '@libreofficeend'
+ * notes.
+ */
+
+
+
+/*****
+ * @libreofficestart
+ *
+ * Several parts of the following code are the result of the porting,
+ * started on August 2011, of the C++ code included in the source files
+ * placed under the folder '/slideshow/source' and subfolders.
+ * @source http://cgit.freedesktop.org/libreoffice/core/tree/slideshow/source
+ *
+ */
+
+
+window.onload = init;
+
+
+// ooo elements
+var aOOOElemMetaSlides = 'ooo:meta_slides';
+var aOOOElemMetaSlide = 'ooo:meta_slide';
+var aOOOElemTextField = 'ooo:text_field';
+
+// ooo attributes
+var aOOOAttrNumberOfSlides = 'number-of-slides';
+var aOOOAttrNumberingType = 'page-numbering-type';
+
+var aOOOAttrSlide = 'slide';
+var aOOOAttrMaster = 'master';
+var aOOOAttrBackgroundVisibility = 'background-visibility';
+var aOOOAttrMasterObjectsVisibility = 'master-objects-visibility';
+var aOOOAttrPageNumberVisibility = 'page-number-visibility';
+var aOOOAttrDateTimeVisibility = 'date-time-visibility';
+var aOOOAttrFooterVisibility = 'footer-visibility';
+var aOOOAttrHeaderVisibility = 'header-visibility';
+var aOOOAttrDateTimeField = 'date-time-field';
+var aOOOAttrFooterField = 'footer-field';
+var aOOOAttrHeaderField = 'header-field';
+
+var aOOOAttrDateTimeFormat = 'date-time-format';
+
+var aOOOAttrTextAdjust = 'text-adjust';
+
+// Placeholder class names
+var aSlideNumberClassName = 'Slide_Number';
+var aDateTimeClassName = 'Date/Time';
+var aFooterClassName = 'Footer';
+var aHeaderClassName = 'Header';
+
+// Creating a namespace dictionary.
+var NSS = new Object();
+NSS['svg']='http://www.w3.org/2000/svg';
+NSS['rdf']='http://www.w3.org/1999/02/22-rdf-syntax-ns#';
+NSS['xlink']='http://www.w3.org/1999/xlink';
+NSS['xml']='http://www.w3.org/XML/1998/namespace';
+NSS['ooo'] = 'http://xml.openoffice.org/svg/export';
+
+// Presentation modes.
+var SLIDE_MODE = 1;
+var INDEX_MODE = 2;
+
+// Mouse handler actions.
+var MOUSE_UP = 1;
+var MOUSE_DOWN = 2;
+var MOUSE_MOVE = 3;
+var MOUSE_WHEEL = 4;
+
+// Keycodes.
+var LEFT_KEY = 37; // cursor left keycode
+var UP_KEY = 38; // cursor up keycode
+var RIGHT_KEY = 39; // cursor right keycode
+var DOWN_KEY = 40; // cursor down keycode
+var PAGE_UP_KEY = 33; // page up keycode
+var PAGE_DOWN_KEY = 34; // page down keycode
+var HOME_KEY = 36; // home keycode
+var END_KEY = 35; // end keycode
+var ENTER_KEY = 13;
+var SPACE_KEY = 32;
+var ESCAPE_KEY = 27;
+
+// Visibility Values
+var HIDDEN = 0;
+var VISIBLE = 1;
+var INHERIT = 2;
+var aVisibilityAttributeValue = [ 'hidden', 'visible', 'inherit' ];
+var aVisibilityValue = { 'hidden' : HIDDEN, 'visible' : VISIBLE, 'inherit' : INHERIT };
+
+// Parameters
+var ROOT_NODE = document.getElementsByTagNameNS( NSS['svg'], 'svg' )[0];
+var WIDTH = 0;
+var HEIGHT = 0;
+var INDEX_COLUMNS_DEFAULT = 3;
+var INDEX_OFFSET = 0;
+
+// Initialization.
+var theMetaDoc;
+var theSlideIndexPage;
+var currentMode = SLIDE_MODE;
+var processingEffect = false;
+var nCurSlide = undefined;
+
+// Initialize char and key code dictionaries.
+var charCodeDictionary = getDefaultCharCodeDictionary();
+var keyCodeDictionary = getDefaultKeyCodeDictionary();
+
+// Initialize mouse handler dictionary.
+var mouseHandlerDictionary = getDefaultMouseHandlerDictionary();
+
+/***************************
+ ** OOP support functions **
+ ***************************/
+
+function object( aObject )
+{
+ var F = function() {};
+ F.prototype = aObject;
+ return new F();
+}
+
+
+function extend( aSubType, aSuperType )
+{
+ if (!aSuperType || !aSubType)
+ {
+ alert('extend failed, verify dependencies');
+ }
+ var OP = Object.prototype;
+ var sp = aSuperType.prototype;
+ var rp = object( sp );
+ aSubType.prototype = rp;
+
+ rp.constructor = aSubType;
+ aSubType.superclass = sp;
+
+ // assign constructor property
+ if (aSuperType != Object && sp.constructor == OP.constructor)
+ {
+ sp.constructor = aSuperType;
+ }
+
+ return aSubType;
+}
+
+
+function instantiate( TemplateClass, BaseType )
+{
+ if( !TemplateClass.instanceSet )
+ TemplateClass.instanceSet = new Array();
+
+ var nSize = TemplateClass.instanceSet.length;
+
+ for( var i = 0; i < nSize; ++i )
+ {
+ if( TemplateClass.instanceSet[i].base === BaseType )
+ return TemplateClass.instanceSet[i].instance;
+ }
+
+ TemplateClass.instanceSet[ nSize ] = new Object();
+ TemplateClass.instanceSet[ nSize ].base = BaseType;
+ TemplateClass.instanceSet[ nSize ].instance = TemplateClass( BaseType );
+
+ return TemplateClass.instanceSet[ nSize ].instance;
+};
+
+// ------------------------------------------------------------------------------------------ //
+/**********************************
+ ** Helper functions and classes **
+ **********************************/
+
+function Rectangle( aSVGRectElem )
+{
+ var x = parseInt( aSVGRectElem.getAttribute( 'x' ) );
+ var y = parseInt( aSVGRectElem.getAttribute( 'y' ) );
+ var width = parseInt( aSVGRectElem.getAttribute( 'width' ) );
+ var height = parseInt( aSVGRectElem.getAttribute( 'height' ) );
+
+ this.left = x;
+ this.right = x + width;
+ this.top = y;
+ this.bottom = y + height;
+}
+
+function log( message )
+{
+ if( typeof console == 'object' )
+ {
+ console.log( message );
+ }
+ else if( typeof opera == 'object' )
+ {
+ opera.postError( message );
+ }
+ else if( typeof java == 'object' && typeof java.lang == 'object' )
+ {
+ java.lang.System.out.println( message );
+ }
+}
+
+function getNSAttribute( sNSPrefix, aElem, sAttrName )
+{
+ if( !aElem ) return null;
+ if( aElem.hasAttributeNS( NSS[sNSPrefix], sAttrName ) )
+ {
+ return aElem.getAttributeNS( NSS[sNSPrefix], sAttrName );
+ }
+ return null;
+}
+
+function getOOOAttribute( aElem, sAttrName )
+{
+ return getNSAttribute( 'ooo', aElem, sAttrName );
+}
+
+function setNSAttribute( sNSPrefix, aElem, sAttrName, aValue )
+{
+ if( !aElem ) return false;
+ if( 'setAttributeNS' in aElem )
+ {
+ aElem.setAttributeNS( NSS[sNSPrefix], sAttrName, aValue );
+ return true;
+ }
+ else
+ {
+ aElem.setAttribute(sNSPrefix + ':' + sAttrName, aValue );
+ return true;
+ }
+}
+
+function setOOOAttribute( aElem, sAttrName, aValue )
+{
+ return setNSAttribute( 'ooo', aElem, sAttrName, aValue );
+}
+
+function checkElemAndSetAttribute( aElem, sAttrName, aValue )
+{
+ if( aElem )
+ aElem.setAttribute( sAttrName, aValue );
+}
+
+function getElementsByClassName( aElem, sClassName )
+{
+
+ var aElementSet = new Array();
+ // not all browsers support the 'getElementsByClassName' method
+ if( 'getElementsByClassName' in aElem )
+ {
+ aElementSet = aElem.getElementsByClassName( sClassName );
+ }
+ else
+ {
+ var aElementSetByClassProperty = getElementsByProperty( aElem, 'class' );
+ for( var i = 0; i < aElementSetByClassProperty.length; ++i )
+ {
+ var sAttrClassName = aElementSetByClassProperty[i].getAttribute( 'class' );
+ if( sAttrClassName == sClassName )
+ {
+ aElementSet.push( aElementSetByClassProperty[i] );
+ }
+ }
+ }
+ return aElementSet;
+}
+
+function getElementByClassName( aElem, sClassName /*, sTagName */)
+{
+ var aElementSet = getElementsByClassName( aElem, sClassName );
+ if ( aElementSet.length == 1 )
+ return aElementSet[0];
+ else
+ return null;
+}
+
+function getClassAttribute( aElem )
+{
+ if( aElem )
+ return aElem.getAttribute( 'class' );
+ return '';
+}
+
+function initVisibilityProperty( aElement )
+{
+ var nVisibility = VISIBLE;
+ var sVisibility = aElement.getAttribute( 'visibility' );
+ if( sVisibility ) nVisibility = aVisibilityValue[ sVisibility ];
+ return nVisibility;
+}
+
+function setElementVisibility( aElement, nCurrentVisibility, nNewVisibility )
+{
+ if( nCurrentVisibility != nNewVisibility )
+ {
+ checkElemAndSetAttribute( aElement, 'visibility', aVisibilityAttributeValue[nNewVisibility] );
+ return nNewVisibility;
+ }
+ return nCurrentVisibility;
+}
+
+function getSafeIndex( nIndex, nMin, nMax )
+{
+ if( nIndex < nMin )
+ return nMin;
+ else if( nIndex > nMax )
+ return nMax;
+ else
+ return nIndex;
+}
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/*********************
+ ** Debug Utilities **
+ *********************/
+
+function DebugPrinter()
+{
+ this.bEnabled = false;
+}
+
+
+DebugPrinter.prototype.on = function()
+{
+ this.bEnabled = true;
+};
+
+DebugPrinter.prototype.off = function()
+{
+ this.bEnabled = false;
+};
+
+DebugPrinter.prototype.isEnabled = function()
+{
+ return this.bEnabled;
+};
+
+DebugPrinter.prototype.print = function( sMessage, nTime )
+{
+ if( this.isEnabled() )
+ {
+ sInfo = 'DBG: ' + sMessage;
+ if( nTime )
+ sInfo += ' (at: ' + String( nTime / 1000 ) + 's)';
+ log( sInfo );
+ }
+ };
+
+
+// - Debug Printers -
+var NAVDBG = new DebugPrinter();
+NAVDBG.off();
+
+var ANIMDBG = new DebugPrinter();
+ANIMDBG.off();
+
+var aRegisterEventDebugPrinter = new DebugPrinter();
+aRegisterEventDebugPrinter.off();
+
+var aTimerEventQueueDebugPrinter = new DebugPrinter();
+aTimerEventQueueDebugPrinter.off();
+
+var aEventMultiplexerDebugPrinter = new DebugPrinter();
+aEventMultiplexerDebugPrinter.off();
+
+var aNextEffectEventArrayDebugPrinter = new DebugPrinter();
+aNextEffectEventArrayDebugPrinter.off();
+
+var aActivityQueueDebugPrinter = new DebugPrinter();
+aActivityQueueDebugPrinter.off();
+
+var aAnimatedElementDebugPrinter = new DebugPrinter();
+aAnimatedElementDebugPrinter.off();
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/******************
+ ** Core Classes **
+ ******************/
+
+/** Class MetaDocument **
+ * This class provides a pool of properties related to the whole presentation and
+ * it is responsible for initializing the set of MetaSlide objects that handle
+ * the meta information for each slide.
+ */
+function MetaDocument( aMetaDocElem )
+{
+ this.nNumberOfSlides = parseInt( aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrNumberOfSlides ) );
+ assert( typeof this.nNumberOfSlides == 'number' && this.nNumberOfSlides > 0,
+ 'MetaDocument: number of slides is zero or undefined.' );
+ this.startSlideNumber = 0;
+ this.sPageNumberingType = aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrNumberingType ) || 'arabic';
+ this.aMetaSlideSet = new Array();
+ this.aMasterPageSet = new Object();
+ this.aTextFieldSet = new Array();
+ this.slideNumberField = new SlideNumberField( this.startSlideNumber + 1, this.sPageNumberingType );
+
+ this.aSlideAnimationsMap = new Object();
+ this.initSlideAnimationsMap();
+
+
+ for( var i = 0; i < this.nNumberOfSlides; ++i )
+ {
+ var sMetaSlideId = aOOOElemMetaSlide + '_' + i;
+ this.aMetaSlideSet.push( new MetaSlide( sMetaSlideId, this ) );
+ }
+ assert( this.aMetaSlideSet.length == this.nNumberOfSlides,
+ 'MetaDocument: aMetaSlideSet.length != nNumberOfSlides.' );
+ //this.aMetaSlideSet[ this.startSlideNumber ].show();
+}
+
+MetaDocument.prototype.initPlaceholderShapes = function()
+{
+ this.aMetaSlideSet[0].initPlaceholderShapes();
+};
+
+MetaDocument.prototype.initSlideAnimationsMap = function()
+{
+ var aAnimationsSection = document.getElementById( 'presentation-animations' );
+ if( aAnimationsSection )
+ {
+ var aAnimationsDefSet = aAnimationsSection.getElementsByTagName( 'defs' );
+
+ for( var i = 0; i < aAnimationsDefSet.length; ++i )
+ {
+ var sSlideId = aAnimationsDefSet[i].getAttributeNS( NSS['ooo'], aOOOAttrSlide );
+ var aChildSet = getElementChildren( aAnimationsDefSet[i] );
+ if( sSlideId && ( aChildSet.length === 1 ) )
+ {
+ this.aSlideAnimationsMap[ sSlideId ] = aChildSet[0];
+ }
+ }
+ }
+};
+
+
+
+/** Class MetaSlide **
+ * This class is responsible for managing the visibility of all master page shapes
+ * and background related to a given slide element; it performs the creation and
+ * the initialization of each Text Field object.
+ */
+function MetaSlide( sMetaSlideId, aMetaDoc )
+{
+ this.theDocument = document;
+ this.id = sMetaSlideId;
+ this.theMetaDoc = aMetaDoc;
+ this.element = this.theDocument.getElementById( this.id );
+ assert( this.element, 'MetaSlide: meta_slide element <' + this.id + '> not found.' );
+ // - Initialize the Slide Element -
+ this.slideId = this.element.getAttributeNS( NSS['ooo'], aOOOAttrSlide );
+ this.slideElement = this.theDocument.getElementById( this.slideId );
+ assert( this.slideElement, 'MetaSlide: slide element <' + this.slideId + '> not found.' );
+ // - Initialize the Target Master Page Element -
+ this.masterPage = this.initMasterPage();
+ // - Initialize Background -
+ //this.aBackground = getElementByClassName( this.aSlide, 'Background' );
+ // - Initialize Visibility Properties -
+ this.nAreMasterObjectsVisible = this.initVisibilityProperty( aOOOAttrMasterObjectsVisibility, VISIBLE );
+ this.nIsBackgroundVisible = this.initVisibilityProperty( aOOOAttrBackgroundVisibility, VISIBLE );
+ this.nIsPageNumberVisible = this.initVisibilityProperty( aOOOAttrPageNumberVisibility, HIDDEN );
+ this.nIsDateTimeVisible = this.initVisibilityProperty( aOOOAttrDateTimeVisibility, VISIBLE );
+ this.nIsFooterVisible = this.initVisibilityProperty( aOOOAttrFooterVisibility, VISIBLE );
+ this.nIsHeaderVisible = this.initVisibilityProperty( aOOOAttrHeaderVisibility, VISIBLE );
+ // - Initialize Master Page Text Fields (Placeholders)-
+ this.aMPTextFieldSet = new Object();
+ this.aMPTextFieldSet[aSlideNumberClassName] = this.initSlideNumberField();
+ this.aMPTextFieldSet[aDateTimeClassName] = this.initDateTimeField( aOOOAttrDateTimeField );
+ this.aMPTextFieldSet[aFooterClassName] = this.initFixedTextField( aOOOAttrFooterField );
+ this.aMPTextFieldSet[aHeaderClassName] = this.initFixedTextField( aOOOAttrHeaderField );
+
+ // - Initialize Slide Animations Handler
+ this.aSlideAnimationsHandler = new SlideAnimations( aSlideShow.getContext() );
+ this.aSlideAnimationsHandler.importAnimations( this.getSlideAnimationsRoot() );
+ this.aSlideAnimationsHandler.parseElements();
+ if( false && this.aSlideAnimationsHandler.aRootNode )
+ log( this.aSlideAnimationsHandler.aRootNode.info( true ) );
+}
+
+/*** MetaSlide methods ***/
+MetaSlide.prototype =
+{
+ /*** public methods ***/
+ hide : function()
+ {
+ checkElemAndSetAttribute( this.slideElement, 'visibility', 'hidden' );
+
+ this.masterPage.hide();
+ this.masterPage.hideBackground();
+
+ var aFieldSet = this.aMPTextFieldSet;
+ var aShapeSet = this.masterPage.aPlaceholderShapeSet;
+ if( aFieldSet[aSlideNumberClassName] ) aFieldSet[aSlideNumberClassName].hide( aShapeSet[aSlideNumberClassName] );
+ if( aFieldSet[aDateTimeClassName] ) aFieldSet[aDateTimeClassName].hide( aShapeSet[aDateTimeClassName] );
+ if( aFieldSet[aFooterClassName] ) aFieldSet[aFooterClassName].hide( aShapeSet[aFooterClassName] );
+ if( aFieldSet[aHeaderClassName] ) aFieldSet[aHeaderClassName].hide( aShapeSet[aHeaderClassName] );
+ },
+
+ hideExceptMaster : function()
+ {
+ checkElemAndSetAttribute( this.slideElement, 'visibility', 'hidden' );
+ },
+
+ show : function()
+ {
+ checkElemAndSetAttribute( this.slideElement, 'visibility', 'visible' );
+
+ this.masterPage.setVisibility( this.nAreMasterObjectsVisible );
+ this.masterPage.setVisibilityBackground( this.nIsBackgroundVisible );
+
+
+ this.setTextFieldVisibility( aSlideNumberClassName, this.nIsPageNumberVisible );
+ this.setTextFieldVisibility( aDateTimeClassName, this.nIsDateTimeVisible );
+ this.setTextFieldVisibility( aFooterClassName, this.nIsFooterVisible );
+ this.setTextFieldVisibility( aHeaderClassName, this.nIsHeaderVisible );
+ },
+
+ getMasterPageId : function()
+ {
+ return this.masterPage.id;
+ },
+
+ getMasterPageElement : function()
+ {
+ return this.masterPage.element;
+ },
+
+ getBackground : function()
+ {
+ return getElementByClassName( this.slideElement, 'Background' );
+ },
+
+ getMasterPageBackground : function()
+ {
+ return this.masterPage.background;
+ },
+
+ /*** private methods ***/
+ initMasterPage : function()
+ {
+ var sMasterPageId = this.element.getAttributeNS( NSS['ooo'], aOOOAttrMaster );
+ if( !this.theMetaDoc.aMasterPageSet.hasOwnProperty( sMasterPageId ) )
+ this.theMetaDoc.aMasterPageSet[ sMasterPageId ] = new MasterPage( sMasterPageId );
+ return this.theMetaDoc.aMasterPageSet[ sMasterPageId ];
+ },
+
+ initVisibilityProperty : function( aVisibilityAttribute, nDefaultValue )
+ {
+ var nVisibility = nDefaultValue;
+ var sVisibility = getOOOAttribute( this.element, aVisibilityAttribute );
+ if( sVisibility )
+ nVisibility = aVisibilityValue[ sVisibility ];
+ return nVisibility;
+ },
+
+ initSlideNumberField : function()
+ {
+ return this.theMetaDoc.slideNumberField;
+ },
+
+ initDateTimeField : function( aOOOAttrDateTimeField )
+ {
+ var sTextFieldId = getOOOAttribute( this.element, aOOOAttrDateTimeField );
+ if( !sTextFieldId ) return null;
+
+ var nLength = aOOOElemTextField.length + 1;
+ var nIndex = parseInt(sTextFieldId.substring( nLength ) );
+ if( typeof nIndex != 'number') return null;
+
+ if( !this.theMetaDoc.aTextFieldSet[ nIndex ] )
+ {
+ var aTextField;
+ var aTextFieldElem = document.getElementById( sTextFieldId );
+ var sClassName = getClassAttribute( aTextFieldElem );
+ if( sClassName == 'FixedDateTimeField' )
+ {
+ aTextField = new FixedTextField( aTextFieldElem );
+ }
+ else if( sClassName == 'VariableDateTimeField' )
+ {
+ aTextField = new VariableDateTimeField( aTextFieldElem );
+ }
+ else
+ {
+ aTextField = null;
+ }
+ this.theMetaDoc.aTextFieldSet[ nIndex ] = aTextField;
+ }
+ return this.theMetaDoc.aTextFieldSet[ nIndex ];
+ },
+
+ initFixedTextField : function( aOOOAttribute )
+ {
+ var sTextFieldId = getOOOAttribute( this.element, aOOOAttribute );
+ if( !sTextFieldId ) return null;
+
+ var nLength = aOOOElemTextField.length + 1;
+ var nIndex = parseInt( sTextFieldId.substring( nLength ) );
+ if( typeof nIndex != 'number') return null;
+
+ if( !this.theMetaDoc.aTextFieldSet[ nIndex ] )
+ {
+ var aTextFieldElem = document.getElementById( sTextFieldId );
+ this.theMetaDoc.aTextFieldSet[ nIndex ]
+ = new FixedTextField( aTextFieldElem );
+ }
+ return this.theMetaDoc.aTextFieldSet[ nIndex ];
+ },
+
+ setTextFieldVisibility : function( sClassName, nVisible )
+ {
+ var aTextField = this.aMPTextFieldSet[ sClassName ];
+ var aPlaceholderShape = this.masterPage.aPlaceholderShapeSet[ sClassName ];
+ if( !aTextField ) return;
+ aTextField.setVisibility( this.nAreMasterObjectsVisible & nVisible, aPlaceholderShape );
+ },
+
+ getSlideAnimationsRoot : function()
+ {
+ return this.theMetaDoc.aSlideAnimationsMap[ this.slideId ];
+ }
+
+};
+
+/** Class MasterPage **
+ * This class gives access to a master page element, its background and
+ * each placeholder shape present in the master page element.
+ */
+function MasterPage( sMasterPageId )
+{
+ this.id = sMasterPageId;
+ this.element = document.getElementById( this.id );
+ assert( this.element, 'MasterPage: master page element <' + this.id + '> not found.' );
+ this.background = getElementByClassName( this.element, 'Background' );
+ this.backgroundId = this.background.getAttribute( 'id' );
+ this.backgroundVisibility = initVisibilityProperty( this.background );
+ this.backgroundObjects = getElementByClassName( this.element, 'BackgroundObjects' );
+ this.backgroundObjectsId = this.backgroundObjects.getAttribute( 'id' );
+ this.backgroundObjectsVisibility = initVisibilityProperty( this.backgroundObjects );
+ this.aPlaceholderShapeSet = new Object();
+ this.initPlaceholderShapes();
+}
+
+/*** MasterPage methods ***/
+MasterPage.prototype =
+{
+ /*** public method ***/
+ setVisibility : function( nVisibility )
+ {
+ this.backgroundObjectsVisibility = setElementVisibility( this.backgroundObjects, this.backgroundObjectsVisibility, nVisibility );
+ },
+
+ setVisibilityBackground : function( nVisibility )
+ {
+ this.backgroundVisibility = setElementVisibility( this.background, this.backgroundVisibility, nVisibility );
+ },
+
+ hide : function()
+ {
+ this.setVisibility( HIDDEN );
+ },
+
+ show : function()
+ {
+ this.setVisibility( VISIBLE );
+ },
+
+ hideBackground : function()
+ {
+ this.setVisibilityBackground( HIDDEN );
+ },
+
+ showBackground : function()
+ {
+ this.setVisibilityBackground( VISIBLE );
+ },
+
+ /*** private method ***/
+ initPlaceholderShapes : function()
+ {
+ this.aPlaceholderShapeSet[ aSlideNumberClassName ] = new PlaceholderShape( this, aSlideNumberClassName );
+ this.aPlaceholderShapeSet[ aDateTimeClassName ] = new PlaceholderShape( this, aDateTimeClassName );
+ this.aPlaceholderShapeSet[ aFooterClassName ] = new PlaceholderShape( this, aFooterClassName );
+ this.aPlaceholderShapeSet[ aHeaderClassName ] = new PlaceholderShape( this, aHeaderClassName );
+ }
+};
+
+/** Class PlaceholderShape **
+ * This class manages the visibility and the text content of a placeholder shape.
+ */
+function PlaceholderShape( aMasterPage, sClassName )
+{
+ this.masterPage = aMasterPage;
+ this.className = sClassName;
+ this.element = null;
+ this.textElement = null;
+
+ this.init();
+}
+
+/* public methods */
+PlaceholderShape.prototype.setTextContent = function( sText )
+{
+ if( !this.textElement )
+ {
+ log( 'error: PlaceholderShape.setTextContent: text element is not valid in placeholder of type '
+ + this.className + ' that belongs to master slide ' + this.masterPage.id );
+ return;
+ }
+ this.textElement.textContent = sText;
+};
+
+PlaceholderShape.prototype.setVisibility = function( nVisibility )
+{
+ this.element.setAttribute( 'visibility', aVisibilityAttributeValue[nVisibility] );
+};
+
+PlaceholderShape.prototype.show = function()
+{
+ this.element.setAttribute( 'visibility', 'visible' );
+};
+
+PlaceholderShape.prototype.hide = function()
+{
+ this.element.setAttribute( 'visibility', 'hidden' );
+};
+
+/* private methods */
+PlaceholderShape.prototype.init = function()
+{
+ var aShapeElem = getElementByClassName( this.masterPage.backgroundObjects, this.className );
+ if( !aShapeElem ) return;
+
+ this.element = aShapeElem;
+ this.element.setAttribute( 'visibility', 'hidden' );
+
+ this.textElement = getElementByClassName( this.element , 'PlaceholderText' );
+ if( !this.textElement ) return;
+
+
+ var aSVGRectElemSet = this.element.getElementsByTagName( 'rect' );
+ if( aSVGRectElemSet.length != 1) return;
+
+ var aRect = new Rectangle( aSVGRectElemSet[0] );
+
+ var sTextAdjust = getOOOAttribute( this.element, aOOOAttrTextAdjust ) || 'left';
+ var sTextAnchor, sX;
+ if( sTextAdjust == 'left' )
+ {
+ sTextAnchor = 'start';
+ sX = String( aRect.left );
+ }
+ else if( sTextAdjust == 'right' )
+ {
+ sTextAnchor = 'end';
+ sX = String( aRect.right );
+ }
+ else if( sTextAdjust == 'center' )
+ {
+ sTextAnchor = 'middle';
+ var nMiddle = ( aRect.left + aRect.right ) / 2;
+ sX = String( parseInt( String( nMiddle ) ) );
+ }
+
+
+ this.textElement.setAttribute( 'text-anchor', sTextAnchor );
+ this.textElement.setAttribute( 'x', sX );
+};
+
+
+// ------------------------------------------------------------------------------------------ //
+/********************************
+ ** Text Field Class Hierarchy **
+ ********************************/
+
+/** Class TextField **
+ * This class is the root abstract class of the hierarchy.
+ * The 'shapeElement' property is the shape element to which
+ * this TextField object provides the text content.
+ */
+function TextField( aTextFieldElem )
+{
+ this.bIsUpdated = false;
+}
+
+/*** TextField public methods ***/
+TextField.prototype.getShapeElement = function()
+{
+ return this.shapeElement;
+};
+
+TextField.prototype.setVisibility = function( nVisibility, aPlaceholderShape )
+{
+ if( !this.bIsUpdated )
+ {
+ if( nVisibility )
+ {
+ this.update( aPlaceholderShape );
+ this.bIsUpdated = true;
+ }
+ aPlaceholderShape.setVisibility( nVisibility );
+ }
+ else if( !nVisibility )
+ {
+ aPlaceholderShape.hide();
+ this.bIsUpdated = false;
+ }
+};
+
+TextField.prototype.show = function( aPlaceholderShape )
+{
+ this.setVisibility( VISIBLE, aPlaceholderShape );
+};
+
+TextField.prototype.hide = function( aPlaceholderShape )
+{
+ this.setVisibility( HIDDEN, aPlaceholderShape );
+};
+
+
+/** Class FixedTextField **
+ * This class handles text field with a fixed text.
+ * The text content is provided by the 'text' property.
+ */
+function FixedTextField( aTextFieldElem )
+{
+ TextField.call( this, aTextFieldElem );
+ this.text = aTextFieldElem.textContent;
+}
+extend( FixedTextField, TextField );
+
+FixedTextField.prototype.update = function( aPlaceholderShape )
+{
+ aPlaceholderShape.setTextContent( this.text );
+};
+
+
+/** Class VariableDateTimeField **
+ * Provide the text content for the related shape by generating the current
+ * date/time in the format specified by the 'dateTimeFormat' property.
+ */
+function VariableDateTimeField( aTextFieldElem )
+{
+ VariableDateTimeField.superclass.constructor.call( this, aTextFieldElem );
+ this.dateTimeFormat = getOOOAttribute( aTextFieldElem, aOOOAttrDateTimeFormat );
+}
+extend( VariableDateTimeField, TextField );
+
+/*** public methods ***/
+VariableDateTimeField.prototype.update = function( aPlaceholderShape )
+{
+ var sText = this.createDateTimeText( this.dateTimeFormat );
+ aPlaceholderShape.setTextContent( sText );
+};
+
+VariableDateTimeField.prototype.createDateTimeText = function( sDateTimeFormat )
+{
+ // TODO handle date/time format
+ var aDate = Date();
+ var sDate = aDate.toLocaleString();
+ return sDate;
+};
+
+/** Class SlideNumberField **
+ * Provides the text content to the related shape by generating
+ * the current page number in the given page numbering type.
+ */
+function SlideNumberField( nInitialSlideNumber, sPageNumberingType )
+{
+ SlideNumberField.superclass.constructor.call( this, null );
+ this.nInitialSlideNumber = nInitialSlideNumber;
+ this.pageNumberingType = sPageNumberingType;
+
+}
+extend( SlideNumberField, TextField );
+
+/*** public methods ***/
+SlideNumberField.prototype.getNumberingType = function()
+{
+ return this.pageNumberingType;
+};
+
+SlideNumberField.prototype.update = function( aPlaceholderShape )
+{
+ var nSlideNumber;
+ if( nCurSlide === undefined )
+ nSlideNumber = this.nInitialSlideNumber;
+ else
+ nSlideNumber = nCurSlide + 1;
+ var sText = this.createSlideNumberText( nSlideNumber, this.getNumberingType() );
+ aPlaceholderShape.setTextContent( sText );
+};
+
+SlideNumberField.prototype.createSlideNumberText = function( nSlideNumber, sNumberingType )
+{
+ // TODO handle page numbering type
+ return String( nSlideNumber );
+};
+
+
+
+//------------------------------------------------------------------------------------------- //
+/********************************
+ ** Slide Index Classes **
+ ********************************/
+
+/** Class SlideIndePagex **
+ * This class is responsible for handling the slide index page
+ */
+function SlideIndexPage()
+{
+ this.pageElementId = 'slide_index';
+ this.pageBgColor = 'rgb(252,252,252)';
+ this.pageElement = this.createPageElement();
+ assert( this.pageElement, 'SlideIndexPage: pageElement is not valid' );
+ this.indexColumns = INDEX_COLUMNS_DEFAULT;
+ this.totalThumbnails = this.indexColumns * this.indexColumns;
+ this.selectedSlideIndex = undefined;
+
+ // set up layout paramers
+ this.xSpacingFactor = 600/28000;
+ this.ySpacingFactor = 450/21000;
+ this.xSpacing = WIDTH * this.xSpacingFactor;
+ this.ySpacing = HEIGHT * this.ySpacingFactor;
+ this.halfBorderWidthFactor = ( 300/28000 ) * ( this.indexColumns / 3 );
+ this.halfBorderWidth = WIDTH * this.halfBorderWidthFactor;
+ this.borderWidth = 2 * this.halfBorderWidth;
+ // the following formula is used to compute the slide shrinking factor:
+ // scaleFactor = ( WIDTH - ( columns + 1 ) * xSpacing ) / ( columns * ( WIDTH + borderWidth ) )
+ // indeed we can divide everything by WIDTH:
+ this.scaleFactor = ( 1 - ( this.indexColumns + 1 ) * this.xSpacingFactor ) /
+ ( this.indexColumns * ( 1 + 2 * this.halfBorderWidthFactor ) );
+
+ // We create a Thumbnail Border and Thumbnail MouseArea rectangle template that will be
+ // used by every Thumbnail. The Mouse Area rectangle is used in order to trigger the
+ // mouseover event properly even when the slide background is hidden.
+ this.thumbnailMouseAreaTemplateId = 'thumbnail_mouse_area';
+ this.thumbnailMouseAreaTemplateElement = null;
+ this.thumbnailBorderTemplateId = 'thumbnail_border';
+ this.thumbnailBorderTemplateElement = null;
+ this.createTemplateElements();
+
+ // Now we create the grid of thumbnails
+ this.aThumbnailSet = new Array( this.totalThumbnails );
+ for( var i = 0; i < this.totalThumbnails; ++i )
+ {
+ this.aThumbnailSet[i] = new Thumbnail( this, i );
+ this.aThumbnailSet[i].updateView();
+ }
+
+// this.curThumbnailIndex = this.selectedSlideIndex % this.totalThumbnails;
+ this.curThumbnailIndex = 0;
+// this.aThumbnailSet[ this.curThumbnailIndex ].select();
+}
+
+
+/* public methods */
+SlideIndexPage.prototype.getTotalThumbnails = function()
+{
+ return this.totalThumbnails;
+};
+
+SlideIndexPage.prototype.show = function()
+{
+ this.pageElement.setAttribute( 'display', 'inherit' );
+};
+
+SlideIndexPage.prototype.hide = function()
+{
+ this.pageElement.setAttribute( 'display', 'none' );
+};
+
+/** setSelection
+ *
+ * Change the selected thumbnail from the current one to the thumbnail with index nIndex.
+ *
+ * @param nIndex - the thumbnail index
+ */
+SlideIndexPage.prototype.setSelection = function( nIndex )
+{
+ nIndex = getSafeIndex( nIndex, 0, this.getTotalThumbnails() - 1 );
+ if( this.curThumbnailIndex != nIndex )
+ {
+ this.aThumbnailSet[ this.curThumbnailIndex ].unselect();
+ this.aThumbnailSet[ nIndex ].select();
+ this.curThumbnailIndex = nIndex;
+ }
+ this.selectedSlideIndex = this.aThumbnailSet[ nIndex ].slideIndex;
+};
+
+SlideIndexPage.prototype.createPageElement = function()
+{
+ var aPageElement = document.createElementNS( NSS['svg'], 'g' );
+ aPageElement.setAttribute( 'id', this.pageElementId );
+ aPageElement.setAttribute( 'display', 'none' );
+
+ // the slide index page background
+ var sPageBgColor = this.pageBgColor + ';';
+ var aRectElement = document.createElementNS( NSS['svg'], 'rect' );
+ aRectElement.setAttribute( 'x', 0 );
+ aRectElement.setAttribute( 'y', 0 );
+ aRectElement.setAttribute( 'width', WIDTH );
+ aRectElement.setAttribute( 'height', HEIGHT );
+ aRectElement.setAttribute( 'style', 'stroke:none;fill:' + sPageBgColor );
+
+ aPageElement.appendChild( aRectElement );
+ // The index page is appended after all slide elements
+ // so when it is displayed it covers them all
+ ROOT_NODE.appendChild( aPageElement );
+ return( document.getElementById( this.pageElementId ) );
+};
+
+SlideIndexPage.prototype.createTemplateElements = function()
+{
+ // We define a Rect element as a template of thumbnail border for all slide-thumbnails.
+ // The stroke color is defined individually by each thumbnail according to
+ // its selection status.
+ var aDefsElement = document.createElementNS( NSS['svg'], 'defs' );
+ var aRectElement = document.createElementNS( NSS['svg'], 'rect' );
+ aRectElement.setAttribute( 'id', this.thumbnailBorderTemplateId );
+ aRectElement.setAttribute( 'x', -this.halfBorderWidth );
+ aRectElement.setAttribute( 'y', -this.halfBorderWidth );
+ aRectElement.setAttribute( 'rx', this.halfBorderWidth );
+ aRectElement.setAttribute( 'ry', this.halfBorderWidth );
+ aRectElement.setAttribute( 'width', WIDTH + this.halfBorderWidth );
+ aRectElement.setAttribute( 'height', HEIGHT + this.halfBorderWidth );
+ aRectElement.setAttribute( 'stroke-width', this.borderWidth );
+ aRectElement.setAttribute( 'fill', 'none' );
+ aDefsElement.appendChild( aRectElement );
+
+ // We define a Rect element as a template of mouse area for triggering the mouseover event.
+ // A copy is used by each thumbnail element.
+ aRectElement = document.createElementNS( NSS['svg'], 'rect' );
+ aRectElement.setAttribute( 'id', this.thumbnailMouseAreaTemplateId );
+ aRectElement.setAttribute( 'x', 0 );
+ aRectElement.setAttribute( 'y', 0 );
+ aRectElement.setAttribute( 'width', WIDTH );
+ aRectElement.setAttribute( 'height', HEIGHT );
+ aRectElement.setAttribute( 'fill', this.pageBgColor );
+ aDefsElement.appendChild( aRectElement );
+
+ this.pageElement.appendChild( aDefsElement );
+
+ this.thumbnailMouseAreaTemplateElement = document.getElementById( this.thumbnailMouseAreaTemplateId );
+ this.thumbnailBorderTemplateElement = document.getElementById( this.thumbnailBorderTemplateId );
+};
+
+SlideIndexPage.prototype.decreaseNumberOfColumns = function()
+{
+ this.setNumberOfColumns( this.indexColumns - 1 );
+};
+
+SlideIndexPage.prototype.increaseNumberOfColumns = function()
+{
+ this.setNumberOfColumns( this.indexColumns + 1 );
+};
+
+SlideIndexPage.prototype.resetNumberOfColumns = function()
+{
+ this.setNumberOfColumns( INDEX_COLUMNS_DEFAULT );
+};
+
+/** setNumberOfColumns
+ *
+ * Change the size of the thumbnail grid.
+ *
+ * @param nNumberOfColumns - the new number of columns/rows of the thumbnail grid
+ */
+SlideIndexPage.prototype.setNumberOfColumns = function( nNumberOfColumns )
+{
+ if( this.indexColumns == nNumberOfColumns ) return;
+ if( nNumberOfColumns < 2 || nNumberOfColumns > 6 ) return;
+
+ var suspendHandle = ROOT_NODE.suspendRedraw(500);
+
+ var nOldTotalThumbnails = this.totalThumbnails;
+ this.indexColumns = nNumberOfColumns;
+ this.totalThumbnails = nNumberOfColumns * nNumberOfColumns;;
+
+ this.aThumbnailSet[this.curThumbnailIndex].unselect();
+
+ // if we decreased the number of used columns we remove the exceding thumbnail elements
+ for( var i = this.totalThumbnails; i < nOldTotalThumbnails; ++i )
+ {
+ this.aThumbnailSet[i].removeElement();
+ };
+
+ // if we increased the number of used columns we create the needed thumbnail objects
+ for( var i = nOldTotalThumbnails; i < this.totalThumbnails; ++i )
+ {
+ this.aThumbnailSet[i] = new Thumbnail( this, i );
+ };
+
+ // we set up layout parameters that depend on the number of columns
+ this.halfBorderWidthFactor = ( 300/28000 ) * ( this.indexColumns / 3 );
+ this.halfBorderWidth = WIDTH * this.halfBorderWidthFactor;
+ this.borderWidth = 2 * this.halfBorderWidth;
+ // scaleFactor = ( WIDTH - ( columns + 1 ) * xSpacing ) / ( columns * ( WIDTH + borderWidth ) )
+ this.scaleFactor = ( 1 - ( this.indexColumns + 1 ) * this.xSpacingFactor ) /
+ ( this.indexColumns * ( 1 + 2 * this.halfBorderWidthFactor ) );
+
+ // update the thumbnail border size
+ var aRectElement = this.thumbnailBorderTemplateElement;
+ aRectElement.setAttribute( 'x', -this.halfBorderWidth );
+ aRectElement.setAttribute( 'y', -this.halfBorderWidth );
+ aRectElement.setAttribute( 'rx', this.halfBorderWidth );
+ aRectElement.setAttribute( 'ry', this.halfBorderWidth );
+ aRectElement.setAttribute( 'width', WIDTH + this.halfBorderWidth );
+ aRectElement.setAttribute( 'height', HEIGHT + this.halfBorderWidth );
+ aRectElement.setAttribute( 'stroke-width', this.borderWidth );
+
+ // now we update the displacement on the index page of each thumbnail (old and new)
+ for( var i = 0; i < this.totalThumbnails; ++i )
+ {
+ this.aThumbnailSet[i].updateView();
+ }
+
+ this.curThumbnailIndex = this.selectedSlideIndex % this.totalThumbnails;
+ this.aThumbnailSet[this.curThumbnailIndex].select();
+
+ // needed for forcing the indexSetPageSlide routine to update the INDEX_OFFSET
+ INDEX_OFFSET = -1;
+ indexSetPageSlide( this.selectedSlideIndex );
+
+ ROOT_NODE.unsuspendRedraw( suspendHandle );
+ ROOT_NODE.forceRedraw();
+};
+
+
+/** Class Thumbnail **
+ * This class handles a slide thumbnail.
+ */
+function Thumbnail( aSlideIndexPage, nIndex )
+{
+ this.container = aSlideIndexPage;
+ this.index = nIndex;//= getSafeIndex( nIndex, 0, this.container.getTotalThumbnails() );
+ this.pageElement = this.container.pageElement;
+ this.thumbnailId = 'thumbnail' + this.index;
+ this.thumbnailElement = this.createThumbnailElement();
+ this.slideElement = getElementByClassName( this.thumbnailElement, 'Slide' );
+ this.backgroundElement = getElementByClassName( this.thumbnailElement, 'Background' );
+ this.backgroundObjectsElement = getElementByClassName( this.thumbnailElement, 'BackgroundObjects' );
+ this.borderElement = getElementByClassName( this.thumbnailElement, 'Border' );
+ this.aTransformSet = new Array( 3 );
+ this.visibility = VISIBLE;
+ this.isSelected = false;
+};
+
+/* static const class member */
+Thumbnail.prototype.sNormalBorderColor = 'rgb(216,216,216)';
+Thumbnail.prototype.sSelectionBorderColor = 'rgb(92,92,255)';
+
+/* public methods */
+Thumbnail.prototype.removeElement = function()
+{
+ if( this.thumbnailElement )
+ this.container.pageElement.removeChild( this.thumbnailElement );
+};
+
+Thumbnail.prototype.show = function()
+{
+ if( this.visibility == HIDDEN )
+ {
+ this.thumbnailElement.setAttribute( 'display', 'inherit' );
+ this.visibility = VISIBLE;
+ }
+};
+
+Thumbnail.prototype.hide = function()
+{
+ if( this.visibility == VISIBLE )
+ {
+ this.thumbnailElement.setAttribute( 'display', 'none' );
+ this.visibility = HIDDEN;
+ }
+ };
+
+ Thumbnail.prototype.select = function()
+ {
+ if( !this.isSelected )
+ {
+ this.borderElement.setAttribute( 'stroke', this.sSelectionBorderColor );
+ this.isSelected = true;
+ }
+};
+
+Thumbnail.prototype.unselect = function()
+{
+ if( this.isSelected )
+ {
+ this.borderElement.setAttribute( 'stroke', this.sNormalBorderColor );
+ this.isSelected = false;
+ }
+};
+
+/** updateView
+ *
+ * This method updates the displacement of the thumbnail on the slide index page,
+ * the value of the row, column coordinates of the thumbnail in the grid, and
+ * the onmouseover property of the thumbnail element.
+ *
+ */
+Thumbnail.prototype.updateView = function()
+{
+ this.column = this.index % this.container.indexColumns;
+ this.row = ( this.index - this.column ) / this.container.indexColumns;
+ this.halfBorderWidth = this.container.halfBorderWidth;
+ this.borderWidth = this.container.borderWidth;
+ this.width = ( WIDTH + this.borderWidth ) * this.container.scaleFactor;
+ this.height = ( HEIGHT + this.borderWidth ) * this.container.scaleFactor;
+ this.aTransformSet[2] = 'translate(' + this.halfBorderWidth + ' ' + this.halfBorderWidth + ')';
+ this.aTransformSet[1] = 'scale(' + this.container.scaleFactor + ')';
+ var sTransformAttrValue = this.computeTransform();
+ this.thumbnailElement.setAttribute( 'transform', sTransformAttrValue );
+ this.thumbnailElement.setAttribute( 'onmouseover', 'theSlideIndexPage.aThumbnailSet[' + this.index + '].onMouseOver()' );
+};
+
+/** update
+ *
+ * This method update the content of the thumbnail view
+ *
+ * @param nIndex - the index of the slide to be shown in the thumbnail
+ */
+Thumbnail.prototype.update = function( nIndex )
+{
+ if( this.slideIndex == nIndex ) return;
+
+ var aMetaSlide = theMetaDoc.aMetaSlideSet[nIndex];
+ setNSAttribute( 'xlink', this.slideElement, 'href', '#' + aMetaSlide.slideId );
+ if( aMetaSlide.nIsBackgroundVisible )
+ {
+ setNSAttribute( 'xlink', this.backgroundElement, 'href', '#' + aMetaSlide.masterPage.backgroundId );
+ this.backgroundElement.setAttribute( 'visibility', 'inherit' );
+ }
+ else
+ {
+ this.backgroundElement.setAttribute( 'visibility', 'hidden' );
+ }
+ if( aMetaSlide.nAreMasterObjectsVisible )
+ {
+ setNSAttribute( 'xlink', this.backgroundObjectsElement, 'href', '#' + aMetaSlide.masterPage.backgroundObjectsId );
+ this.backgroundObjectsElement.setAttribute( 'visibility', 'inherit' );
+ }
+ else
+ {
+ this.backgroundObjectsElement.setAttribute( 'visibility', 'hidden' );
+ }
+ this.slideIndex = nIndex;
+};
+
+Thumbnail.prototype.clear = function( nIndex )
+{
+ setNSAttribute( 'xlink', this.slideElement, 'href', '' );
+ setNSAttribute( 'xlink', this.backgroundElement, 'href', '' );
+ setNSAttribute( 'xlink', this.backgroundObjectsElement, 'href', '' );
+};
+
+/* private methods */
+Thumbnail.prototype.createThumbnailElement = function()
+{
+ var aThumbnailElement = document.createElementNS( NSS['svg'], 'g' );
+ aThumbnailElement.setAttribute( 'id', this.thumbnailId );
+ aThumbnailElement.setAttribute( 'display', 'inherit' );
+
+ var aMouseAreaElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aMouseAreaElement, 'href', '#' + this.container.thumbnailMouseAreaTemplateId );
+ aMouseAreaElement.setAttribute( 'class', 'MouseArea' );
+ aThumbnailElement.appendChild( aMouseAreaElement );
+
+ var aBackgroundElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aBackgroundElement, 'href', '' );
+ aBackgroundElement.setAttribute( 'visibility', 'inherit');
+ aBackgroundElement.setAttribute( 'class', 'Background' );
+ aThumbnailElement.appendChild( aBackgroundElement );
+
+ var aBackgroundObjectsElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aBackgroundObjectsElement, 'href', '' );
+ aBackgroundObjectsElement.setAttribute( 'visibility', 'inherit');
+ aBackgroundObjectsElement.setAttribute( 'class', 'BackgroundObjects' );
+ aThumbnailElement.appendChild( aBackgroundObjectsElement );
+
+ var aSlideElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aSlideElement, 'href', '' );
+ aSlideElement.setAttribute( 'class', 'Slide' );
+ aThumbnailElement.appendChild( aSlideElement );
+
+ var aBorderElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aBorderElement, 'href', '#' + this.container.thumbnailBorderTemplateId );
+ aBorderElement.setAttribute( 'stroke', this.sNormalBorderColor );
+ aBorderElement.setAttribute( 'class', 'Border' );
+ aThumbnailElement.appendChild( aBorderElement );
+
+ this.container.pageElement.appendChild( aThumbnailElement );
+ return( document.getElementById( this.thumbnailId ) );
+};
+
+Thumbnail.prototype.computeTransform = function()
+{
+ var nXSpacing = this.container.xSpacing;
+ var nYSpacing = this.container.ySpacing;
+
+ var nXOffset = nXSpacing + ( this.width + nXSpacing ) * this.column;
+ var nYOffset = nYSpacing + ( this.height + nYSpacing ) * this.row;
+
+ this.aTransformSet[0] = 'translate(' + nXOffset + ' ' + nYOffset + ')';
+
+ sTransform = this.aTransformSet.join( ' ' );
+
+ return sTransform;
+};
+
+Thumbnail.prototype.onMouseOver = function()
+{
+ if( ( currentMode == INDEX_MODE ) && ( this.container.curThumbnailIndex != this.index ) )
+ {
+ this.container.setSelection( this.index );
+ }
+};
+
+
+
+
+// ------------------------------------------------------------------------------------------ //
+/** Initialization function.
+ * The whole presentation is set-up in this function.
+ */
+function init()
+{
+ var VIEWBOX = ROOT_NODE.getAttribute('viewBox');
+
+ if( VIEWBOX )
+ {
+ WIDTH = ROOT_NODE.viewBox.animVal.width;
+ HEIGHT = ROOT_NODE.viewBox.animVal.height;
+ }
+
+ var aMetaDocElem = document.getElementById( aOOOElemMetaSlides );
+ assert( aMetaDocElem, 'init: meta document element not found' );
+ aSlideShow = new SlideShow();
+ theMetaDoc = new MetaDocument( aMetaDocElem );
+ theSlideIndexPage = new SlideIndexPage();
+ aSlideShow.displaySlide( theMetaDoc.startSlideNumber );
+
+ //=====================================//
+ // ===== timing test ===== //
+ //=====================================//
+// var aTimingAttributeList = [ '0.001s', '-12:16.123', 'next', 'id23.click', 'id3.end + 5s', 'id4.begin - 12:45' ];
+//
+// for( var i = 0; i < aTimingAttributeList.length; ++i)
+// {
+// var aTiming = new Timing( aTimingAttributeList[i] );
+// aTiming.parse();
+// aTiming.info();
+// }
+
+
+ //=====================================//
+ // == animations parsing test == //
+ //=====================================//
+
+// var aSlideShowContext = aSlideShow.getContext();
+// var aSlideAnimations = new SlideAnimations( aSlideShowContext );
+// aSlideAnimations.importAnimations( getSlideAnimationsRoot( 'id7' ) );
+// aSlideAnimations.parseElements();
+// log( aSlideAnimations.aRootNode.info( true ) );
+
+}
+
+function presentationEngineStop()
+{
+ alert( 'We are sorry! An unexpected error occurred.\nThe presentation engine will be stopped' );
+ document.onkeydown = null;
+ document.onkeypress = null;
+ document.onclick = null;
+ window.onmousewheel = null;
+}
+
+function assert( condition, message )
+{
+ if (!condition)
+ {
+ presentationEngineStop();
+ if (typeof console == 'object')
+ console.trace();
+ throw new Error( message );
+ }
+}
+
+function dispatchEffects(dir)
+{
+ // TODO to be implemented
+
+ if( dir == 1 )
+ {
+ var bRet = aSlideShow.nextEffect();
+
+ if( !bRet )
+ {
+ switchSlide( 1 );
+ }
+ }
+ else
+ {
+ switchSlide( dir );
+ }
+}
+
+function skipEffects(dir)
+{
+ // TODO to be implemented
+ switchSlide(dir);
+}
+
+function switchSlide( nOffset, bSkipTransition )
+{
+ var nNextSlide = nCurSlide + nOffset;
+ aSlideShow.displaySlide( nNextSlide, bSkipTransition );
+}
+
+/** Function to display the index sheet.
+*
+* @param offsetNumber offset number
+*/
+ function displayIndex( offsetNumber )
+ {
+ var aMetaSlideSet = theMetaDoc.aMetaSlideSet;
+ offsetNumber = getSafeIndex( offsetNumber, 0, aMetaSlideSet.length - 1 );
+
+ var nTotalThumbnails = theSlideIndexPage.getTotalThumbnails();
+ var nEnd = Math.min( offsetNumber + nTotalThumbnails, aMetaSlideSet.length);
+
+ var aThumbnailSet = theSlideIndexPage.aThumbnailSet;
+ var j = 0;
+ for( var i = offsetNumber; i < nEnd; ++i, ++j )
+ {
+ aThumbnailSet[j].update( i );
+ aThumbnailSet[j].show();
+ }
+ for( ; j < nTotalThumbnails; ++j )
+ {
+ aThumbnailSet[j].hide();
+ }
+
+ //do we need to save the current offset?
+ if (INDEX_OFFSET != offsetNumber)
+ INDEX_OFFSET = offsetNumber;
+ }
+
+/** Function to toggle between index and slide mode.
+ */
+function toggleSlideIndex()
+{
+ var suspendHandle = ROOT_NODE.suspendRedraw(500);
+ var aMetaSlideSet = theMetaDoc.aMetaSlideSet;
+
+ if( currentMode == SLIDE_MODE )
+ {
+ aMetaSlideSet[nCurSlide].hide();
+ for( var counter = 0; counter < aMetaSlideSet.length; ++counter )
+ {
+ checkElemAndSetAttribute( aMetaSlideSet[counter].slideElement, 'visibility', 'inherit' );
+ aMetaSlideSet[counter].masterPage.setVisibilityBackground( INHERIT );
+ aMetaSlideSet[counter].masterPage.setVisibility( INHERIT );
+ }
+ INDEX_OFFSET = -1;
+ indexSetPageSlide( nCurSlide );
+ theSlideIndexPage.show();
+ currentMode = INDEX_MODE;
+ }
+ else if( currentMode == INDEX_MODE )
+ {
+ theSlideIndexPage.hide();
+ var nNewSlide = theSlideIndexPage.selectedSlideIndex;
+
+ for( var counter = 0; counter < aMetaSlideSet.length; ++counter )
+ {
+ var aMetaSlide = aMetaSlideSet[counter];
+ aMetaSlide.slideElement.setAttribute( 'visibility', 'hidden' );
+ aMetaSlide.masterPage.setVisibilityBackground( HIDDEN );
+ aMetaSlide.masterPage.setVisibility( HIDDEN );
+ }
+
+ aSlideShow.displaySlide( nNewSlide, true );
+ currentMode = SLIDE_MODE;
+ }
+
+ ROOT_NODE.unsuspendRedraw(suspendHandle);
+ ROOT_NODE.forceRedraw();
+}
+
+/** Function that exit from the index mode without changing the shown slide
+ *
+ */
+function abandonIndexMode()
+{
+ theSlideIndexPage.selectedSlideIndex = nCurSlide;
+ toggleSlideIndex();
+}
+
+
+
+
+
+/*********************************************************************************************
+ *********************************************************************************************
+ *********************************************************************************************
+
+ ***** ANIMATION ENGINE *****
+
+ *********************************************************************************************
+ *********************************************************************************************
+ *********************************************************************************************/
+
+
+
+
+
+// ------------------------------------------------------------------------------------------ //
+// helper functions
+
+
+var CURR_UNIQUE_ID = 0;
+
+function getUniqueId()
+{
+ ++CURR_UNIQUE_ID;
+ return CURR_UNIQUE_ID;
+}
+
+function mem_fn( sMethodName )
+{
+ return function( aObject )
+ {
+ var aMethod = aObject[ sMethodName ];
+ if( aMethod )
+ aMethod.call( aObject );
+ else
+ log( 'method sMethodName not found' );
+ };
+}
+
+function bind( aObject, aMethod )
+{
+ return function()
+ {
+ return aMethod.call( aObject, arguments[0] );
+ };
+}
+
+function getCurrentSystemTime()
+{
+ return ( new Date() ).getTime();
+ //return ROOT_NODE.getCurrentTime();
+}
+
+function getSlideAnimationsRoot( sSlideId )
+{
+ return theMetaDoc.aSlideAnimationsMap[ sSlideId ];
+}
+
+/** This function return an array populated with all children nodes of the
+ * passed element that are elements
+ *
+ * @param aElement: any XML element
+ *
+ * @returns an array that contains all children elements
+ */
+function getElementChildren( aElement )
+{
+ var aChildrenArray = new Array();
+
+ var nSize = aElement.childNodes.length;
+
+ for( var i = 0; i < nSize; ++i )
+ {
+ if( aElement.childNodes[i].nodeType == 1 )
+ aChildrenArray.push( aElement.childNodes[i] );
+ }
+
+ return aChildrenArray;
+}
+
+function removeWhiteSpaces( str )
+{
+ if( !str )
+ return '';
+
+ var re = / */;
+ var aSplittedString = str.split( re );
+ return aSplittedString.join('');
+}
+
+function clamp( nValue, nMinimum, nMaximum )
+{
+ if( nValue < nMinimum )
+ {
+ return nMinimum;
+ }
+ else if( nValue > nMaximum )
+ {
+ return nMaximum;
+ }
+ else
+ {
+ return nValue;
+ }
+}
+
+function makeMatrixString( a, b, c, d, e, f )
+{
+ var s = 'matrix(';
+ s += a + ', ';
+ s += b + ', ';
+ s += c + ', ';
+ s += d + ', ';
+ s += e + ', ';
+ s += f + ')';
+
+ return s;
+}
+
+function matrixToString( aSVGMatrix )
+{
+ return makeMatrixString( aSVGMatrix.a, aSVGMatrix.b, aSVGMatrix.c,
+ aSVGMatrix.d, aSVGMatrix.e, aSVGMatrix.f );
+}
+
+
+
+// ------------------------------------------------------------------------------------------ //
+// Attribute Parsers
+
+function numberParser( sValue )
+{
+ if( sValue === '.' )
+ return undefined;
+ var reFloatNumber = /^[+-]?[0-9]*[.]?[0-9]*$/;
+
+ if( reFloatNumber.test( sValue ) )
+ return parseFloat( sValue );
+ else
+ return undefined;
+}
+
+function booleanParser( sValue )
+{
+ sValue = sValue.toLowerCase();
+ if( sValue === 'true' )
+ return true;
+ else if( sValue === 'false' )
+ return false;
+ else
+ return undefined;
+}
+
+function colorParser( sValue )
+{
+
+ function hsl( nHue, nSaturation, nLuminance )
+ {
+ return new HSLColor( nHue, nSaturation / 100, nLuminance / 100 );
+ }
+
+ function rgb( nRed, nGreen, nBlue )
+ {
+ return new RGBColor( nRed / 255, nGreen / 255, nBlue / 255 );
+ }
+
+ function prgb( nRed, nGreen, nBlue )
+ {
+ return new RGBColor( nRed / 100, nGreen / 100, nBlue / 100 );
+ }
+
+ var sCommaPattern = ' *[,] *';
+ var sIntegerPattern = '[+-]?[0-9]+';
+ var sHexDigitPattern = '[0-9A-Fa-f]';
+
+ var sHexColorPattern = '#(' + sHexDigitPattern + '{2})('
+ + sHexDigitPattern + '{2})('
+ + sHexDigitPattern + '{2})';
+
+ var sRGBIntegerPattern = 'rgb[(] *' + sIntegerPattern + sCommaPattern
+ + sIntegerPattern + sCommaPattern
+ + sIntegerPattern + ' *[)]';
+
+ var sRGBPercentPattern = 'rgb[(] *' + sIntegerPattern + '%' + sCommaPattern
+ + sIntegerPattern + '%' + sCommaPattern
+ + sIntegerPattern + '%' + ' *[)]';
+
+ var sHSLPercentPattern = 'hsl[(] *' + sIntegerPattern + sCommaPattern
+ + sIntegerPattern + '%' + sCommaPattern
+ + sIntegerPattern + '%' + ' *[)]';
+
+ var reHexColor = RegExp( sHexColorPattern );
+ var reRGBInteger = RegExp( sRGBIntegerPattern );
+ var reRGBPercent = RegExp( sRGBPercentPattern );
+ var reHSLPercent = RegExp( sHSLPercentPattern );
+
+ if( reHexColor.test( sValue ) )
+ {
+ var aRGBTriple = reHexColor.exec( sValue );
+
+ var nRed = parseInt( aRGBTriple[1], 16 ) / 255;
+ var nGreen = parseInt( aRGBTriple[2], 16 ) / 255;
+ var nBlue = parseInt( aRGBTriple[3], 16 ) / 255;
+
+ return new RGBColor( nRed, nGreen, nBlue );
+ }
+ else if( reHSLPercent.test( sValue ) )
+ {
+ sValue = sValue.replace( '%', '' ).replace( '%', '' );
+ return eval( sValue );
+ }
+ else if( reRGBInteger.test( sValue ) )
+ {
+ return eval( sValue );
+ }
+ else if( reRGBPercent.test( sValue ) )
+ {
+ sValue = 'p' + sValue.replace( '%', '' ).replace( '%', '' ).replace( '%', '' );
+ return eval( sValue );
+ }
+ else
+ {
+ return null;
+ }
+}
+
+
+
+/**********************************************************************************************
+ * RGB and HSL color classes
+ **********************************************************************************************/
+
+// ------------------------------------------------------------------------------------------ //
+function RGBColor( nRed, nGreen, nBlue )
+{
+ this.eColorSpace = COLOR_SPACE_RGB;
+ // values in the [0,1] range
+ this.nRed = nRed;
+ this.nGreen = nGreen;
+ this.nBlue = nBlue;
+}
+
+
+RGBColor.prototype.clone = function()
+{
+ return new RGBColor( this.nRed, this.nGreen, this.nBlue );
+};
+
+RGBColor.prototype.add = function( aRGBColor )
+{
+ this.nRed += aRGBColor.nRed;
+ this.nGreen += aRGBColor.nGreen;
+ this.nBlue += aRGBColor.nBlue;
+ return this;
+};
+
+RGBColor.prototype.scale = function( aT )
+{
+ this.nRed *= aT;
+ this.nGreen *= aT;
+ this.nBlue *= aT;
+ return this;
+};
+
+RGBColor.clamp = function( aRGBColor )
+{
+ var aClampedRGBColor = new RGBColor( 0, 0, 0 );
+
+ aClampedRGBColor.nRed = clamp( aRGBColor.nRed, 0.0, 1.0 );
+ aClampedRGBColor.nGreen = clamp( aRGBColor.nGreen, 0.0, 1.0 );
+ aClampedRGBColor.nBlue = clamp( aRGBColor.nBlue, 0.0, 1.0 );
+
+ return aClampedRGBColor;
+};
+
+RGBColor.prototype.convertToHSL = function()
+{
+ var nRed = clamp( this.nRed, 0.0, 1.0 );
+ var nGreen = clamp( this.nGreen, 0.0, 1.0 );
+ var nBlue = clamp( this.nBlue, 0.0, 1.0 );
+
+ var nMax = Math.max( nRed, nGreen, nBlue );
+ var nMin = Math.min( nRed, nGreen, nBlue );
+ var nDelta = nMax - nMin;
+
+ var nLuminance = ( nMax + nMin ) / 2.0;
+ var nSaturation = 0.0;
+ var nHue = 0.0;
+ if( nDelta !== 0 )
+ {
+ nSaturation = ( nLuminance > 0.5 ) ?
+ ( nDelta / ( 2.0 - nMax - nMin) ) :
+ ( nDelta / ( nMax + nMin ) );
+
+ if( nRed == nMax )
+ nHue = ( nGreen - nBlue ) / nDelta;
+ else if( nGreen == nMax )
+ nHue = 2.0 + ( nBlue - nRed ) / nDelta;
+ else if( nBlue == nMax )
+ nHue = 4.0 + ( nRed - nGreen ) / nDelta;
+
+ nHue *= 60.0;
+
+ if( nHue < 0.0 )
+ nHue += 360.0;
+ }
+
+ return new HSLColor( nHue, nSaturation, nLuminance );
+
+};
+
+RGBColor.prototype.toString = function( bClamped )
+{
+ var aRGBColor;
+ if( bClamped )
+ {
+ aRGBColor = RGBColor.clamp( this );
+ }
+ else
+ {
+ aRGBColor = this;
+ }
+
+ var nRed = Math.round( aRGBColor.nRed * 255 );
+ var nGreen = Math.round( aRGBColor.nGreen * 255 );
+ var nBlue = Math.round( aRGBColor.nBlue * 255 );
+
+ return ( 'rgb(' + nRed + ',' + nGreen + ',' + nBlue + ')' );
+};
+
+RGBColor.interpolate = function( aStartRGB , aEndRGB, nT )
+{
+ var aResult = aStartRGB.clone();
+ var aTEndRGB = aEndRGB.clone();
+ aResult.scale( 1.0 - nT );
+ aTEndRGB.scale( nT );
+ aResult.add( aTEndRGB );
+
+ return aResult;
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
+function HSLColor( nHue, nSaturation, nLuminance )
+{
+ this.eColorSpace = COLOR_SPACE_HSL;
+ // Hue is in the [0,360[ range, Saturation and Luminance are in the [0,1] range
+ this.nHue = nHue;
+ this.nSaturation = nSaturation;
+ this.nLuminance = nLuminance;
+
+ this.normalizeHue();
+}
+
+
+HSLColor.prototype.clone = function()
+{
+ return new HSLColor( this.nHue, this.nSaturation, this.nLuminance );
+};
+
+HSLColor.prototype.add = function( aHSLColor )
+{
+ this.nHue += aHSLColor.nHue;
+ this.nSaturation += aHSLColor.nSaturation;
+ this.nLuminance += aHSLColor.nLuminance;
+ this.normalizeHue();
+ return this;
+};
+
+HSLColor.prototype.scale = function( aT )
+{
+ this.nHue *= aT;
+ this.nSaturation *= aT;
+ this.nLuminance *= aT;
+ this.normalizeHue();
+ return this;
+};
+
+HSLColor.clamp = function( aHSLColor )
+{
+ var aClampedHSLColor = new HSLColor( 0, 0, 0 );
+
+ aClampedHSLColor.nHue = aHSLColor.nHue % 360;
+ if( aClampedHSLColor.nHue < 0 )
+ aClampedHSLColor.nHue += 360;
+ aClampedHSLColor.nSaturation = clamp( aHSLColor.nSaturation, 0.0, 1.0 );
+ aClampedHSLColor.nLuminance = clamp( aHSLColor.nLuminance, 0.0, 1.0 );
+};
+
+HSLColor.prototype.normalizeHue = function()
+{
+ this.nHue = this.nHue % 360;
+ if( this.nHue < 0 ) this.nHue += 360;
+};
+
+HSLColor.prototype.toString = function()
+{
+ return 'hsl(' + this.nHue.toFixed( 3 ) + ','
+ + this.nSaturation.toFixed( 3 ) + ','
+ + this.nLuminance.toFixed( 3 ) + ')';
+};
+
+HSLColor.prototype.convertToRGB = function()
+{
+
+ var nHue = this.nHue % 360;
+ if( nHue < 0 ) nHue += 360;
+ var nSaturation = clamp( this.nSaturation, 0.0, 1.0 );
+ var nLuminance = clamp( this.nLuminance, 0.0, 1.0 );
+
+
+ if( nSaturation === 0 )
+ {
+ return new RGBColor( nLuminance, nLuminance, nLuminance );
+ }
+
+ var nVal1 = ( nLuminance <= 0.5 ) ?
+ ( nLuminance * (1.0 + nSaturation) ) :
+ ( nLuminance + nSaturation - nLuminance * nSaturation );
+
+ var nVal2 = 2.0 * nLuminance - nVal1;
+
+ var nRed = HSLColor.hsl2rgbHelper( nVal2, nVal1, nHue + 120 );
+ var nGreen = HSLColor.hsl2rgbHelper( nVal2, nVal1, nHue );
+ var nBlue = HSLColor.hsl2rgbHelper( nVal2, nVal1, nHue - 120 );
+
+ return new RGBColor( nRed, nGreen, nBlue );
+};
+
+HSLColor.hsl2rgbHelper = function( nValue1, nValue2, nHue )
+{
+ nHue = nHue % 360;
+ if( nHue < 0 )
+ nHue += 360;
+
+ if( nHue < 60.0 )
+ return nValue1 + ( nValue2 - nValue1 ) * nHue / 60.0;
+ else if( nHue < 180.0 )
+ return nValue2;
+ else if( nHue < 240.0 )
+ return ( nValue1 + ( nValue2 - nValue1 ) * ( 240.0 - nHue ) / 60.0 );
+ else
+ return nValue1;
+};
+
+HSLColor.interpolate = function( aFrom, aTo, nT, bCCW )
+{
+ var nS = 1.0 - nT;
+
+ var nHue = 0.0;
+ if( aFrom.nHue <= aTo.nHue && !bCCW )
+ {
+ // interpolate hue clockwise. That is, hue starts at
+ // high values and ends at low ones. Therefore, we
+ // must 'cross' the 360 degrees and start at low
+ // values again (imagine the hues to lie on the
+ // circle, where values above 360 degrees are mapped
+ // back to [0,360)).
+ nHue = nS * (aFrom.nHue + 360.0) + nT * aTo.nHue;
+ }
+ else if( aFrom.nHue > aTo.nHue && bCCW )
+ {
+ // interpolate hue counter-clockwise. That is, hue
+ // starts at high values and ends at low
+ // ones. Therefore, we must 'cross' the 360 degrees
+ // and start at low values again (imagine the hues to
+ // lie on the circle, where values above 360 degrees
+ // are mapped back to [0,360)).
+ nHue = nS * aFrom.nHue + nT * (aTo.nHue + 360.0);
+ }
+ else
+ {
+ // interpolate hue counter-clockwise. That is, hue
+ // starts at low values and ends at high ones (imagine
+ // the hue value as degrees on a circle, with
+ // increasing values going counter-clockwise)
+ nHue = nS * aFrom.nHue + nT * aTo.nHue;
+ }
+
+ var nSaturation = nS * aFrom.nSaturation + nT * aTo.nSaturation;
+ var nLuminance = nS * aFrom.nLuminance + nT * aTo.nLuminance;
+
+ return new HSLColor( nHue, nSaturation, nLuminance );
+ };
+
+
+
+
+/**********************************************************************************************
+ * AnimationNode Class Hierarchy
+ **********************************************************************************************/
+
+// ------------------------------------------------------------------------------------------ //
+
+// Node Types
+var ANIMATION_NODE_CUSTOM = 0;
+var ANIMATION_NODE_PAR = 1;
+var ANIMATION_NODE_SEQ = 2;
+var ANIMATION_NODE_ITERATE = 3;
+var ANIMATION_NODE_ANIMATE = 4;
+var ANIMATION_NODE_SET = 5;
+var ANIMATION_NODE_ANIMATEMOTION = 6;
+var ANIMATION_NODE_ANIMATECOLOR = 7;
+var ANIMATION_NODE_ANIMATETRANSFORM = 8;
+var ANIMATION_NODE_TRANSITIONFILTER = 9;
+var ANIMATION_NODE_AUDIO = 10;
+var ANIMATION_NODE_COMMAND = 11;
+
+aAnimationNodeTypeInMap = {
+ 'par' : ANIMATION_NODE_PAR,
+ 'seq' : ANIMATION_NODE_SEQ,
+ 'iterate' : ANIMATION_NODE_ITERATE,
+ 'animate' : ANIMATION_NODE_ANIMATE,
+ 'set' : ANIMATION_NODE_SET,
+ 'animatemotion' : ANIMATION_NODE_ANIMATEMOTION,
+ 'animatecolor' : ANIMATION_NODE_ANIMATECOLOR,
+ 'animatetransform' : ANIMATION_NODE_ANIMATETRANSFORM,
+ 'transitionfilter' : ANIMATION_NODE_TRANSITIONFILTER
+};
+
+
+
+// ------------------------------------------------------------------------------------------ //
+function getAnimationElementType( aElement )
+{
+ var sName = aElement.localName.toLowerCase();
+ //log( 'getAnimationElementType: ' + sName );
+
+ if( sName && aAnimationNodeTypeInMap[ sName ] )
+ return aAnimationNodeTypeInMap[ sName ];
+ else
+ return ANIMATION_NODE_CUSTOM;
+}
+
+
+
+// ------------------------------------------------------------------------------------------ //
+
+// Node States
+var INVALID_NODE = 0;
+var UNRESOLVED_NODE = 1;
+var RESOLVED_NODE = 2;
+var ACTIVE_NODE = 4;
+var FROZEN_NODE = 8;
+var ENDED_NODE = 16;
+
+function getNodeStateName( eNodeState )
+{
+ switch( eNodeState )
+ {
+ case INVALID_NODE:
+ return 'INVALID';
+ case UNRESOLVED_NODE:
+ return 'UNRESOLVED';
+ case RESOLVED_NODE:
+ return 'RESOLVED';
+ case ACTIVE_NODE:
+ return 'ACTIVE';
+ case FROZEN_NODE:
+ return 'FROZEN';
+ case ENDED_NODE:
+ return 'ENDED';
+ default:
+ return 'UNKNOWN';
+ }
+}
+
+
+// Impress Node Types
+IMPRESS_DEFAULT_NODE = 0;
+IMPRESS_ON_CLICK_NODE = 1;
+IMPRESS_WITH_PREVIOUS_NODE = 2;
+IMPRESS_AFTER_PREVIOUS_NODE = 3;
+IMPRESS_MAIN_SEQUENCE_NODE = 4;
+IMPRESS_TIMING_ROOT_NODE = 5;
+IMPRESS_INTERACTIVE_SEQUENCE_NODE = 6;
+
+aImpressNodeTypeInMap = {
+ 'on-click' : IMPRESS_ON_CLICK_NODE,
+ 'with-previous' : IMPRESS_WITH_PREVIOUS_NODE,
+ 'after-previous' : IMPRESS_AFTER_PREVIOUS_NODE,
+ 'main-sequence' : IMPRESS_MAIN_SEQUENCE_NODE,
+ 'timing-root' : IMPRESS_TIMING_ROOT_NODE,
+ 'interactive-sequence' : IMPRESS_INTERACTIVE_SEQUENCE_NODE
+};
+
+aImpressNodeTypeOutMap = [ 'default', 'on-click', 'with-previous', 'after-previous',
+ 'main-sequence', 'timing-root', 'interactive-sequence' ];
+
+
+// Preset Classes
+aPresetClassInMap = {};
+
+
+// Preset Ids
+aPresetIdInMap = {};
+
+
+// Restart Modes
+RESTART_MODE_DEFAULT = 0;
+RESTART_MODE_INHERIT = 0;
+RESTART_MODE_ALWAYS = 1;
+RESTART_MODE_WHEN_NOT_ACTIVE = 2;
+RESTART_MODE_NEVER = 3;
+
+aRestartModeInMap = {
+ 'inherit' : RESTART_MODE_DEFAULT,
+ 'always' : RESTART_MODE_ALWAYS,
+ 'whenNotActive' : RESTART_MODE_WHEN_NOT_ACTIVE,
+ 'never' : RESTART_MODE_NEVER
+};
+
+aRestartModeOutMap = [ 'inherit','always', 'whenNotActive', 'never' ];
+
+
+// Fill Modes
+var FILL_MODE_DEFAULT = 0;
+var FILL_MODE_INHERIT = 0;
+var FILL_MODE_REMOVE = 1;
+var FILL_MODE_FREEZE = 2;
+var FILL_MODE_HOLD = 3;
+var FILL_MODE_TRANSITION = 4;
+var FILL_MODE_AUTO = 5;
+
+aFillModeInMap = {
+ 'inherit' : FILL_MODE_DEFAULT,
+ 'remove' : FILL_MODE_REMOVE,
+ 'freeze' : FILL_MODE_FREEZE,
+ 'hold' : FILL_MODE_HOLD,
+ 'transition' : FILL_MODE_TRANSITION,
+ 'auto' : FILL_MODE_AUTO
+};
+
+aFillModeOutMap = [ 'inherit', 'remove', 'freeze', 'hold', 'transition', 'auto' ];
+
+
+// Additive Modes
+var ADDITIVE_MODE_BASE = 0;
+var ADDITIVE_MODE_SUM = 1;
+var ADDITIVE_MODE_REPLACE = 2;
+var ADDITIVE_MODE_MULTIPLY = 3;
+var ADDITIVE_MODE_NONE = 4;
+
+aAddittiveModeInMap = {
+ 'base' : ADDITIVE_MODE_BASE,
+ 'sum' : ADDITIVE_MODE_SUM,
+ 'replace' : ADDITIVE_MODE_REPLACE,
+ 'multiply' : ADDITIVE_MODE_MULTIPLY,
+ 'none' : ADDITIVE_MODE_NONE
+};
+
+aAddittiveModeOutMap = [ 'base', 'sum', 'replace', 'multiply', 'none' ];
+
+
+// Accumulate Modes
+var ACCUMULATE_MODE_NONE = 0;
+var ACCUMULATE_MODE_SUM = 1;
+
+aAccumulateModeOutMap = [ 'none', 'sum' ];
+
+// Calculation Modes
+var CALC_MODE_DISCRETE = 0;
+var CALC_MODE_LINEAR = 1;
+var CALC_MODE_PACED = 2;
+var CALC_MODE_SPLINE = 3;
+
+aCalcModeInMap = {
+ 'discrete' : CALC_MODE_DISCRETE,
+ 'linear' : CALC_MODE_LINEAR,
+ 'paced' : CALC_MODE_PACED,
+ 'spline' : CALC_MODE_SPLINE
+};
+
+aCalcModeOutMap = [ 'discrete', 'linear', 'paced', 'spline' ];
+
+
+// Color Spaces
+var COLOR_SPACE_RGB = 0;
+var COLOR_SPACE_HSL = 1;
+
+aColorSpaceInMap = { 'rgb': COLOR_SPACE_RGB, 'hsl': COLOR_SPACE_HSL };
+
+aColorSpaceOutMap = [ 'rgb', 'hsl' ];
+
+
+// Clock Directions
+var CLOCKWISE = 0;
+var COUNTERCLOCKWISE = 1;
+
+aClockDirectionInMap = { 'clockwise': CLOCKWISE, 'counterclockwise': COUNTERCLOCKWISE };
+
+aClockDirectionOutMap = [ 'clockwise', 'counterclockwise' ];
+
+
+// Attribute Value Types
+UNKNOWN_PROPERTY = 0;
+NUMBER_PROPERTY = 1;
+ENUM_PROPERTY = 2;
+COLOR_PROPERTY = 3;
+STRING_PROPERTY = 4;
+BOOL_PROPERTY = 5;
+
+aValueTypeOutMap = [ 'unknown', 'number', 'enum', 'color', 'string', 'boolean' ];
+
+
+// Attribute Map
+var aAttributeMap =
+{
+ 'height': { 'type': NUMBER_PROPERTY,
+ 'get': 'getHeight',
+ 'set': 'setHeight',
+ 'getmod': 'makeScaler( 1/nHeight )',
+ 'setmod': 'makeScaler( nHeight)' },
+
+ 'opacity': { 'type': NUMBER_PROPERTY,
+ 'get': 'getOpacity',
+ 'set': 'setOpacity' },
+
+ 'width': { 'type': NUMBER_PROPERTY,
+ 'get': 'getWidth',
+ 'set': 'setWidth',
+ 'getmod': 'makeScaler( 1/nWidth )',
+ 'setmod': 'makeScaler( nWidth)' },
+
+ 'x': { 'type': NUMBER_PROPERTY,
+ 'get': 'getX',
+ 'set': 'setX',
+ 'getmod': 'makeScaler( 1/nWidth )',
+ 'setmod': 'makeScaler( nWidth)' },
+
+ 'y': { 'type': NUMBER_PROPERTY,
+ 'get': 'getY',
+ 'set': 'setY',
+ 'getmod': 'makeScaler( 1/nHeight )',
+ 'setmod': 'makeScaler( nHeight)' },
+
+ 'fill': { 'type': ENUM_PROPERTY,
+ 'get': 'getFillStyle',
+ 'set': 'setFillStyle' },
+
+ 'stroke': { 'type': ENUM_PROPERTY,
+ 'get': 'getStrokeStyle',
+ 'set': 'setStrokeStyle' },
+
+ 'visibility': { 'type': ENUM_PROPERTY,
+ 'get': 'getVisibility',
+ 'set': 'setVisibility' },
+
+ 'fill-color': { 'type': COLOR_PROPERTY,
+ 'get': 'getFillColor',
+ 'set': 'setFillColor' },
+
+ 'stroke-color': { 'type': COLOR_PROPERTY,
+ 'get': 'getStrokeColor',
+ 'set': 'setStrokeColor' },
+
+ 'color': { 'type': COLOR_PROPERTY,
+ 'get': 'getFontColor',
+ 'set': 'setFontColor' },
+
+};
+
+
+// Transition Types
+BARWIPE_TRANSITION = 1;
+FADE_TRANSITION = 2; // 37
+
+aTransitionTypeInMap = {
+ 'barWipe' : BARWIPE_TRANSITION,
+ 'fade' : FADE_TRANSITION
+};
+
+aTransitionTypeOutMap = [ '', 'barWipe', 'fade' ];
+
+
+// Transition Subtypes
+DEFAULT_TRANS_SUBTYPE = 0;
+LEFTTORIGHT_TRANS_SUBTYPE = 1;
+TOPTOBOTTOM_TRANS_SUBTYPE = 2;
+CROSSFADE_TRANS_SUBTYPE = 3; // 101
+
+aTransitionSubtypeInMap = {
+ 'leftToRight' : LEFTTORIGHT_TRANS_SUBTYPE,
+ 'topToBottom' : TOPTOBOTTOM_TRANS_SUBTYPE,
+ 'crossfade' : CROSSFADE_TRANS_SUBTYPE
+};
+
+aTransitionSubtypeOutMap = [ 'default', 'leftToRight', 'topToBottom', 'crossfade' ];
+
+
+// Transition Modes
+TRANSITION_MODE_IN = 1;
+TRANSITION_MODE_OUT = 0;
+
+aTransitionModeInMap = { 'out': TRANSITION_MODE_OUT, 'in': TRANSITION_MODE_IN };
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list