<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cr_html.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 20:04:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <fstream>
#include "cr_html.hxx"
#include "xmltree.hxx"
#include "../support/syshelp.hxx"

char C_sHtmlFileHeader1[] =
    "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n"
    "\n"
    "\n"
    "   <TITLE>";

char C_sHtmlFileHeader2[] =
        "</TITLE>\n"
    "       <META NAME=\"GENERATOR\" CONTENT=\"xml2cmp\">\n"
    "\n"
    "\n

";

char C_sHtmlFileFoot[] = "\n\n";

HtmlCreator::HtmlCreator( const char *              i_pOutputFileName,
                          const XmlElement &        i_rDocument,
                          const Simstr &            i_sIDL_BaseDirectory )
    :   aFile(i_pOutputFileName, std::ios::out
#ifdef WNT
                                               | std::ios::binary
#endif
                                                             ),
        rDocument(i_rDocument),
        sIdl_BaseDirectory(i_sIDL_BaseDirectory)
{
    if ( !aFile )
    {
        std::cerr << "Error: " << i_pOutputFileName << " could not be created." << std::endl;
        exit(0);
    }
}

HtmlCreator::~HtmlCreator()
{
    aFile.close();
}

void
HtmlCreator::Run()
{
    WriteStr( C_sHtmlFileHeader1 );
    WriteStr( "ModuleDescription" );
    WriteStr( C_sHtmlFileHeader2 );

    rDocument.Write2Html(*this);

    WriteStr( "

\n" );
    WriteStr( C_sHtmlFileFoot );
}

void
HtmlCreator::StartTable()
{
    WriteStr( "

\n" );
    WriteStr(
            "
\n"
            "
\n"  );
}

void
HtmlCreator::FinishTable()
{
    WriteStr( "
\n"
              "
\n\n" );
}

void
HtmlCreator::StartBigCell( const char * i_sTitle )
{
    WriteStr( "
\n"
              "

" );
    WriteStr( i_sTitle );
    WriteStr( "
\n" );

}

void
HtmlCreator::FinishBigCell()
{
    WriteStr( "
\n" );
}

void
HtmlCreator::Write_SglTextElement( const SglTextElement &  i_rElement,
                                   bool                    i_bStrong )
{
    StartRow();

    WriteElementName( i_rElement.Name(), i_bStrong );

    StartCell( "77%");
    if (i_bStrong)
    {
        WriteStr( "
" );
    }

    WriteName( aFile, sIdl_BaseDirectory, i_rElement.Data(),
               i_bStrong ? lt_nolink : i_rElement.LinkType() );

    if (i_bStrong)
        WriteStr( "
" );
    FinishCell();

    FinishRow();
}

void
HtmlCreator::Write_MultiTextElement( const MultipleTextElement &    i_rElement )
{
    StartRow();

    WriteElementName( i_rElement.Name(), false );

    StartCell( "77%");
    unsigned i_max = i_rElement.Size();
    for ( unsigned i = 0; i < i_max; ++i )
    {
        if (i > 0)
            WriteStr( "
\n" );
        WriteName( aFile, sIdl_BaseDirectory, i_rElement.Data(i), i_rElement.LinkType() );
    }   // end for
    FinishCell();

    FinishRow();
}

void
HtmlCreator::Write_SglText( const Simstr &      i_sName,
                            const Simstr &      i_sValue )
{
    StartRow();

    WriteElementName( i_sName, false );

    StartCell( "77%");
    WriteStr( i_sValue );
    FinishCell();

    FinishRow();
}

void
HtmlCreator::Write_ReferenceDocu( const Simstr &      i_sName,
                                  const Simstr &      i_sRef,
                                  const Simstr &      i_sRole,
                                  const Simstr &      i_sTitle )
{
    StartRow();

    StartCell( "23%" );
    WriteStr(i_sName);
    FinishCell();

    StartCell( "77%" );
    if ( !i_sRef.is_empty() )
    {
        WriteStr("");
        if ( !i_sTitle.is_empty() )
            WriteStr( i_sTitle );
        else
            WriteStr(i_sRef);
        WriteStr("
\n");
    }
    else if ( !i_sTitle.is_empty() )
    {
        WriteStr("Title: ");
        WriteStr( i_sTitle );
        WriteStr("
\n");
    }
    if ( !i_sRole.is_empty() )
    {
        WriteStr("Role: ");
        WriteStr( i_sRole );
    }
    FinishCell();

    FinishRow();
}

void
HtmlCreator::PrintH1( const char * i_pText)
{
    static const char sH1a[] = "
";
    static const char sH1e[] = "
";
    WriteStr(sH1a);
    WriteStr(i_pText);
    WriteStr(sH1e);
}

void
HtmlCreator::StartRow()
{
    WriteStr( "
\n" );
}

void
HtmlCreator::FinishRow()
{
    WriteStr( "
\n" );
}

void
HtmlCreator::StartCell( const char * i_pWidth)
{
    WriteStr( "         \n
" );
}

void
HtmlCreator::FinishCell()
{
    WriteStr( "
\n           	\n" );
}

void
HtmlCreator::WriteElementName( const Simstr & i_sName,
                               bool           i_bStrong )
{
    StartCell( "23%" );
    if (i_bStrong)
        WriteStr( "
" );
    WriteStr(i_sName);
    if (i_bStrong)
        WriteStr( "
" );
    FinishCell();
}

<commit_msg>INTEGRATION: CWS obo05 (1.8.2); FILE MERGED 2006/06/27 13:15:59 obo 1.8.2.1: #i53611# port for .net 2005<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cr_html.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: vg $ $Date: 2006-09-25 13:26:08 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <fstream>
#include "cr_html.hxx"
#include "xmltree.hxx"
#include "../support/syshelp.hxx"

char C_sHtmlFileHeader1[] =
    "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n"
    "\n"
    "\n"
    "   <TITLE>";

char C_sHtmlFileHeader2[] =
        "</TITLE>\n"
    "       <META NAME=\"GENERATOR\" CONTENT=\"xml2cmp\">\n"
    "\n"
    "\n

";

char C_sHtmlFileFoot[] = "\n\n";

HtmlCreator::HtmlCreator( const char *              i_pOutputFileName,
                          const XmlElement &        i_rDocument,
                          const Simstr &            i_sIDL_BaseDirectory )
    :   aFile(i_pOutputFileName, std::ios::out
#ifdef WNT
                                               | std::ios::binary
#endif
                                                             ),
        rDocument(i_rDocument),
        sIdl_BaseDirectory(i_sIDL_BaseDirectory)
{
    if ( !aFile )
    {
        std::cerr << "Error: " << i_pOutputFileName << " could not be created." << std::endl;
        exit(0);
    }
}

HtmlCreator::~HtmlCreator()
{
    aFile.close();
}

void
HtmlCreator::Run()
{
    WriteStr( C_sHtmlFileHeader1 );
    WriteStr( "ModuleDescription" );
    WriteStr( C_sHtmlFileHeader2 );

    rDocument.Write2Html(*this);

    WriteStr( "

\n" );
    WriteStr( C_sHtmlFileFoot );
}

void
HtmlCreator::StartTable()
{
    WriteStr( "

\n" );
    WriteStr(
            "
\n"
            "
\n"  );
}

void
HtmlCreator::FinishTable()
{
    WriteStr( "
\n"
              "
\n\n" );
}

void
HtmlCreator::StartBigCell( const char * i_sTitle )
{
    WriteStr( "
\n"
              "

" );
    WriteStr( i_sTitle );
    WriteStr( "
\n" );

}

void
HtmlCreator::FinishBigCell()
{
    WriteStr( "
\n" );
}

void
HtmlCreator::Write_SglTextElement( const SglTextElement &  i_rElement,
                                   bool                    i_bStrong )
{
    StartRow();

    WriteElementName( i_rElement.Name(), i_bStrong );

    StartCell( "77%");
    if (i_bStrong)
    {
        WriteStr( "
" );
    }

    WriteName( aFile, sIdl_BaseDirectory, i_rElement.Data(),
               i_bStrong ? lt_nolink : i_rElement.LinkType() );

    if (i_bStrong)
        WriteStr( "
" );
    FinishCell();

    FinishRow();
}

void
HtmlCreator::Write_MultiTextElement( const MultipleTextElement &    i_rElement )
{
    StartRow();

    WriteElementName( i_rElement.Name(), false );

    StartCell( "77%");
    unsigned i_max = i_rElement.Size();
    for ( unsigned i = 0; i < i_max; ++i )
    {
        if (i > 0)
            WriteStr( "
\n" );
        WriteName( aFile, sIdl_BaseDirectory, i_rElement.Data(i), i_rElement.LinkType() );
    }   // end for
    FinishCell();

    FinishRow();
}

void
HtmlCreator::Write_SglText( const Simstr &      i_sName,
                            const Simstr &      i_sValue )
{
    StartRow();

    WriteElementName( i_sName, false );

    StartCell( "77%");
    WriteStr( i_sValue );
    FinishCell();

    FinishRow();
}

void
HtmlCreator::Write_ReferenceDocu( const Simstr &      i_sName,
                                  const Simstr &      i_sRef,
                                  const Simstr &      i_sRole,
                                  const Simstr &      i_sTitle )
{
    StartRow();

    StartCell( "23%" );
    WriteStr(i_sName);
    FinishCell();

    StartCell( "77%" );
    if ( !i_sRef.is_empty() )
    {
        WriteStr("");
        if ( !i_sTitle.is_empty() )
            WriteStr( i_sTitle );
        else
            WriteStr(i_sRef);
        WriteStr("
\n");
    }
    else if ( !i_sTitle.is_empty() )
    {
        WriteStr("Title: ");
        WriteStr( i_sTitle );
        WriteStr("
\n");
    }
    if ( !i_sRole.is_empty() )
    {
        WriteStr("Role: ");
        WriteStr( i_sRole );
    }
    FinishCell();

    FinishRow();
}

void
HtmlCreator::PrintH1( const char * i_pText)
{
    static const char sH1a[] = "
";
    static const char sH1e[] = "
";
    WriteStr(sH1a);
    WriteStr(i_pText);
    WriteStr(sH1e);
}

void
HtmlCreator::StartRow()
{
    WriteStr( "
\n" );
}

void
HtmlCreator::FinishRow()
{
    WriteStr( "
\n" );
}

void
HtmlCreator::StartCell( const char * i_pWidth)
{
    WriteStr( "         \n
" );
}

void
HtmlCreator::FinishCell()
{
    WriteStr( "
\n           	\n" );
}

void
HtmlCreator::WriteElementName( const Simstr & i_sName,
                               bool           i_bStrong )
{
    StartCell( "23%" );
    if (i_bStrong)
        WriteStr( "
" );
    WriteStr(i_sName);
    if (i_bStrong)
        WriteStr( "
" );
    FinishCell();
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlmetae.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: vg $ $Date: 2007-04-11 13:33:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLMETAE_HXX
#define _XMLOFF_XMLMETAE_HXX

#ifndef _SAL_CONFIG_H_
#include "sal/config.h"
#endif

#ifndef INCLUDED_XMLOFF_DLLAPI_H
#include "xmloff/dllapi.h"
#endif

#ifndef _SAL_TYPES_H_
#include "sal/types.h"
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTINFO_HPP_
#include <com/sun/star/document/XDocumentInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP_
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_NAMEDVALUE_HPP_
#include <com/sun/star/beans/NamedValue.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_DATETIME_HPP_
#include <com/sun/star/util/DateTime.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_
#include <com/sun/star/lang/Locale.hpp>
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif

namespace com { namespace sun { namespace star { namespace frame {
    class XModel;
} } } }

class Time;
class SvXMLNamespaceMap;
class SvXMLAttributeList;
class SvXMLExport;

class XMLOFF_DLLPUBLIC SfxXMLMetaExport
{
private:
    SvXMLExport&                                        rExport;
    ::com::sun::star::uno::Reference<
        ::com::sun::star::document::XDocumentInfo>      xDocInfo;
    ::com::sun::star::uno::Reference<
        ::com::sun::star::beans::XPropertySet>          xInfoProp;
    ::com::sun::star::lang::Locale                      aLocale;
    ::com::sun::star::uno::Sequence<
        ::com::sun::star::beans::NamedValue>            aDocStatistic;

    SAL_DLLPRIVATE void SimpleStringElement(
        const ::rtl::OUString& rPropertyName, sal_uInt16 nNamespace,
        enum ::xmloff::token::XMLTokenEnum eElementName );
    SAL_DLLPRIVATE void SimpleDateTimeElement(
        const ::rtl::OUString& rPropertyName, sal_uInt16 nNamespace,
        enum ::xmloff::token::XMLTokenEnum eElementName );

public:
    SfxXMLMetaExport( SvXMLExport& rExport,
                      const ::com::sun::star::uno::Reference<
                        ::com::sun::star::frame::XModel>& rDocModel );
    SfxXMLMetaExport( SvXMLExport& rExport,
                      const ::com::sun::star::uno::Reference<
                        ::com::sun::star::document::XDocumentInfo>& rDocInfo );

    virtual ~SfxXMLMetaExport();

    // core API
    void Export();

    static ::rtl::OUString GetISODateTimeString(
                        const ::com::sun::star::util::DateTime& rDateTime );
};

#endif // _XMLOFF_XMLMETAE_HXX

<commit_msg>INTEGRATION: CWS custommeta (1.2.132); FILE MERGED 2007/12/18 15:53:49 mst 1.2.132.2: - xmloff/inc/xmloff/xmlmetae.hxx, xmloff/source/meta/xmlmetae.cxx,   xmloff/source/meta/xmlversion.cxx:   + remove class SfxXMLMetaExport; replaced by SvXMLMetaExport   + SvXMLMetaExport::_Export replaces SfxXMLMetaExport::Export,     uses XDocumentProperties instead of XDocumentInfo 2007/12/07 18:51:47 mst 1.2.132.1: refactoring to use XDocumentProperties instead of XDocumentInfo on document export: - xmloff/inc/xmloff/xmlexp.hxx, xmloff/source/core/xmlexp.cxx:   + turn lcl_GetProductName into static method SvXMLExport::GetProductName   + updating of Generator string is now done in _ExportMeta - xmloff/inc/MetaExportComponent.hxx, source/meta/MetaExportComponent.cxx:   + use XDocumentProperties instead of XDocumentInfo   + override _ExportMeta - xmloff/inc/xmloff/xmlmetae.hxx, source/meta/xmlmetae.cxx:   + new class SvXMLMetaExport, to eventually replace SfxXMLMetaExport   + move lcl_GetProductName to xmlexp.cxx<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xmlmetae.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2008-02-26 13:30:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLMETAE_HXX
#define _XMLOFF_XMLMETAE_HXX

#ifndef _SAL_CONFIG_H_
#include "sal/config.h"
#endif

#ifndef INCLUDED_XMLOFF_DLLAPI_H
#include "xmloff/dllapi.h"
#endif

#ifndef _SAL_TYPES_H_
#include "sal/types.h"
#endif

#include <cppuhelper/implbase1.hxx>
#include <xmloff/xmltoken.hxx>

#include <vector>

#include <com/sun/star/beans/StringPair.hpp>
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/document/XDocumentProperties.hpp>

class SvXMLExport;

/** export meta data from an <type>XDocumentProperties</type> instance.

    This class will start the export at the office:meta element,
    not at the root element. This means that when <method>Export</method>
    is called here, the document root element must already be written, but
    office:meta must not be written.

 */
class XMLOFF_DLLPUBLIC SvXMLMetaExport : public ::cppu::WeakImplHelper1<
                ::com::sun::star::xml::sax::XDocumentHandler >
{
private:
    SvXMLExport& mrExport;
    ::com::sun::star::uno::Reference<
        ::com::sun::star::document::XDocumentProperties> mxDocProps;
    /// counts levels of the xml document. necessary for special handling.
    int m_level;
    /// preserved namespaces. necessary because we do not write the root node.
    std::vector< ::com::sun::star::beans::StringPair > m_preservedNSs;

    SAL_DLLPRIVATE void SimpleStringElement(
        const ::rtl::OUString& rText, sal_uInt16 nNamespace,
        enum ::xmloff::token::XMLTokenEnum eElementName );
    SAL_DLLPRIVATE void SimpleDateTimeElement(
        const ::com::sun::star::util::DateTime & rDate, sal_uInt16 nNamespace,
        enum ::xmloff::token::XMLTokenEnum eElementName );

    /// currently unused; for exporting via the XDocumentProperties interface
    SAL_DLLPRIVATE void _Export();

public:
    SvXMLMetaExport( SvXMLExport& i_rExport,
        const ::com::sun::star::uno::Reference<
                ::com::sun::star::document::XDocumentProperties>& i_rDocProps);

    virtual ~SvXMLMetaExport();

    /// export via XSAXWriter interface, with fallback to _Export
    void Export();

    static ::rtl::OUString GetISODateTimeString(
                        const ::com::sun::star::util::DateTime& rDateTime );

    // ::com::sun::star::xml::sax::XDocumentHandler:
    virtual void SAL_CALL startDocument()
        throw (::com::sun::star::uno::RuntimeException,
               ::com::sun::star::xml::sax::SAXException);
    virtual void SAL_CALL endDocument()
        throw (::com::sun::star::uno::RuntimeException,
               ::com::sun::star::xml::sax::SAXException);
    virtual void SAL_CALL startElement(const ::rtl::OUString & i_rName,
        const ::com::sun::star::uno::Reference<
                ::com::sun::star::xml::sax::XAttributeList > & i_xAttribs)
        throw (::com::sun::star::uno::RuntimeException,
               ::com::sun::star::xml::sax::SAXException);
    virtual void SAL_CALL endElement(const ::rtl::OUString & i_rName)
        throw (::com::sun::star::uno::RuntimeException,
               ::com::sun::star::xml::sax::SAXException);
    virtual void SAL_CALL characters(const ::rtl::OUString & i_rChars)
        throw (::com::sun::star::uno::RuntimeException,
               ::com::sun::star::xml::sax::SAXException);
    virtual void SAL_CALL ignorableWhitespace(
        const ::rtl::OUString & i_rWhitespaces)
        throw (::com::sun::star::uno::RuntimeException,
               ::com::sun::star::xml::sax::SAXException);
    virtual void SAL_CALL processingInstruction(
        const ::rtl::OUString & i_rTarget, const ::rtl::OUString & i_rData)
        throw (::com::sun::star::uno::RuntimeException,
               ::com::sun::star::xml::sax::SAXException);
    virtual void SAL_CALL setDocumentLocator(
        const ::com::sun::star::uno::Reference<
                ::com::sun::star::xml::sax::XLocator > & i_xLocator)
        throw (::com::sun::star::uno::RuntimeException,
               ::com::sun::star::xml::sax::SAXException);

};

#endif // _XMLOFF_XMLMETAE_HXX

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    PlaneSrc.cc
  Language:  C++
  Date:      5/15/94
  Version:   1.12

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkPlaneSource.hh"
#include "vtkFloatPoints.hh"
#include "vtkFloatNormals.hh"
#include "vtkFloatTCoords.hh"
#include "vtkMath.hh"

static vtkMath math;

// Description:
// Construct plane perpendicular to z-axis, resolution 1x1, width and height 1.0,
// and centered at the origin.
vtkPlaneSource::vtkPlaneSource()
{
  this->XResolution = 1;
  this->YResolution = 1;

  this->Origin[0] = this->Origin[1] = -0.5;
  this->Origin[2] = 0.0;

  this->Point1[0] = 0.5;
  this->Point1[1] = -0.5;
  this->Point1[2] = 0.0;

  this->Point2[0] = -0.5;
  this->Point2[1] = 0.5;
  this->Point2[2] = 0.0;

  this->Normal[2] = 1.0;
  this->Normal[0] = this->Normal[1] = 0.0;
}

// Description:
// Set the number of x-y subdivisions in the plane.
void vtkPlaneSource::SetResolution(const int xR, const int yR)
{
  if ( xR != this->XResolution || yR != this->YResolution )
    {
    this->XResolution = xR;
    this->YResolution = yR;

    this->XResolution = (this->XResolution > 0 ? this->XResolution : 1);
    this->YResolution = (this->YResolution > 0 ? this->YResolution : 1);

    this->Modified();
    }
}

void vtkPlaneSource::Execute()
{
  float x[3], tc[2], v1[3], v2[3];
  int pts[4];
  int i, j, ii;
  int numPts;
  int numPolys;
  vtkFloatPoints *newPoints;
  vtkFloatNormals *newNormals;
  vtkFloatTCoords *newTCoords;
  vtkCellArray *newPolys;
  vtkPolyData *output = this->GetOutput();

  // Check input
  for ( i=0; i < 3; i++ )
    {
    v1[i] = this->Point1[i] - this->Origin[i];
    v2[i] = this->Point2[i] - this->Origin[i];
    }
  if ( !this->UpdateNormal(v1,v2) ) return;

  //
  // Set things up; allocate memory
  //
  numPts = (this->XResolution+1) * (this->YResolution+1);
  numPolys = this->XResolution * this->YResolution;

  newPoints = new vtkFloatPoints(numPts);
  newNormals = new vtkFloatNormals(numPts);
  newTCoords = new vtkFloatTCoords(numPts,2);

  newPolys = new vtkCellArray;
  newPolys->Allocate(newPolys->EstimateSize(numPolys,4));
//
// Generate points and point data
//
  for (numPts=0, i=0; i<(this->YResolution+1); i++)
    {
    tc[1] = (float) i / this->YResolution;
    for (j=0; j<(this->XResolution+1); j++)
      {
      tc[0] = (float) j / this->XResolution;

      for ( ii=0; ii < 3; ii++)
        {
        x[ii] = this->Origin[ii] + tc[0]*v1[ii] + tc[1]*v2[ii];
        }

      newPoints->InsertPoint(numPts,x);
      newTCoords->InsertTCoord(numPts,tc);
      newNormals->InsertNormal(numPts++,this->Normal);
      }
    }
//
// Generate polygon connectivity
//
  for (i=0; i<this->YResolution; i++)
    {
    for (j=0; j<this->XResolution; j++)
      {
      pts[0] = j + i*(this->XResolution+1);
      pts[1] = pts[0] + 1;
      pts[2] = pts[0] + this->XResolution + 2;
      pts[3] = pts[0] + this->XResolution + 1;
      newPolys->InsertNextCell(4,pts);
      }
    }
//
// Update ourselves and release memory
//
  output->SetPoints(newPoints);
  newPoints->Delete();

  output->GetPointData()->SetNormals(newNormals);
  newNormals->Delete();

  output->GetPointData()->SetTCoords(newTCoords);
  newTCoords->Delete();

  output->SetPolys(newPolys);
  newPolys->Delete();
}

// Description:
// Set the normal to the plane. Will modify the Origin, Point1, and Point2
// instance variables are necessary (i.e., rotate the plane around its center).
void vtkPlaneSource::SetNormal(float N[3])
{
  float n[3], v1[3], v2[3], center[3];
  float rotVector[3];
  int i;

  // compute plane axes
  for ( i=0; i < 3; i++)
    {
    n[i] = N[i];
    v1[i] = (this->Point1[i] - this->Origin[i]) / 2.0;
    v2[i] = (this->Point2[i] - this->Origin[i]) / 2.0;
    center[i] = this->Origin[i] + v1[i] + v2[i];
    }

  //make sure input is decent
  if ( math.Normalize(n) == 0.0 )
    {
    vtkErrorMacro(<<"Specified zero normal");
    return;
    }
  if ( !this->UpdateNormal(v1,v2) ) return;

  //compute rotation vector
  math.Cross(this->Normal,n,rotVector);
  if ( math.Normalize(rotVector) == 0.0 ) return; //no rotation

  // determine components of rotation around the three axes

}

// Description:
// Set the normal to the plane. Will modify the Origin, Point1, and Point2
// instance variables are necessary (i.e., rotate the plane around its center).
void vtkPlaneSource::SetNormal(float nx, float ny, float nz)
{
  float n[3];

  n[0] = nx; n[1] = ny; n[2] = nz;
  this->SetNormal(n);
}

// Description:
// Translate the plane in the direction of the normal by the distance specified.
// Negative values move the plane in the opposite direction.
void vtkPlaneSource::Push(float distance)
{
  if ( distance == 0.0 ) return;

  for ( int i=0; i < 3; i++ )
    {
    this->Origin[i] += distance * this->Normal[i];
    this->Point1[i] += distance * this->Normal[i];
    this->Point2[i] += distance * this->Normal[i];
    }

  this->Modified();
}

// Protected method updates normals from two axes.
int vtkPlaneSource::UpdateNormal(float v1[3], float v2[3])
{
  math.Cross(v1,v2,this->Normal);
  if ( math.Normalize(this->Normal) == 0.0 )
    {
    vtkErrorMacro(<<"Bad plane coordinate system");
    return 0;
    }
  else
    {
    return 1;
    }
}

void vtkPlaneSource::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolySource::PrintSelf(os,indent);

  os << indent << "X Resolution: " << this->XResolution << "\n";
  os << indent << "Y Resolution: " << this->YResolution << "\n";

  os << indent << "Origin: (" << this->Origin[0] << ", "
                              << this->Origin[1] << ", "
                              << this->Origin[2] << ")\n";

  os << indent << "Point 1: (" << this->Point1[0] << ", "
                               << this->Point1[1] << ", "
                               << this->Point1[2] << ")\n";

  os << indent << "Point 2: (" << this->Point2[0] << ", "
                               << this->Point2[1] << ", "
                               << this->Point2[2] << ")\n";

  os << indent << "Normal: (" << this->Normal[0] << ", "
                              << this->Normal[1] << ", "
                              << this->Normal[2] << ")\n";

}
<commit_msg>ENH: Got Normal and Center working.<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    vtkPlaneSource.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute
this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. Additionally, the
authors grant permission to modify this software and its documentation for
any purpose, provided that such modifications are not distributed without
the explicit consent of the authors and that existing copyright notices are
retained in all copies.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

=========================================================================*/
#include "vtkPlaneSource.hh"
#include "vtkFloatPoints.hh"
#include "vtkFloatNormals.hh"
#include "vtkFloatTCoords.hh"
#include "vtkMath.hh"
#include "vtkTransform.hh"

static vtkMath math;

// Description:
// Construct plane perpendicular to z-axis, resolution 1x1, width and height 1.0,
// and centered at the origin.
vtkPlaneSource::vtkPlaneSource()
{
  this->XResolution = 1;
  this->YResolution = 1;

  this->Origin[0] = this->Origin[1] = -0.5;
  this->Origin[2] = 0.0;

  this->Point1[0] = 0.5;
  this->Point1[1] = -0.5;
  this->Point1[2] = 0.0;

  this->Point2[0] = -0.5;
  this->Point2[1] = 0.5;
  this->Point2[2] = 0.0;

  this->Normal[2] = 1.0;
  this->Normal[0] = this->Normal[1] = 0.0;

  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;
}

// Description:
// Set the number of x-y subdivisions in the plane.
void vtkPlaneSource::SetResolution(const int xR, const int yR)
{
  if ( xR != this->XResolution || yR != this->YResolution )
    {
    this->XResolution = xR;
    this->YResolution = yR;

    this->XResolution = (this->XResolution > 0 ? this->XResolution : 1);
    this->YResolution = (this->YResolution > 0 ? this->YResolution : 1);

    this->Modified();
    }
}

void vtkPlaneSource::Execute()
{
  float x[3], tc[2], v1[3], v2[3];
  int pts[4];
  int i, j, ii;
  int numPts;
  int numPolys;
  vtkFloatPoints *newPoints;
  vtkFloatNormals *newNormals;
  vtkFloatTCoords *newTCoords;
  vtkCellArray *newPolys;
  vtkPolyData *output = this->GetOutput();

  // Check input
  for ( i=0; i < 3; i++ )
    {
    v1[i] = this->Point1[i] - this->Origin[i];
    v2[i] = this->Point2[i] - this->Origin[i];
    }
  if ( !this->UpdatePlane(v1,v2) ) return;

  //
  // Set things up; allocate memory
  //
  numPts = (this->XResolution+1) * (this->YResolution+1);
  numPolys = this->XResolution * this->YResolution;

  newPoints = new vtkFloatPoints(numPts);
  newNormals = new vtkFloatNormals(numPts);
  newTCoords = new vtkFloatTCoords(numPts,2);

  newPolys = new vtkCellArray;
  newPolys->Allocate(newPolys->EstimateSize(numPolys,4));
//
// Generate points and point data
//
  for (numPts=0, i=0; i<(this->YResolution+1); i++)
    {
    tc[1] = (float) i / this->YResolution;
    for (j=0; j<(this->XResolution+1); j++)
      {
      tc[0] = (float) j / this->XResolution;

      for ( ii=0; ii < 3; ii++)
        {
        x[ii] = this->Origin[ii] + tc[0]*v1[ii] + tc[1]*v2[ii];
        }

      newPoints->InsertPoint(numPts,x);
      newTCoords->InsertTCoord(numPts,tc);
      newNormals->InsertNormal(numPts++,this->Normal);
      }
    }
//
// Generate polygon connectivity
//
  for (i=0; i<this->YResolution; i++)
    {
    for (j=0; j<this->XResolution; j++)
      {
      pts[0] = j + i*(this->XResolution+1);
      pts[1] = pts[0] + 1;
      pts[2] = pts[0] + this->XResolution + 2;
      pts[3] = pts[0] + this->XResolution + 1;
      newPolys->InsertNextCell(4,pts);
      }
    }
//
// Update ourselves and release memory
//
  output->SetPoints(newPoints);
  newPoints->Delete();

  output->GetPointData()->SetNormals(newNormals);
  newNormals->Delete();

  output->GetPointData()->SetTCoords(newTCoords);
  newTCoords->Delete();

  output->SetPolys(newPolys);
  newPolys->Delete();
}

// Description:
// Set the normal to the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., rotate the plane around its center).
void vtkPlaneSource::SetNormal(float N[3])
{
  float n[3], v1[3], v2[3], p[4];
  float rotVector[3], theta;
  int i;
  vtkTransform transform;

  // compute plane axes
  for ( i=0; i < 3; i++)
    {
    n[i] = N[i];
    v1[i] = this->Point1[i] - this->Origin[i];
    v2[i] = this->Point2[i] - this->Origin[i];
    }

  //make sure input is decent
  if ( math.Normalize(n) == 0.0 )
    {
    vtkErrorMacro(<<"Specified zero normal");
    return;
    }
  if ( !this->UpdatePlane(v1,v2) ) return;

  //compute rotation vector
  math.Cross(this->Normal,n,rotVector);
  if ( math.Normalize(rotVector) == 0.0 ) return; //no rotation
  theta = acos((double)math.Dot(this->Normal,n)) / math.DegreesToRadians();

  // create rotation matrix
  transform.PostMultiply();

  transform.Translate(-this->Center[0],-this->Center[1],-this->Center[2]);
  transform.RotateWXYZ(theta,rotVector[0],rotVector[1],rotVector[2]);
  transform.Translate(this->Center[0],this->Center[1],this->Center[2]);

  // transform the three defining points
  transform.SetPoint(this->Origin[0],this->Origin[1],this->Origin[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Origin[i] = p[i] / p[3];

  transform.SetPoint(this->Point1[0],this->Point1[1],this->Point1[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Point1[i] = p[i] / p[3];

  transform.SetPoint(this->Point2[0],this->Point2[1],this->Point2[2],1.0);
  transform.GetPoint(p);
  for (i=0; i < 3; i++) this->Point2[i] = p[i] / p[3];

  this->Modified();
}

// Description:
// Set the normal to the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., rotate the plane around its center).
void vtkPlaneSource::SetNormal(float nx, float ny, float nz)
{
  float n[3];

  n[0] = nx; n[1] = ny; n[2] = nz;
  this->SetNormal(n);
}

// Description:
// Set the center of the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., translate the plane).
void vtkPlaneSource::SetCenter(float center[3])
{
  if ( this->Center[0] == center[0] && this->Center[1] == center[1] &&
  this->Center[2] == center[2] )
    {
    return; //no change
    }
  else
    {
    float d;

    for ( int i=0; i < 3; i++ )
      {
      d = center[i] - this->Center[i];
      this->Center[i] = center[i];
      this->Origin[i] += d;
      this->Point1[i] += d;
      this->Point2[i] += d;
      }
    this->Modified();
    }
}

// Description:
// Set the center of the plane. Will modify the Origin, Point1, and Point2
// instance variables as necessary (i.e., translate the plane).
void vtkPlaneSource::SetCenter(float x, float y, float z)
{
  float center[3];

  center[0] = x; center[1] = y; center[2] = z;
  this->SetCenter(center);
}

// Description:
// Translate the plane in the direction of the normal by the distance specified.
// Negative values move the plane in the opposite direction.
void vtkPlaneSource::Push(float distance)
{
  if ( distance == 0.0 ) return;

  for ( int i=0; i < 3; i++ )
    {
    this->Origin[i] += distance * this->Normal[i];
    this->Point1[i] += distance * this->Normal[i];
    this->Point2[i] += distance * this->Normal[i];
    }

  this->Modified();
}

// Protected method updates normals and plane center from two axes.
int vtkPlaneSource::UpdatePlane(float v1[3], float v2[3])
{
  // set plane center
  for ( int i=0; i < 3; i++ )
    {
    this->Center[i] = this->Origin[i] + 0.5*(v1[i] + v2[i]);
    }

  // set plane normal
  math.Cross(v1,v2,this->Normal);
  if ( math.Normalize(this->Normal) == 0.0 )
    {
    vtkErrorMacro(<<"Bad plane coordinate system");
    return 0;
    }
  else
    {
    return 1;
    }
}

void vtkPlaneSource::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolySource::PrintSelf(os,indent);

  os << indent << "X Resolution: " << this->XResolution << "\n";
  os << indent << "Y Resolution: " << this->YResolution << "\n";

  os << indent << "Origin: (" << this->Origin[0] << ", "
                              << this->Origin[1] << ", "
                              << this->Origin[2] << ")\n";

  os << indent << "Point 1: (" << this->Point1[0] << ", "
                               << this->Point1[1] << ", "
                               << this->Point1[2] << ")\n";

  os << indent << "Point 2: (" << this->Point2[0] << ", "
                               << this->Point2[1] << ", "
                               << this->Point2[2] << ")\n";

  os << indent << "Normal: (" << this->Normal[0] << ", "
                              << this->Normal[1] << ", "
                              << this->Normal[2] << ")\n";

  os << indent << "Center: (" << this->Center[0] << ", "
                              << this->Center[1] << ", "
                              << this->Center[2] << ")\n";

}
<|endoftext|>


<commit_before>#include <assert.h>
#include <stdio.h>

#include "../ClipperUtils.hpp"
#include "../Geometry.hpp"
#include "../Layer.hpp"
#include "../Print.hpp"
#include "../PrintConfig.hpp"
#include "../Surface.hpp"

#include "FillBase.hpp"

namespace Slic3r {

// Generate infills for Slic3r::Layer::Region.
// The Slic3r::Layer::Region at this point of time may contain
// surfaces of various types (internal/bridge/top/bottom/solid).
// The infills are generated on the groups of surfaces with a compatible type.
// Returns an array of Slic3r::ExtrusionPath::Collection objects containing the infills generaed now
// and the thin fills generated by generate_perimeters().
void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
{
//    Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;

    double  fill_density           = layerm.region()->config.fill_density;
    Flow    infill_flow            = layerm.flow(frInfill);
    Flow    solid_infill_flow      = layerm.flow(frSolidInfill);
    Flow    top_solid_infill_flow  = layerm.flow(frTopSolidInfill);

    Surfaces surfaces;

    // merge adjacent surfaces
    // in case of bridge surfaces, the ones with defined angle will be attached to the ones
    // without any angle (shouldn't this logic be moved to process_external_surfaces()?)
    {
        SurfacesPtr surfaces_with_bridge_angle;
        surfaces_with_bridge_angle.reserve(layerm.fill_surfaces.surfaces.size());
        for (Surfaces::iterator it = layerm.fill_surfaces.surfaces.begin(); it != layerm.fill_surfaces.surfaces.end(); ++ it)
            if (it->bridge_angle >= 0)
                surfaces_with_bridge_angle.push_back(&(*it));

        // group surfaces by distinct properties (equal surface_type, thickness, thickness_layers, bridge_angle)
        // group is of type Slic3r::SurfaceCollection
        //FIXME: Use some smart heuristics to merge similar surfaces to eliminate tiny regions.
        std::vector<SurfacesPtr> groups;
        layerm.fill_surfaces.group(&groups);

        // merge compatible groups (we can generate continuous infill for them)
        {
            // cache flow widths and patterns used for all solid groups
            // (we'll use them for comparing compatible groups)
            std::vector<char>   is_solid(groups.size(), false);
            std::vector<float>  fw(groups.size(), 0.f);
            std::vector<int>    pattern(groups.size(), -1);
            for (size_t i = 0; i < groups.size(); ++ i) {
                // we can only merge solid non-bridge surfaces, so discard
                // non-solid surfaces
                const Surface &surface = *groups[i].front();
                if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
                    is_solid[i] = true;
                    fw[i] = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
                    pattern[i] = surface.is_external() ? layerm.region()->config.external_fill_pattern.value : ipRectilinear;
                }
            }
            // loop through solid groups
            for (size_t i = 0; i < groups.size(); ++ i) {
                if (is_solid[i]) {
                    // find compatible groups and append them to this one
                    for (size_t j = i + 1; j < groups.size(); ++ j) {
                        if (is_solid[j] && fw[i] == fw[j] && pattern[i] == pattern[j]) {
                            // groups are compatible, merge them
                            groups[i].insert(groups[i].end(), groups[j].begin(), groups[j].end());
                            groups.erase(groups.begin() + j);
                            is_solid.erase(is_solid.begin() + j);
                            fw.erase(fw.begin() + j);
                            pattern.erase(pattern.begin() + j);
                        }
                    }
                }
            }
        }

        // Give priority to bridges. Process the bridges in the first round, the rest of the surfaces in the 2nd round.
        for (size_t round = 0; round < 2; ++ round) {
            for (std::vector<SurfacesPtr>::iterator it_group = groups.begin(); it_group != groups.end(); ++ it_group) {
                const SurfacesPtr &group = *it_group;
                bool is_bridge = group.front()->bridge_angle >= 0;
                if (is_bridge != (round == 0))
                    continue;
                // Make a union of polygons defining the infiill regions of a group, use a safety offset.
                Polygons union_p = union_(to_polygons(*it_group), true);
                // Subtract surfaces having a defined bridge_angle from any other, use a safety offset.
                if (! surfaces_with_bridge_angle.empty() && it_group->front()->bridge_angle < 0)
                    union_p = diff(union_p, to_polygons(surfaces_with_bridge_angle), true);
                // subtract any other surface already processed
                //FIXME Vojtech: Because the bridge surfaces came first, they are subtracted twice!
                ExPolygons union_expolys = diff_ex(union_p, to_polygons(surfaces), true);
                for (ExPolygons::const_iterator it_expoly = union_expolys.begin(); it_expoly != union_expolys.end(); ++ it_expoly)
                    surfaces.push_back(Surface(*it_group->front(), *it_expoly));
            }
        }
    }

    // we need to detect any narrow surfaces that might collapse
    // when adding spacing below
    // such narrow surfaces are often generated in sloping walls
    // by bridge_over_infill() and combine_infill() as a result of the
    // subtraction of the combinable area from the layer infill area,
    // which leaves small areas near the perimeters
    // we are going to grow such regions by overlapping them with the void (if any)
    // TODO: detect and investigate whether there could be narrow regions without
    // any void neighbors
    {
        coord_t distance_between_surfaces = std::max(
            std::max(infill_flow.scaled_spacing(), solid_infill_flow.scaled_spacing()),
            top_solid_infill_flow.scaled_spacing());
        Polygons surfaces_polygons = to_polygons(surfaces);
        Polygons collapsed = diff(
            surfaces_polygons,
            offset2(surfaces_polygons, -distance_between_surfaces/2, +distance_between_surfaces/2),
            true);
        Polygons to_subtract;
        to_subtract.reserve(collapsed.size() + number_polygons(surfaces));
        for (Surfaces::const_iterator it_surface = surfaces.begin(); it_surface != surfaces.end(); ++ it_surface)
            if (it_surface->surface_type == stInternalVoid)
                polygons_append(to_subtract, *it_surface);
        polygons_append(to_subtract, collapsed);
        surfaces_append(
            surfaces,
            intersection_ex(
                offset(collapsed, distance_between_surfaces),
                to_subtract,
                true),
            stInternalSolid);
    }

    if (0) {
//        require "Slic3r/SVG.pm";
//        Slic3r::SVG::output("fill_" . $layerm->print_z . ".svg",
//            expolygons      => [ map $_->expolygon, grep !$_->is_solid, @surfaces ],
//            red_expolygons  => [ map $_->expolygon, grep  $_->is_solid, @surfaces ],
//        );
    }

    for (Surfaces::const_iterator surface_it = surfaces.begin(); surface_it != surfaces.end(); ++ surface_it) {
        const Surface &surface = *surface_it;
        if (surface.surface_type == stInternalVoid)
            continue;
        InfillPattern  fill_pattern = layerm.region()->config.fill_pattern.value;
        double         density      = fill_density;
        FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
            (surface.is_solid() ? frSolidInfill : frInfill);
        bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();

        if (surface.is_solid()) {
            density = 100;
            fill_pattern = (surface.is_external() && ! is_bridge) ?
                layerm.region()->config.external_fill_pattern.value :
                ipRectilinear;
        } else if (density <= 0)
            continue;

        // get filler object
        std::auto_ptr<Fill> f = std::auto_ptr<Fill>(Fill::new_from_type(fill_pattern));
        f->set_bounding_box(layerm.layer()->object()->bounding_box());

        // calculate the actual flow we'll be using for this infill
        coordf_t h = (surface.thickness == -1) ? layerm.layer()->height : surface.thickness;
        Flow flow = layerm.region()->flow(
            role,
            h,
            is_bridge || f->use_bridge_flow(),  // bridge flow?
            layerm.layer()->id() == 0,          // first layer?
            -1,                                 // auto width
            *layerm.layer()->object()
        );

        // calculate flow spacing for infill pattern generation
        bool using_internal_flow = false;
        if (! surface.is_solid() && ! is_bridge) {
            // it's internal infill, so we can calculate a generic flow spacing
            // for all layers, for avoiding the ugly effect of
            // misaligned infill on first layer because of different extrusion width and
            // layer height
            Flow internal_flow = layerm.region()->flow(
                frInfill,
                layerm.layer()->object()->config.layer_height.value,  // TODO: handle infill_every_layers?
                false,  // no bridge
                false,  // no first layer
                -1,     // auto width
                *layerm.layer()->object()
            );
            f->spacing = internal_flow.spacing();
            using_internal_flow = 1;
        } else {
            f->spacing = flow.spacing();
        }

        double link_max_length = 0.;
        if (! is_bridge) {
            link_max_length = layerm.region()->config.get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing());
//            printf("flow spacing: %f,  is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length);
        }

        f->layer_id = layerm.layer()->id();
        f->z = layerm.layer()->print_z;
        f->angle = Geometry::deg2rad(layerm.region()->config.fill_angle.value);
        // Maximum length of the perimeter segment linking two infill lines.
        f->link_max_length = scale_(link_max_length);
        // Used by the concentric infill pattern to clip the loops to create extrusion paths.
        f->loop_clipping = scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER;
//        f->layer_height = h;

        // apply half spacing using this flow's own spacing and generate infill
        FillParams params;
        params.density = 0.01 * density;
        params.dont_adjust = true;
        Polylines polylines = f->fill_surface(&surface, params);
        if (polylines.empty())
            continue;

        // calculate actual flow from spacing (which might have been adjusted by the infill
        // pattern generator)
        if (using_internal_flow) {
            // if we used the internal flow we're not doing a solid infill
            // so we can safely ignore the slight variation that might have
            // been applied to $f->flow_spacing
        } else {
            flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, h, is_bridge || f->use_bridge_flow());
        }

        // save into layer
        {
            ExtrusionRole role = is_bridge ? erBridgeInfill :
                (surface.is_solid() ? ((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) : erInternalInfill);
            ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
            out.entities.push_back(&collection);
            // Only concentric fills are not sorted.
            collection.no_sort = f->no_sort();
            for (Polylines::iterator it = polylines.begin(); it != polylines.end(); ++ it) {
                ExtrusionPath *path = new ExtrusionPath(role);
                collection.entities.push_back(path);
                path->polyline.points.swap(it->points);
                path->mm3_per_mm = flow.mm3_per_mm();
                path->width      = flow.width,
                path->height     = flow.height;
            }
        }
    }

    // add thin fill regions
    // thin_fills are of C++ Slic3r::ExtrusionEntityCollection, perl type Slic3r::ExtrusionPath::Collection
    // Unpacks the collection, creates multiple collections per path.
    // The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection.
    // Why the paths are unpacked?
    for (ExtrusionEntitiesPtr::iterator thin_fill = layerm.thin_fills.entities.begin(); thin_fill != layerm.thin_fills.entities.end(); ++ thin_fill) {
    #if 0
        out.entities.push_back((*thin_fill)->clone());
        assert(dynamic_cast<ExtrusionEntityCollection*>(out.entities.back()) != NULL);
    #else
        ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
        out.entities.push_back(&collection);
        collection.entities.push_back((*thin_fill)->clone());
    #endif
    }
}

} // namespace Slic3r
<commit_msg>Missing #include <memory><commit_after>#include <assert.h>
#include <stdio.h>
#include <memory>

#include "../ClipperUtils.hpp"
#include "../Geometry.hpp"
#include "../Layer.hpp"
#include "../Print.hpp"
#include "../PrintConfig.hpp"
#include "../Surface.hpp"

#include "FillBase.hpp"

namespace Slic3r {

// Generate infills for Slic3r::Layer::Region.
// The Slic3r::Layer::Region at this point of time may contain
// surfaces of various types (internal/bridge/top/bottom/solid).
// The infills are generated on the groups of surfaces with a compatible type.
// Returns an array of Slic3r::ExtrusionPath::Collection objects containing the infills generaed now
// and the thin fills generated by generate_perimeters().
void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
{
//    Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;

    double  fill_density           = layerm.region()->config.fill_density;
    Flow    infill_flow            = layerm.flow(frInfill);
    Flow    solid_infill_flow      = layerm.flow(frSolidInfill);
    Flow    top_solid_infill_flow  = layerm.flow(frTopSolidInfill);

    Surfaces surfaces;

    // merge adjacent surfaces
    // in case of bridge surfaces, the ones with defined angle will be attached to the ones
    // without any angle (shouldn't this logic be moved to process_external_surfaces()?)
    {
        SurfacesPtr surfaces_with_bridge_angle;
        surfaces_with_bridge_angle.reserve(layerm.fill_surfaces.surfaces.size());
        for (Surfaces::iterator it = layerm.fill_surfaces.surfaces.begin(); it != layerm.fill_surfaces.surfaces.end(); ++ it)
            if (it->bridge_angle >= 0)
                surfaces_with_bridge_angle.push_back(&(*it));

        // group surfaces by distinct properties (equal surface_type, thickness, thickness_layers, bridge_angle)
        // group is of type Slic3r::SurfaceCollection
        //FIXME: Use some smart heuristics to merge similar surfaces to eliminate tiny regions.
        std::vector<SurfacesPtr> groups;
        layerm.fill_surfaces.group(&groups);

        // merge compatible groups (we can generate continuous infill for them)
        {
            // cache flow widths and patterns used for all solid groups
            // (we'll use them for comparing compatible groups)
            std::vector<char>   is_solid(groups.size(), false);
            std::vector<float>  fw(groups.size(), 0.f);
            std::vector<int>    pattern(groups.size(), -1);
            for (size_t i = 0; i < groups.size(); ++ i) {
                // we can only merge solid non-bridge surfaces, so discard
                // non-solid surfaces
                const Surface &surface = *groups[i].front();
                if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
                    is_solid[i] = true;
                    fw[i] = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
                    pattern[i] = surface.is_external() ? layerm.region()->config.external_fill_pattern.value : ipRectilinear;
                }
            }
            // loop through solid groups
            for (size_t i = 0; i < groups.size(); ++ i) {
                if (is_solid[i]) {
                    // find compatible groups and append them to this one
                    for (size_t j = i + 1; j < groups.size(); ++ j) {
                        if (is_solid[j] && fw[i] == fw[j] && pattern[i] == pattern[j]) {
                            // groups are compatible, merge them
                            groups[i].insert(groups[i].end(), groups[j].begin(), groups[j].end());
                            groups.erase(groups.begin() + j);
                            is_solid.erase(is_solid.begin() + j);
                            fw.erase(fw.begin() + j);
                            pattern.erase(pattern.begin() + j);
                        }
                    }
                }
            }
        }

        // Give priority to bridges. Process the bridges in the first round, the rest of the surfaces in the 2nd round.
        for (size_t round = 0; round < 2; ++ round) {
            for (std::vector<SurfacesPtr>::iterator it_group = groups.begin(); it_group != groups.end(); ++ it_group) {
                const SurfacesPtr &group = *it_group;
                bool is_bridge = group.front()->bridge_angle >= 0;
                if (is_bridge != (round == 0))
                    continue;
                // Make a union of polygons defining the infiill regions of a group, use a safety offset.
                Polygons union_p = union_(to_polygons(*it_group), true);
                // Subtract surfaces having a defined bridge_angle from any other, use a safety offset.
                if (! surfaces_with_bridge_angle.empty() && it_group->front()->bridge_angle < 0)
                    union_p = diff(union_p, to_polygons(surfaces_with_bridge_angle), true);
                // subtract any other surface already processed
                //FIXME Vojtech: Because the bridge surfaces came first, they are subtracted twice!
                ExPolygons union_expolys = diff_ex(union_p, to_polygons(surfaces), true);
                for (ExPolygons::const_iterator it_expoly = union_expolys.begin(); it_expoly != union_expolys.end(); ++ it_expoly)
                    surfaces.push_back(Surface(*it_group->front(), *it_expoly));
            }
        }
    }

    // we need to detect any narrow surfaces that might collapse
    // when adding spacing below
    // such narrow surfaces are often generated in sloping walls
    // by bridge_over_infill() and combine_infill() as a result of the
    // subtraction of the combinable area from the layer infill area,
    // which leaves small areas near the perimeters
    // we are going to grow such regions by overlapping them with the void (if any)
    // TODO: detect and investigate whether there could be narrow regions without
    // any void neighbors
    {
        coord_t distance_between_surfaces = std::max(
            std::max(infill_flow.scaled_spacing(), solid_infill_flow.scaled_spacing()),
            top_solid_infill_flow.scaled_spacing());
        Polygons surfaces_polygons = to_polygons(surfaces);
        Polygons collapsed = diff(
            surfaces_polygons,
            offset2(surfaces_polygons, -distance_between_surfaces/2, +distance_between_surfaces/2),
            true);
        Polygons to_subtract;
        to_subtract.reserve(collapsed.size() + number_polygons(surfaces));
        for (Surfaces::const_iterator it_surface = surfaces.begin(); it_surface != surfaces.end(); ++ it_surface)
            if (it_surface->surface_type == stInternalVoid)
                polygons_append(to_subtract, *it_surface);
        polygons_append(to_subtract, collapsed);
        surfaces_append(
            surfaces,
            intersection_ex(
                offset(collapsed, distance_between_surfaces),
                to_subtract,
                true),
            stInternalSolid);
    }

    if (0) {
//        require "Slic3r/SVG.pm";
//        Slic3r::SVG::output("fill_" . $layerm->print_z . ".svg",
//            expolygons      => [ map $_->expolygon, grep !$_->is_solid, @surfaces ],
//            red_expolygons  => [ map $_->expolygon, grep  $_->is_solid, @surfaces ],
//        );
    }

    for (Surfaces::const_iterator surface_it = surfaces.begin(); surface_it != surfaces.end(); ++ surface_it) {
        const Surface &surface = *surface_it;
        if (surface.surface_type == stInternalVoid)
            continue;
        InfillPattern  fill_pattern = layerm.region()->config.fill_pattern.value;
        double         density      = fill_density;
        FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
            (surface.is_solid() ? frSolidInfill : frInfill);
        bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();

        if (surface.is_solid()) {
            density = 100;
            fill_pattern = (surface.is_external() && ! is_bridge) ?
                layerm.region()->config.external_fill_pattern.value :
                ipRectilinear;
        } else if (density <= 0)
            continue;

        // get filler object
        std::auto_ptr<Fill> f = std::auto_ptr<Fill>(Fill::new_from_type(fill_pattern));
        f->set_bounding_box(layerm.layer()->object()->bounding_box());

        // calculate the actual flow we'll be using for this infill
        coordf_t h = (surface.thickness == -1) ? layerm.layer()->height : surface.thickness;
        Flow flow = layerm.region()->flow(
            role,
            h,
            is_bridge || f->use_bridge_flow(),  // bridge flow?
            layerm.layer()->id() == 0,          // first layer?
            -1,                                 // auto width
            *layerm.layer()->object()
        );

        // calculate flow spacing for infill pattern generation
        bool using_internal_flow = false;
        if (! surface.is_solid() && ! is_bridge) {
            // it's internal infill, so we can calculate a generic flow spacing
            // for all layers, for avoiding the ugly effect of
            // misaligned infill on first layer because of different extrusion width and
            // layer height
            Flow internal_flow = layerm.region()->flow(
                frInfill,
                layerm.layer()->object()->config.layer_height.value,  // TODO: handle infill_every_layers?
                false,  // no bridge
                false,  // no first layer
                -1,     // auto width
                *layerm.layer()->object()
            );
            f->spacing = internal_flow.spacing();
            using_internal_flow = 1;
        } else {
            f->spacing = flow.spacing();
        }

        double link_max_length = 0.;
        if (! is_bridge) {
            link_max_length = layerm.region()->config.get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing());
//            printf("flow spacing: %f,  is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length);
        }

        f->layer_id = layerm.layer()->id();
        f->z = layerm.layer()->print_z;
        f->angle = Geometry::deg2rad(layerm.region()->config.fill_angle.value);
        // Maximum length of the perimeter segment linking two infill lines.
        f->link_max_length = scale_(link_max_length);
        // Used by the concentric infill pattern to clip the loops to create extrusion paths.
        f->loop_clipping = scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER;
//        f->layer_height = h;

        // apply half spacing using this flow's own spacing and generate infill
        FillParams params;
        params.density = 0.01 * density;
        params.dont_adjust = true;
        Polylines polylines = f->fill_surface(&surface, params);
        if (polylines.empty())
            continue;

        // calculate actual flow from spacing (which might have been adjusted by the infill
        // pattern generator)
        if (using_internal_flow) {
            // if we used the internal flow we're not doing a solid infill
            // so we can safely ignore the slight variation that might have
            // been applied to $f->flow_spacing
        } else {
            flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, h, is_bridge || f->use_bridge_flow());
        }

        // save into layer
        {
            ExtrusionRole role = is_bridge ? erBridgeInfill :
                (surface.is_solid() ? ((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) : erInternalInfill);
            ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
            out.entities.push_back(&collection);
            // Only concentric fills are not sorted.
            collection.no_sort = f->no_sort();
            for (Polylines::iterator it = polylines.begin(); it != polylines.end(); ++ it) {
                ExtrusionPath *path = new ExtrusionPath(role);
                collection.entities.push_back(path);
                path->polyline.points.swap(it->points);
                path->mm3_per_mm = flow.mm3_per_mm();
                path->width      = flow.width,
                path->height     = flow.height;
            }
        }
    }

    // add thin fill regions
    // thin_fills are of C++ Slic3r::ExtrusionEntityCollection, perl type Slic3r::ExtrusionPath::Collection
    // Unpacks the collection, creates multiple collections per path.
    // The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection.
    // Why the paths are unpacked?
    for (ExtrusionEntitiesPtr::iterator thin_fill = layerm.thin_fills.entities.begin(); thin_fill != layerm.thin_fills.entities.end(); ++ thin_fill) {
    #if 0
        out.entities.push_back((*thin_fill)->clone());
        assert(dynamic_cast<ExtrusionEntityCollection*>(out.entities.back()) != NULL);
    #else
        ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
        out.entities.push_back(&collection);
        collection.entities.push_back((*thin_fill)->clone());
    #endif
    }
}

} // namespace Slic3r
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdio.h>
#include <stdlib.h>

#include <cassert>

#include "ppapi/c/ppb_gamepad.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/size.h"
#include "ppapi/cpp/var.h"
#include "ppapi/utility/completion_callback_factory.h"

#ifdef WIN32
#undef min
#undef max

// Allow 'this' in initializer list
#pragma warning(disable : 4355)
#endif

class GamepadInstance : public pp::Instance {
 public:
  explicit GamepadInstance(PP_Instance instance);
  virtual ~GamepadInstance();

  // Update the graphics context to the new size, and regenerate |pixel_buffer_|
  // to fit the new size as well.
  virtual void DidChangeView(const pp::View& view);

  // Flushes its contents of |pixel_buffer_| to the 2D graphics context.
  void Paint();

  int width() const {
    return pixel_buffer_ ? pixel_buffer_->size().width() : 0;
  }
  int height() const {
    return pixel_buffer_ ? pixel_buffer_->size().height() : 0;
  }

  // Indicate whether a flush is pending.  This can only be called from the
  // main thread; it is not thread safe.
  bool flush_pending() const { return flush_pending_; }
  void set_flush_pending(bool flag) { flush_pending_ = flag; }

 private:
  // Create and initialize the 2D context used for drawing.
  void CreateContext(const pp::Size& size);
  // Destroy the 2D drawing context.
  void DestroyContext();
  // Push the pixels to the browser, then attempt to flush the 2D context.  If
  // there is a pending flush on the 2D context, then update the pixels only
  // and do not flush.
  void FlushPixelBuffer();

  void FlushCallback(int32_t result);

  bool IsContextValid() const { return graphics_2d_context_ != NULL; }

  pp::CompletionCallbackFactory<GamepadInstance> callback_factory_;
  pp::Graphics2D* graphics_2d_context_;
  pp::ImageData* pixel_buffer_;
  const PPB_Gamepad* gamepad_;
  bool flush_pending_;
};

GamepadInstance::GamepadInstance(PP_Instance instance)
    : pp::Instance(instance),
      callback_factory_(this),
      graphics_2d_context_(NULL),
      pixel_buffer_(NULL),
      flush_pending_(false) {
  pp::Module* module = pp::Module::Get();
  assert(module);
  gamepad_ = static_cast<const PPB_Gamepad*>(
      module->GetBrowserInterface(PPB_GAMEPAD_INTERFACE));
  assert(gamepad_);
}

GamepadInstance::~GamepadInstance() {
  DestroyContext();
  delete pixel_buffer_;
}

void GamepadInstance::DidChangeView(const pp::View& view) {
  pp::Rect position = view.GetRect();
  if (position.size().width() == width() &&
      position.size().height() == height())
    return;  // Size didn't change, no need to update anything.

  // Create a new device context with the new size.
  DestroyContext();
  CreateContext(position.size());
  // Delete the old pixel buffer and create a new one.
  delete pixel_buffer_;
  pixel_buffer_ = NULL;
  if (graphics_2d_context_ != NULL) {
    pixel_buffer_ = new pp::ImageData(this,
                                      PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                                      graphics_2d_context_->size(),
                                      false);
  }
  Paint();
}

void FillRect(pp::ImageData* image,
              int left,
              int top,
              int width,
              int height,
              uint32_t color) {
  for (int y = std::max(0, top);
       y < std::min(image->size().height() - 1, top + height);
       y++) {
    for (int x = std::max(0, left);
         x < std::min(image->size().width() - 1, left + width);
         x++)
      *image->GetAddr32(pp::Point(x, y)) = color;
  }
}

void GamepadInstance::Paint() {
  // Clear the background.
  FillRect(pixel_buffer_, 0, 0, width(), height(), 0xfff0f0f0);

  // Get current gamepad data.
  PP_GamepadsSampleData gamepad_data;
  gamepad_->Sample(pp_instance(), &gamepad_data);

  // Draw the current state for each connected gamepad.
  for (size_t p = 0; p < gamepad_data.length; ++p) {
    int width2 = width() / gamepad_data.length / 2;
    int height2 = height() / 2;
    int offset = width2 * 2 * p;
    PP_GamepadSampleData& pad = gamepad_data.items[p];

    if (!pad.connected)
      continue;

    // Draw axes.
    for (size_t i = 0; i < pad.axes_length; i += 2) {
      int x = static_cast<int>(pad.axes[i + 0] * width2 + width2) + offset;
      int y = static_cast<int>(pad.axes[i + 1] * height2 + height2);
      uint32_t box_bgra = 0x80000000;  // Alpha 50%.
      FillRect(pixel_buffer_, x - 3, y - 3, 7, 7, box_bgra);
    }

    // Draw buttons.
    for (size_t i = 0; i < pad.buttons_length; ++i) {
      float button_val = pad.buttons[i];
      uint32_t colour = static_cast<uint32_t>((button_val * 192) + 63) << 24;
      int x = i * 8 + 10 + offset;
      int y = 10;
      FillRect(pixel_buffer_, x - 3, y - 3, 7, 7, colour);
    }
  }

  // Output to the screen.
  FlushPixelBuffer();
}

void GamepadInstance::CreateContext(const pp::Size& size) {
  if (IsContextValid())
    return;
  graphics_2d_context_ = new pp::Graphics2D(this, size, false);
  if (!BindGraphics(*graphics_2d_context_)) {
    printf("Couldn't bind the device context\n");
  }
}

void GamepadInstance::DestroyContext() {
  if (!IsContextValid())
    return;
  delete graphics_2d_context_;
  graphics_2d_context_ = NULL;
}

void GamepadInstance::FlushPixelBuffer() {
  if (!IsContextValid())
    return;
  // Note that the pixel lock is held while the buffer is copied into the
  // device context and then flushed.
  graphics_2d_context_->PaintImageData(*pixel_buffer_, pp::Point());
  if (flush_pending())
    return;
  set_flush_pending(true);
  graphics_2d_context_->Flush(
      callback_factory_.NewCallback(&GamepadInstance::FlushCallback));
}

void GamepadInstance::FlushCallback(int32_t result) {
  set_flush_pending(false);
  Paint();
}

class GamepadModule : public pp::Module {
 public:
  GamepadModule() : pp::Module() {}
  virtual ~GamepadModule() {}

  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new GamepadInstance(instance);
  }
};

namespace pp {
Module* CreateModule() { return new GamepadModule(); }
}  // namespace pp
<commit_msg>[NaCl SDK] Fix gamepad example for msvc 2013<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdio.h>
#include <stdlib.h>

#include <algorithm>
#include <cassert>

#include "ppapi/c/ppb_gamepad.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/size.h"
#include "ppapi/cpp/var.h"
#include "ppapi/utility/completion_callback_factory.h"

#ifdef WIN32
#undef min
#undef max

// Allow 'this' in initializer list
#pragma warning(disable : 4355)
#endif

class GamepadInstance : public pp::Instance {
 public:
  explicit GamepadInstance(PP_Instance instance);
  virtual ~GamepadInstance();

  // Update the graphics context to the new size, and regenerate |pixel_buffer_|
  // to fit the new size as well.
  virtual void DidChangeView(const pp::View& view);

  // Flushes its contents of |pixel_buffer_| to the 2D graphics context.
  void Paint();

  int width() const {
    return pixel_buffer_ ? pixel_buffer_->size().width() : 0;
  }
  int height() const {
    return pixel_buffer_ ? pixel_buffer_->size().height() : 0;
  }

  // Indicate whether a flush is pending.  This can only be called from the
  // main thread; it is not thread safe.
  bool flush_pending() const { return flush_pending_; }
  void set_flush_pending(bool flag) { flush_pending_ = flag; }

 private:
  // Create and initialize the 2D context used for drawing.
  void CreateContext(const pp::Size& size);
  // Destroy the 2D drawing context.
  void DestroyContext();
  // Push the pixels to the browser, then attempt to flush the 2D context.  If
  // there is a pending flush on the 2D context, then update the pixels only
  // and do not flush.
  void FlushPixelBuffer();

  void FlushCallback(int32_t result);

  bool IsContextValid() const { return graphics_2d_context_ != NULL; }

  pp::CompletionCallbackFactory<GamepadInstance> callback_factory_;
  pp::Graphics2D* graphics_2d_context_;
  pp::ImageData* pixel_buffer_;
  const PPB_Gamepad* gamepad_;
  bool flush_pending_;
};

GamepadInstance::GamepadInstance(PP_Instance instance)
    : pp::Instance(instance),
      callback_factory_(this),
      graphics_2d_context_(NULL),
      pixel_buffer_(NULL),
      flush_pending_(false) {
  pp::Module* module = pp::Module::Get();
  assert(module);
  gamepad_ = static_cast<const PPB_Gamepad*>(
      module->GetBrowserInterface(PPB_GAMEPAD_INTERFACE));
  assert(gamepad_);
}

GamepadInstance::~GamepadInstance() {
  DestroyContext();
  delete pixel_buffer_;
}

void GamepadInstance::DidChangeView(const pp::View& view) {
  pp::Rect position = view.GetRect();
  if (position.size().width() == width() &&
      position.size().height() == height())
    return;  // Size didn't change, no need to update anything.

  // Create a new device context with the new size.
  DestroyContext();
  CreateContext(position.size());
  // Delete the old pixel buffer and create a new one.
  delete pixel_buffer_;
  pixel_buffer_ = NULL;
  if (graphics_2d_context_ != NULL) {
    pixel_buffer_ = new pp::ImageData(this,
                                      PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                                      graphics_2d_context_->size(),
                                      false);
  }
  Paint();
}

void FillRect(pp::ImageData* image,
              int left,
              int top,
              int width,
              int height,
              uint32_t color) {
  for (int y = std::max(0, top);
       y < std::min(image->size().height() - 1, top + height);
       y++) {
    for (int x = std::max(0, left);
         x < std::min(image->size().width() - 1, left + width);
         x++)
      *image->GetAddr32(pp::Point(x, y)) = color;
  }
}

void GamepadInstance::Paint() {
  // Clear the background.
  FillRect(pixel_buffer_, 0, 0, width(), height(), 0xfff0f0f0);

  // Get current gamepad data.
  PP_GamepadsSampleData gamepad_data;
  gamepad_->Sample(pp_instance(), &gamepad_data);

  // Draw the current state for each connected gamepad.
  for (size_t p = 0; p < gamepad_data.length; ++p) {
    int width2 = width() / gamepad_data.length / 2;
    int height2 = height() / 2;
    int offset = width2 * 2 * p;
    PP_GamepadSampleData& pad = gamepad_data.items[p];

    if (!pad.connected)
      continue;

    // Draw axes.
    for (size_t i = 0; i < pad.axes_length; i += 2) {
      int x = static_cast<int>(pad.axes[i + 0] * width2 + width2) + offset;
      int y = static_cast<int>(pad.axes[i + 1] * height2 + height2);
      uint32_t box_bgra = 0x80000000;  // Alpha 50%.
      FillRect(pixel_buffer_, x - 3, y - 3, 7, 7, box_bgra);
    }

    // Draw buttons.
    for (size_t i = 0; i < pad.buttons_length; ++i) {
      float button_val = pad.buttons[i];
      uint32_t colour = static_cast<uint32_t>((button_val * 192) + 63) << 24;
      int x = i * 8 + 10 + offset;
      int y = 10;
      FillRect(pixel_buffer_, x - 3, y - 3, 7, 7, colour);
    }
  }

  // Output to the screen.
  FlushPixelBuffer();
}

void GamepadInstance::CreateContext(const pp::Size& size) {
  if (IsContextValid())
    return;
  graphics_2d_context_ = new pp::Graphics2D(this, size, false);
  if (!BindGraphics(*graphics_2d_context_)) {
    printf("Couldn't bind the device context\n");
  }
}

void GamepadInstance::DestroyContext() {
  if (!IsContextValid())
    return;
  delete graphics_2d_context_;
  graphics_2d_context_ = NULL;
}

void GamepadInstance::FlushPixelBuffer() {
  if (!IsContextValid())
    return;
  // Note that the pixel lock is held while the buffer is copied into the
  // device context and then flushed.
  graphics_2d_context_->PaintImageData(*pixel_buffer_, pp::Point());
  if (flush_pending())
    return;
  set_flush_pending(true);
  graphics_2d_context_->Flush(
      callback_factory_.NewCallback(&GamepadInstance::FlushCallback));
}

void GamepadInstance::FlushCallback(int32_t result) {
  set_flush_pending(false);
  Paint();
}

class GamepadModule : public pp::Module {
 public:
  GamepadModule() : pp::Module() {}
  virtual ~GamepadModule() {}

  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new GamepadInstance(instance);
  }
};

namespace pp {
Module* CreateModule() { return new GamepadModule(); }
}  // namespace pp
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/focus/accelerator_handler.h"

#include <bitset>
#include <gtk/gtk.h>
#if defined(HAVE_XINPUT2)
#include <X11/extensions/XInput2.h>
#else
#include <X11/Xlib.h>
#endif

#include "views/accelerator.h"
#include "views/events/event.h"
#include "views/focus/focus_manager.h"
#include "views/touchui/touch_factory.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"

namespace views {

namespace {

RootView* FindRootViewForGdkWindow(GdkWindow* gdk_window) {
  gpointer data = NULL;
  gdk_window_get_user_data(gdk_window, &data);
  GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data);
  if (!gtk_widget || !GTK_IS_WIDGET(gtk_widget)) {
    DLOG(WARNING) << "no GtkWidget found for that GdkWindow";
    return NULL;
  }
  WidgetGtk* widget_gtk = WidgetGtk::GetViewForNative(gtk_widget);

  if (!widget_gtk) {
    DLOG(WARNING) << "no WidgetGtk found for that GtkWidget";
    return NULL;
  }
  return widget_gtk->GetRootView();
}

#if defined(HAVE_XINPUT2)
bool X2EventIsTouchEvent(XEvent* xev) {
  // TODO(sad): Determine if the captured event is a touch-event.
  XGenericEventCookie* cookie = &xev->xcookie;
  switch (cookie->evtype) {
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      // Is the event coming from a touch device?
      return TouchFactory::GetInstance()->IsTouchDevice(
          static_cast<XIDeviceEvent*>(cookie->data)->sourceid);
    }
    default:
      return false;
  }
}
#endif  // HAVE_XINPUT2

}  // namespace

#if defined(HAVE_XINPUT2)
bool DispatchX2Event(RootView* root, XEvent* xev) {
  XGenericEventCookie* cookie = &xev->xcookie;
  bool touch_event = false;

  if (X2EventIsTouchEvent(xev)) {
    // Hide the cursor when a touch event comes in.
    TouchFactory::GetInstance()->SetCursorVisible(false, false);
    touch_event = true;

    // Create a TouchEvent, and send it off to |root|. If the event
    // is processed by |root|, then return. Otherwise let it fall through so it
    // can be used (if desired) as a mouse event.
    TouchEvent touch(xev);
    if (root->OnTouchEvent(touch) != views::View::TOUCH_STATUS_UNKNOWN)
      return true;
  }

  switch (cookie->evtype) {
    case XI_KeyPress:
    case XI_KeyRelease: {
      // TODO(sad): We don't capture XInput2 events from keyboard yet.
      break;
    }
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      // Scrolling the wheel generates press/release events with button id's 4
      // and 5. In case of a wheelscroll, we do not want to show the cursor.
      XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(cookie->data);
      if (xievent->detail == 4 || xievent->detail == 5) {
        Event::FromNativeEvent2 from_native;
        return root->OnMouseWheel(MouseWheelEvent(xev, from_native));
      }

      MouseEvent mouseev(xev);
      if (!touch_event) {
        // Show the cursor, and decide whether or not the cursor should be
        // automatically hidden after a certain time of inactivity.
        int button_flags = mouseev.flags() & (ui::EF_RIGHT_BUTTON_DOWN |
            ui::EF_MIDDLE_BUTTON_DOWN | ui::EF_LEFT_BUTTON_DOWN);
        bool start_timer = false;

        switch (cookie->evtype) {
          case XI_ButtonPress:
            start_timer = false;
            break;
          case XI_ButtonRelease:
            // For a release, start the timer if this was only button pressed
            // that is being released.
            if (button_flags == ui::EF_RIGHT_BUTTON_DOWN ||
                button_flags == ui::EF_LEFT_BUTTON_DOWN ||
                button_flags == ui::EF_MIDDLE_BUTTON_DOWN)
              start_timer = true;
            break;
          case XI_Motion:
            start_timer = !button_flags;
            break;
        }
        TouchFactory::GetInstance()->SetCursorVisible(true, start_timer);
      }

      // Dispatch the event.
      switch (cookie->evtype) {
        case XI_ButtonPress:
          return root->OnMousePressed(mouseev);
        case XI_ButtonRelease:
          root->OnMouseReleased(mouseev, false);
          return true;
        case XI_Motion: {
          if (mouseev.type() == ui::ET_MOUSE_DRAGGED) {
            return root->OnMouseDragged(mouseev);
          } else {
            root->OnMouseMoved(mouseev);
            return true;
          }
        }
      }
    }
  }

  return false;
}

#endif  // HAVE_XINPUT2

bool DispatchXEvent(XEvent* xev) {
  GdkDisplay* gdisp = gdk_display_get_default();
  XID xwindow = xev->xany.window;

#if defined(HAVE_XINPUT2)
  if (xev->type == GenericEvent) {
    XGenericEventCookie* cookie = &xev->xcookie;
    XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data);
    xwindow = xiev->event;
  }
#endif

  GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow);

  if (RootView* root = FindRootViewForGdkWindow(gwind)) {
    switch (xev->type) {
      case KeyPress:
      case KeyRelease: {
        Event::FromNativeEvent2 from_native;
        KeyEvent keyev(xev, from_native);
        return root->ProcessKeyEvent(keyev);
      }

      case ButtonPress:
      case ButtonRelease: {
        if (xev->xbutton.button == 4 || xev->xbutton.button == 5) {
          // Scrolling the wheel triggers button press/release events.
          Event::FromNativeEvent2 from_native;
          return root->OnMouseWheel(MouseWheelEvent(xev, from_native));
        } else {
          MouseEvent mouseev(xev);
          if (xev->type == ButtonPress) {
            return root->OnMousePressed(mouseev);
          } else {
            root->OnMouseReleased(mouseev, false);
            return true;  // Assume the event has been processed to make sure we
                          // don't process it twice.
          }
        }
      }

      case MotionNotify: {
        MouseEvent mouseev(xev);
        if (mouseev.type() == ui::ET_MOUSE_DRAGGED) {
          return root->OnMouseDragged(mouseev);
        } else {
          root->OnMouseMoved(mouseev);
          return true;
        }
      }

#if defined(HAVE_XINPUT2)
      case GenericEvent: {
        return DispatchX2Event(root, xev);
      }
#endif
    }
  }

  return false;
}

#if defined(HAVE_XINPUT2)
void SetTouchDeviceList(std::vector<unsigned int>& devices) {
  TouchFactory::GetInstance()->SetTouchDeviceList(devices);
}
#endif

AcceleratorHandler::AcceleratorHandler() {}

bool AcceleratorHandler::Dispatch(GdkEvent* event) {
  gtk_main_do_event(event);
  return true;
}

base::MessagePumpGlibXDispatcher::DispatchStatus
    AcceleratorHandler::DispatchX(XEvent* xev) {
  return DispatchXEvent(xev) ?
      base::MessagePumpGlibXDispatcher::EVENT_PROCESSED :
      base::MessagePumpGlibXDispatcher::EVENT_IGNORED;
}

}  // namespace views
<commit_msg>touchui: Fix building on a buildbot.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/focus/accelerator_handler.h"

#include <bitset>
#include <gtk/gtk.h>
#if defined(HAVE_XINPUT2)
#include <X11/extensions/XInput2.h>
#else
#include <X11/Xlib.h>
#endif

#include "views/accelerator.h"
#include "views/events/event.h"
#include "views/focus/focus_manager.h"
#include "views/touchui/touch_factory.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_gtk.h"

namespace views {

namespace {

RootView* FindRootViewForGdkWindow(GdkWindow* gdk_window) {
  gpointer data = NULL;
  gdk_window_get_user_data(gdk_window, &data);
  GtkWidget* gtk_widget = reinterpret_cast<GtkWidget*>(data);
  if (!gtk_widget || !GTK_IS_WIDGET(gtk_widget)) {
    DLOG(WARNING) << "no GtkWidget found for that GdkWindow";
    return NULL;
  }
  WidgetGtk* widget_gtk = WidgetGtk::GetViewForNative(gtk_widget);

  if (!widget_gtk) {
    DLOG(WARNING) << "no WidgetGtk found for that GtkWidget";
    return NULL;
  }
  return widget_gtk->GetRootView();
}

#if defined(HAVE_XINPUT2)
bool X2EventIsTouchEvent(XEvent* xev) {
  // TODO(sad): Determine if the captured event is a touch-event.
  XGenericEventCookie* cookie = &xev->xcookie;
  switch (cookie->evtype) {
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      // Is the event coming from a touch device?
      return TouchFactory::GetInstance()->IsTouchDevice(
          static_cast<XIDeviceEvent*>(cookie->data)->sourceid);
    }
    default:
      return false;
  }
}
#endif  // HAVE_XINPUT2

}  // namespace

#if defined(HAVE_XINPUT2)
bool DispatchX2Event(RootView* root, XEvent* xev) {
  XGenericEventCookie* cookie = &xev->xcookie;
  bool touch_event = false;

  if (X2EventIsTouchEvent(xev)) {
    // Hide the cursor when a touch event comes in.
    TouchFactory::GetInstance()->SetCursorVisible(false, false);
    touch_event = true;

    // Create a TouchEvent, and send it off to |root|. If the event
    // is processed by |root|, then return. Otherwise let it fall through so it
    // can be used (if desired) as a mouse event.
    TouchEvent touch(xev);
    if (root->OnTouchEvent(touch) != views::View::TOUCH_STATUS_UNKNOWN)
      return true;
  }

  switch (cookie->evtype) {
    case XI_KeyPress:
    case XI_KeyRelease: {
      // TODO(sad): We don't capture XInput2 events from keyboard yet.
      break;
    }
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_Motion: {
      // Scrolling the wheel generates press/release events with button id's 4
      // and 5. In case of a wheelscroll, we do not want to show the cursor.
      XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(cookie->data);
      if (xievent->detail == 4 || xievent->detail == 5) {
        Event::FromNativeEvent2 from_native;
        MouseWheelEvent wheelev(xev, from_native);
        return root->OnMouseWheel(wheelev);
      }

      MouseEvent mouseev(xev);
      if (!touch_event) {
        // Show the cursor, and decide whether or not the cursor should be
        // automatically hidden after a certain time of inactivity.
        int button_flags = mouseev.flags() & (ui::EF_RIGHT_BUTTON_DOWN |
            ui::EF_MIDDLE_BUTTON_DOWN | ui::EF_LEFT_BUTTON_DOWN);
        bool start_timer = false;

        switch (cookie->evtype) {
          case XI_ButtonPress:
            start_timer = false;
            break;
          case XI_ButtonRelease:
            // For a release, start the timer if this was only button pressed
            // that is being released.
            if (button_flags == ui::EF_RIGHT_BUTTON_DOWN ||
                button_flags == ui::EF_LEFT_BUTTON_DOWN ||
                button_flags == ui::EF_MIDDLE_BUTTON_DOWN)
              start_timer = true;
            break;
          case XI_Motion:
            start_timer = !button_flags;
            break;
        }
        TouchFactory::GetInstance()->SetCursorVisible(true, start_timer);
      }

      // Dispatch the event.
      switch (cookie->evtype) {
        case XI_ButtonPress:
          return root->OnMousePressed(mouseev);
        case XI_ButtonRelease:
          root->OnMouseReleased(mouseev, false);
          return true;
        case XI_Motion: {
          if (mouseev.type() == ui::ET_MOUSE_DRAGGED) {
            return root->OnMouseDragged(mouseev);
          } else {
            root->OnMouseMoved(mouseev);
            return true;
          }
        }
      }
    }
  }

  return false;
}

#endif  // HAVE_XINPUT2

bool DispatchXEvent(XEvent* xev) {
  GdkDisplay* gdisp = gdk_display_get_default();
  XID xwindow = xev->xany.window;

#if defined(HAVE_XINPUT2)
  if (xev->type == GenericEvent) {
    XGenericEventCookie* cookie = &xev->xcookie;
    XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data);
    xwindow = xiev->event;
  }
#endif

  GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow);

  if (RootView* root = FindRootViewForGdkWindow(gwind)) {
    switch (xev->type) {
      case KeyPress:
      case KeyRelease: {
        Event::FromNativeEvent2 from_native;
        KeyEvent keyev(xev, from_native);
        return root->ProcessKeyEvent(keyev);
      }

      case ButtonPress:
      case ButtonRelease: {
        if (xev->xbutton.button == 4 || xev->xbutton.button == 5) {
          // Scrolling the wheel triggers button press/release events.
          Event::FromNativeEvent2 from_native;
          MouseWheelEvent wheelev(xev, from_native);
          return root->OnMouseWheel(wheelev);
        } else {
          MouseEvent mouseev(xev);
          if (xev->type == ButtonPress) {
            return root->OnMousePressed(mouseev);
          } else {
            root->OnMouseReleased(mouseev, false);
            return true;  // Assume the event has been processed to make sure we
                          // don't process it twice.
          }
        }
      }

      case MotionNotify: {
        MouseEvent mouseev(xev);
        if (mouseev.type() == ui::ET_MOUSE_DRAGGED) {
          return root->OnMouseDragged(mouseev);
        } else {
          root->OnMouseMoved(mouseev);
          return true;
        }
      }

#if defined(HAVE_XINPUT2)
      case GenericEvent: {
        return DispatchX2Event(root, xev);
      }
#endif
    }
  }

  return false;
}

#if defined(HAVE_XINPUT2)
void SetTouchDeviceList(std::vector<unsigned int>& devices) {
  TouchFactory::GetInstance()->SetTouchDeviceList(devices);
}
#endif

AcceleratorHandler::AcceleratorHandler() {}

bool AcceleratorHandler::Dispatch(GdkEvent* event) {
  gtk_main_do_event(event);
  return true;
}

base::MessagePumpGlibXDispatcher::DispatchStatus
    AcceleratorHandler::DispatchX(XEvent* xev) {
  return DispatchXEvent(xev) ?
      base::MessagePumpGlibXDispatcher::EVENT_PROCESSED :
      base::MessagePumpGlibXDispatcher::EVENT_IGNORED;
}

}  // namespace views
<|endoftext|>