[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