<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id: quadtree.hh 17 2005-03-08 23:58:43Z pavlenko $

#ifndef QUADTREE_HPP
#define QUADTREE_HPP
// stl
#include <cstring>
#include <vector>
#include <fstream>
#include <iostream>
// mapnik
#include <mapnik/box2d.hpp>

using mapnik::box2d;
using mapnik::coord2d;

template <typename T>
struct quadtree_node
{
    box2d<double> ext_;
    std::vector<T> data_;
    quadtree_node<T>* children_[4];
    quadtree_node(const box2d<double>& ext)
        : ext_(ext),data_()
    {
        memset(children_,0,sizeof(quadtree_node<T>*)*4);
    }

    ~quadtree_node()
    {
        for (int i=0;i<4;++i)
        {
            if (children_[i])
            {
                delete children_[i],children_[i]=0;
            }
        }
    }

    int num_subnodes() const
    {
        int count=0;
        for (int i=0;i<4;++i)
        {
            if (children_[i])
            {
                ++count;
            }
        }
        return count;
    }
};

template <typename T>
class quadtree
{
private:
    quadtree_node<T>* root_;
    const int maxdepth_;
    const double ratio_;
public:
    quadtree(const box2d<double>& extent,int maxdepth,double ratio)
        : root_(new quadtree_node<T>(extent)),
          maxdepth_(maxdepth),
          ratio_(ratio) {}

    ~quadtree()
    {
        if (root_) delete root_;
    }

    void insert(const T& data,const box2d<double>& item_ext)
    {
        insert(data,item_ext,root_,maxdepth_);
    }

    int count() const
    {
        return count_nodes(root_);
    }

    int count_items() const
    {
        int count=0;
        count_items(root_,count);
        return count;
    }

    void print() const
    {
        print(root_);
    }

    void trim()
    {
        trim_tree(root_);
    }

    void write(std::ostream& out)
    {
        char header[16];
        memset(header,0,16);
        header[0]='m';
        header[1]='a';
        header[2]='p';
        header[3]='n';
        header[4]='i';
        header[5]='k';
        out.write(header,16);
        write_node(out,root_);
    }

private:

    void trim_tree(quadtree_node<T>*&  node)
    {
        if (node)
        {
            for (int i=0;i<4;++i)
            {
                trim_tree(node->children_[i]);
            }

            if (node->num_subnodes()==1 && node->data_.size()==0)
            {
                for (int i=0;i<4;++i)
                {
                    if (node->children_[i])
                    {
                        node=node->children_[i];
                        break;
                    }
                }
            }
        }
    }

    int count_nodes(const quadtree_node<T>*  node) const
    {
        if (!node)
        {
            return 0;
        }
        else
        {
            int count = 1;
            for (int i=0;i<4;++i)
            {
                count += count_nodes(node->children_[i]);
            }
            return count;
        }
    }

    void count_items(const quadtree_node<T>* node,int& count) const
    {
        if (node)
        {
            count += node->data_.size();
            for (int i=0;i<4;++i)
            {
                count_items(node->children_[i],count);
            }
        }
    }

    int subnode_offset(const quadtree_node<T>* node) const
    {
        int offset=0;
        for (int i=0;i<4;i++)
        {
            if (node->children_[i])
            {
                offset +=sizeof(box2d<double>)+(node->children_[i]->data_.size()*sizeof(T))+3*sizeof(int);
                offset +=subnode_offset(node->children_[i]);
            }
        }
        return offset;
    }

    void write_node(std::ostream& out,const quadtree_node<T>* node) const
    {
        if (node)
        {
            int offset=subnode_offset(node);
            int shape_count=node->data_.size();
            int recsize=sizeof(box2d<double>) + 3 * sizeof(int) + shape_count * sizeof(T);
            char* node_record=new char[recsize];
            memset(node_record,0,recsize);
            memcpy(node_record,&offset,4);
            memcpy(node_record+4,&node->ext_,sizeof(box2d<double>));
            memcpy(node_record+36,&shape_count,4);
            for (int i=0;i<shape_count;++i)
            {
                memcpy(node_record + 40 + i * sizeof(T),&(node->data_[i]),sizeof(T));
            }
            int num_subnodes=0;
            for (int i=0;i<4;++i)
            {
                if (node->children_[i])
                {
                    ++num_subnodes;
                }
            }
            memcpy(node_record + 40 + shape_count * sizeof(T),&num_subnodes,4);
            out.write(node_record,recsize);
            delete [] node_record;

            for (int i=0;i<4;++i)
            {
                write_node(out,node->children_[i]);
            }
        }
    }

    void print(const quadtree_node<T>* node,int level=0) const
    {
        if (node)
        {
            typename std::vector<T>::const_iterator itr=node->data_.begin();
            std::string pad;
            for (int i=0;i<level;++i)
            {
                pad+=" ";
            }
            std::clog<<pad<<"node "<<node<<" extent:"<<node->ext_<<std::endl;
            std::clog<<pad;
            while(itr!=node->data_.end())
            {
                std::clog<<*itr<<" ";
                ++itr;
            }
            std::clog<<std::endl;
            for (int i=0;i<4;++i)
            {
                print(node->children_[i],level+4);
            }
        }
    }

    void insert(const T& data,const box2d<double>& item_ext,quadtree_node<T>*  node,int maxdepth)
    {
        if (node && node->ext_.contains(item_ext))
        {
            coord2d c=node->ext_.center();

            double width=node->ext_.width();
            double height=node->ext_.height();

            double lox=node->ext_.minx();
            double loy=node->ext_.miny();
            double hix=node->ext_.maxx();
            double hiy=node->ext_.maxy();

            box2d<double> ext[4];
            ext[0]=box2d<double>(lox,loy,lox + width * ratio_,loy + height * ratio_);
            ext[1]=box2d<double>(hix - width * ratio_,loy,hix,loy + height * ratio_);
            ext[2]=box2d<double>(lox,hiy - height*ratio_,lox + width * ratio_,hiy);
            ext[3]=box2d<double>(hix - width * ratio_,hiy - height*ratio_,hix,hiy);

            if (maxdepth > 1)
            {
                for (int i=0;i<4;++i)
                {
                    if (ext[i].contains(item_ext))
                    {
                        if (!node->children_[i])
                        {
                            node->children_[i]=new quadtree_node<T>(ext[i]);
                        }
                        insert(data,item_ext,node->children_[i],maxdepth-1);
                        return;
                    }
                }
            }
            node->data_.push_back(data);
        }
    }
};
#endif //QUADTREE_HPP
<commit_msg>quadtree: remove unused variable<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id: quadtree.hh 17 2005-03-08 23:58:43Z pavlenko $

#ifndef QUADTREE_HPP
#define QUADTREE_HPP
// stl
#include <cstring>
#include <vector>
#include <fstream>
#include <iostream>
// mapnik
#include <mapnik/box2d.hpp>

using mapnik::box2d;
using mapnik::coord2d;

template <typename T>
struct quadtree_node
{
    box2d<double> ext_;
    std::vector<T> data_;
    quadtree_node<T>* children_[4];
    quadtree_node(const box2d<double>& ext)
        : ext_(ext),data_()
    {
        memset(children_,0,sizeof(quadtree_node<T>*)*4);
    }

    ~quadtree_node()
    {
        for (int i=0;i<4;++i)
        {
            if (children_[i])
            {
                delete children_[i],children_[i]=0;
            }
        }
    }

    int num_subnodes() const
    {
        int count=0;
        for (int i=0;i<4;++i)
        {
            if (children_[i])
            {
                ++count;
            }
        }
        return count;
    }
};

template <typename T>
class quadtree
{
private:
    quadtree_node<T>* root_;
    const int maxdepth_;
    const double ratio_;
public:
    quadtree(const box2d<double>& extent,int maxdepth,double ratio)
        : root_(new quadtree_node<T>(extent)),
          maxdepth_(maxdepth),
          ratio_(ratio) {}

    ~quadtree()
    {
        if (root_) delete root_;
    }

    void insert(const T& data,const box2d<double>& item_ext)
    {
        insert(data,item_ext,root_,maxdepth_);
    }

    int count() const
    {
        return count_nodes(root_);
    }

    int count_items() const
    {
        int count=0;
        count_items(root_,count);
        return count;
    }

    void print() const
    {
        print(root_);
    }

    void trim()
    {
        trim_tree(root_);
    }

    void write(std::ostream& out)
    {
        char header[16];
        memset(header,0,16);
        header[0]='m';
        header[1]='a';
        header[2]='p';
        header[3]='n';
        header[4]='i';
        header[5]='k';
        out.write(header,16);
        write_node(out,root_);
    }

private:

    void trim_tree(quadtree_node<T>*&  node)
    {
        if (node)
        {
            for (int i=0;i<4;++i)
            {
                trim_tree(node->children_[i]);
            }

            if (node->num_subnodes()==1 && node->data_.size()==0)
            {
                for (int i=0;i<4;++i)
                {
                    if (node->children_[i])
                    {
                        node=node->children_[i];
                        break;
                    }
                }
            }
        }
    }

    int count_nodes(const quadtree_node<T>*  node) const
    {
        if (!node)
        {
            return 0;
        }
        else
        {
            int count = 1;
            for (int i=0;i<4;++i)
            {
                count += count_nodes(node->children_[i]);
            }
            return count;
        }
    }

    void count_items(const quadtree_node<T>* node,int& count) const
    {
        if (node)
        {
            count += node->data_.size();
            for (int i=0;i<4;++i)
            {
                count_items(node->children_[i],count);
            }
        }
    }

    int subnode_offset(const quadtree_node<T>* node) const
    {
        int offset=0;
        for (int i=0;i<4;i++)
        {
            if (node->children_[i])
            {
                offset +=sizeof(box2d<double>)+(node->children_[i]->data_.size()*sizeof(T))+3*sizeof(int);
                offset +=subnode_offset(node->children_[i]);
            }
        }
        return offset;
    }

    void write_node(std::ostream& out,const quadtree_node<T>* node) const
    {
        if (node)
        {
            int offset=subnode_offset(node);
            int shape_count=node->data_.size();
            int recsize=sizeof(box2d<double>) + 3 * sizeof(int) + shape_count * sizeof(T);
            char* node_record=new char[recsize];
            memset(node_record,0,recsize);
            memcpy(node_record,&offset,4);
            memcpy(node_record+4,&node->ext_,sizeof(box2d<double>));
            memcpy(node_record+36,&shape_count,4);
            for (int i=0;i<shape_count;++i)
            {
                memcpy(node_record + 40 + i * sizeof(T),&(node->data_[i]),sizeof(T));
            }
            int num_subnodes=0;
            for (int i=0;i<4;++i)
            {
                if (node->children_[i])
                {
                    ++num_subnodes;
                }
            }
            memcpy(node_record + 40 + shape_count * sizeof(T),&num_subnodes,4);
            out.write(node_record,recsize);
            delete [] node_record;

            for (int i=0;i<4;++i)
            {
                write_node(out,node->children_[i]);
            }
        }
    }

    void print(const quadtree_node<T>* node,int level=0) const
    {
        if (node)
        {
            typename std::vector<T>::const_iterator itr=node->data_.begin();
            std::string pad;
            for (int i=0;i<level;++i)
            {
                pad+=" ";
            }
            std::clog<<pad<<"node "<<node<<" extent:"<<node->ext_<<std::endl;
            std::clog<<pad;
            while(itr!=node->data_.end())
            {
                std::clog<<*itr<<" ";
                ++itr;
            }
            std::clog<<std::endl;
            for (int i=0;i<4;++i)
            {
                print(node->children_[i],level+4);
            }
        }
    }

    void insert(const T& data,const box2d<double>& item_ext,quadtree_node<T>*  node,int maxdepth)
    {
        if (node && node->ext_.contains(item_ext))
        {
            double width=node->ext_.width();
            double height=node->ext_.height();

            double lox=node->ext_.minx();
            double loy=node->ext_.miny();
            double hix=node->ext_.maxx();
            double hiy=node->ext_.maxy();

            box2d<double> ext[4];
            ext[0]=box2d<double>(lox,loy,lox + width * ratio_,loy + height * ratio_);
            ext[1]=box2d<double>(hix - width * ratio_,loy,hix,loy + height * ratio_);
            ext[2]=box2d<double>(lox,hiy - height*ratio_,lox + width * ratio_,hiy);
            ext[3]=box2d<double>(hix - width * ratio_,hiy - height*ratio_,hix,hiy);

            if (maxdepth > 1)
            {
                for (int i=0;i<4;++i)
                {
                    if (ext[i].contains(item_ext))
                    {
                        if (!node->children_[i])
                        {
                            node->children_[i]=new quadtree_node<T>(ext[i]);
                        }
                        insert(data,item_ext,node->children_[i],maxdepth-1);
                        return;
                    }
                }
            }
            node->data_.push_back(data);
        }
    }
};
#endif //QUADTREE_HPP
<|endoftext|>


<commit_before>#include "otc/write_dot.h"
#include <algorithm>
#include "otc/embedded_tree.h"
#include "otc/embedding.h"
#include "otc/tree.h"
#include "otc/tree_data.h"
#include "otc/tree_iter.h"
#include "otc/tree_operations.h"

namespace otc {

typedef std::pair<const NodeWithSplits *, std::string> ToDotKey;
typedef std::map<ToDotKey, std::vector<std::string>> NodeToDotNames;
void writeNodeDOT(std::ostream & out,
                           const NodeWithSplits * nd,
                           NodeToDotNames & nd2name,
                           std::set<std::string> & names,
                           const std::string &style,
                           bool forceMRCANaming,
                           const std::string & prefix,
                           bool writeLabel,
                           bool pt);

void writeDOTEdge(std::ostream & out,
                  const ToDotKey anc,
                  const ToDotKey des,
                  NodeToDotNames & nd2name,
                  const std::string &style,
                  bool toMidEdge);

void writeDOTCrossEdge(std::ostream & out,
                  const ToDotKey anc,
                  const ToDotKey des,
                  NodeToDotNames & nd2name,
                  const std::string &style);

void writePathPairingToDOT(std::ostream & out,
                           const PathPairingWithSplits & pp,
                           NodeToDotNames & nd2name,
                           std::set<std::string> & names,
                           std::set<const PathPairingWithSplits *> & pathSet,
                           const char * color,
                           const char * prefix) ;

void writeDOTEmbeddingForNode(std::ostream & out,
                              const NodeEmbeddingWithSplits & thr,
                              NodeToDotNames & nd2name,
                              std::set<std::string> & names,
                              std::set<const PathPairingWithSplits *> & pathSet,
                              const char * color,
                              const char * prefix,
                              std::size_t treeIndex
                              );
// IMPL

constexpr const char * COLORS [] = {"crimson",
                                    "blue",
                                    "springgreen",
                                    "magenta",
                                    "darkorange",
                                    "lightblue",
                                    "goldenrod",
                                    "brown",
                                    "gray"};
constexpr unsigned LAST_COLOR_IND = 8;

typedef std::pair<const NodeWithSplits *, std::string> ToDotKey;
typedef std::map<ToDotKey, std::vector<std::string>> NodeToDotNames;

void writeNodeDOT(std::ostream & out,
                           const NodeWithSplits * nd,
                           NodeToDotNames & nd2name,
                           std::set<std::string> & names,
                           const std::string &style,
                           bool forceMRCANaming,
                           const std::string & prefix,
                           bool writeLabel,
                           bool pt) {
    const ToDotKey k{nd, prefix};
    std::string name;
    std::string unadorned;
    if (pt) {
        name = nd2name.at(k)[0];
        unadorned = name;
    } else {
        if (contains(nd2name, k)) {
            return;
        }
        if (nd->isTip() && !prefix.empty()) {
            return;
        } else {
            name.append(std::string(prefix));
            unadorned = forceMRCANaming ? getMRCADesignator(*nd) :  getDesignator(*nd);
            name.append(unadorned);
            nd2name[k].push_back(name);
        }
    }
    out << "  \"" << name << "\"[";
    if (pt) {
        out << "shape=point label=\"\" ";
    } else {
        if (writeLabel || nd->isTip()) {
            out << "label=\"" << unadorned << "\" ";
        } else {
            out << "label=\"\" ";
        }
    }
    if (!style.empty()) {
        out << style;
    }
    out << "];\n";
    names.insert(name);
}

void writeDOTEdge(std::ostream & out,
                  const ToDotKey anc,
                  const ToDotKey des,
                  NodeToDotNames & nd2name,
                  const std::string &style,
                  bool /*toMidEdge*/) {
    out << "    \"" << nd2name[anc][0] << "\" -> \"" << nd2name[des][0] << '\"';
    if (!style.empty()) {
        out << "[" << style <<']';
    }
    out << ";\n";
}

void writeDOTCrossEdge(std::ostream & out,
                  const ToDotKey anc,
                  const ToDotKey des,
                  NodeToDotNames & nd2name,
                  const std::string &style) {
    out << "    \"" << nd2name[anc][0] << "\" -> \"" << nd2name[des][0] << '\"';
    if (!style.empty()) {
        out << "[arrowhead=none " << style <<']';
    }
    out << ";\n";
}

void writePathPairingToDOT(std::ostream & out,
                           const PathPairingWithSplits & pp,
                           NodeToDotNames & nd2name,
                           std::set<std::string> & names,
                           std::set<const PathPairingWithSplits *> & pathSet,
                           const char * color,
                           const char * prefix) {
    if (contains(pathSet, &pp)) {
        return;
    }
    pathSet.insert(&pp);
    std::string style = "fontcolor=\"";
    style.append(color);
    style.append("\" style=\"dashed\" color=\"");
    style.append(color);
    style.append("\"");

    const auto * pn = pp.phyloParent;
    const auto * pd = pp.phyloChild;
    writeNodeDOT(out, pn, nd2name, names, style, true, prefix, false, false);
    writeNodeDOT(out, pd, nd2name, names, style, false, prefix, false, false);
    ToDotKey pk{pd, "_path"};
    nd2name[pk].push_back("_" + std::to_string((long)(&pp)));
    writeNodeDOT(out, pd, nd2name, names, style, false, "_path", false, true);
    writeDOTEdge(out, ToDotKey{pn, prefix}, pk, nd2name, style, true);
    const auto * sn = pp.scaffoldAnc;
    const auto * sd = pp.scaffoldDes;
    if (pd->isTip()) {
        writeDOTEdge(out, pk, ToDotKey{sd, ""}, nd2name, style, false);
    } else {
        writeDOTEdge(out, pk, ToDotKey{pd, prefix}, nd2name, style, false);
    }
    ToDotKey sk{sd, "_path"};
    nd2name[sk].push_back("_" + std::to_string((long)(&pp)));
    writeNodeDOT(out, sn, nd2name, names, style, true, prefix, false, false);
    writeNodeDOT(out, sd, nd2name, names, style, false, prefix, false, false);
    writeNodeDOT(out, sd, nd2name, names, style, false, "_path", false, true);
    writeDOTEdge(out, ToDotKey{sn, ""}, sk, nd2name, style, true);
    writeDOTEdge(out, sk, ToDotKey{sd, ""}, nd2name, style, false);
    style.append(" style=\"dotted\"");
    writeDOTCrossEdge(out, pk, sk, nd2name, style);
}

void writeDOTEmbeddingForNode(std::ostream & out,
                              const NodeEmbeddingWithSplits & thr,
                              NodeToDotNames & nd2name,
                              std::set<std::string> & names,
                              std::set<const PathPairingWithSplits *> & pathSet,
                              const char * color,
                              const char * prefix,
                              std::size_t treeIndex
                              ) {
    const auto eait = thr.edgeBelowEmbeddings.find(treeIndex);
    if (eait != thr.edgeBelowEmbeddings.end()) {
        for (const auto & pp : eait->second) {
            writePathPairingToDOT(out, *pp, nd2name, names, pathSet, color, prefix);
        }
    }
    const auto lait = thr.loopEmbeddings.find(treeIndex);
    if (lait != thr.loopEmbeddings.end()) {
        for (const auto & pp : lait->second) {
            writePathPairingToDOT(out, *pp, nd2name, names, pathSet, color, prefix);
        }
    }
}

void writeDOTForEmbedding(std::ostream & out,
                     const NodeWithSplits * nd,
                     const std::vector<TreeMappedWithSplits *> & tv,
                     const std::map<const NodeWithSplits *, NodeEmbeddingWithSplits> & eForNd,
                     bool entireSubtree) {
    NodeToDotNames nd2name;
    std::set<std::string> names;
    out << "digraph G{\n";
    for (auto n : iter_pre_n_const(nd)) {
        writeNodeDOT(out, n, nd2name, names, "", false, "", true, false);
    }
    for (auto n : iter_pre_n_const(nd)) {
        auto p = n->getParent();
        if (p == nullptr) {
            continue;
        }
        ToDotKey nk{n, ""};
        ToDotKey pk{p, ""};
        out << "    " << nd2name[pk][0] << " -> " << nd2name[nk][0] << ";\n";
    }
    std::set<const PathPairingWithSplits *> pathSet;
    const auto nt = tv.size();
    for (auto n : iter_pre_n_const(nd)) {
        const NodeEmbeddingWithSplits & thr = eForNd.at(n);
        for (auto i = 0U; i < nt; ++i) {
            const std::string tP = std::string("t") + std::to_string(i);
            auto colorIndex = std::min(LAST_COLOR_IND, i);
            const char * color = COLORS[colorIndex];
            writeDOTEmbeddingForNode(out, thr, nd2name, names, pathSet, color, tP.c_str(), i);
        }
        if (!entireSubtree) {
            break;
        }
    }
    out << "}\n";
}

} // namespace otc

<commit_msg>cleanup<commit_after>#include "otc/write_dot.h"
#include <algorithm>
#include "otc/embedded_tree.h"
#include "otc/embedding.h"
#include "otc/tree.h"
#include "otc/tree_data.h"
#include "otc/tree_iter.h"
#include "otc/tree_operations.h"

namespace otc {
typedef std::pair<const NodeWithSplits *, std::string> ToDotKey;
typedef std::pair<std::string, std::string> NamePair; // nodeName and nodeLabel
typedef std::map<ToDotKey, NamePair> NodeToDotNames;

void writeNodeDOT(std::ostream & out,
                           const NodeWithSplits * nd,
                           NodeToDotNames & nd2name,
                           const std::string &style,
                           bool forceMRCANaming,
                           const std::string & prefix,
                           bool writeLabel,
                           bool pt);
void writeDOTEdge(std::ostream & out,
                  const ToDotKey anc,
                  const ToDotKey des,
                  NodeToDotNames & nd2name,
                  const std::string &style,
                  bool toMidEdge);
void writeDOTCrossEdge(std::ostream & out,
                  const ToDotKey anc,
                  const ToDotKey des,
                  NodeToDotNames & nd2name,
                  const std::string &style);
void writePathPairingToDOT(std::ostream & out,
                           const PathPairingWithSplits & pp,
                           NodeToDotNames & nd2name,
                           std::set<const PathPairingWithSplits *> & pathSet,
                           const char * color,
                           const char * prefix) ;
void writeDOTEmbeddingForNode(std::ostream & out,
                              const NodeEmbeddingWithSplits & thr,
                              NodeToDotNames & nd2name,
                              std::set<const PathPairingWithSplits *> & pathSet,
                              const char * color,
                              const char * prefix,
                              std::size_t treeIndex
                              );
// IMPL
constexpr const char * COLORS [] = {"crimson",
                                    "blue",
                                    "springgreen",
                                    "magenta",
                                    "darkorange",
                                    "lightblue",
                                    "goldenrod",
                                    "brown",
                                    "gray"};
constexpr unsigned LAST_COLOR_IND = 8;

void writeNodeDOT(std::ostream & out,
                           const NodeWithSplits * nd,
                           NodeToDotNames & nd2name,
                           const std::string &style,
                           bool forceMRCANaming,
                           const std::string & prefix,
                           bool writeLabel,
                           bool pt) {
    const ToDotKey k{nd, prefix};
    if (!pt) {
        if (contains(nd2name, k)) {
            return;
        }
        if (nd->isTip() && !prefix.empty()) {
            return;
        }
        std::string name{prefix};
        const std::string unadorned = forceMRCANaming ? getMRCADesignator(*nd) :  getDesignator(*nd);
        name.append(unadorned);
        nd2name.emplace(k, NamePair{name, unadorned});
    }
    const NamePair & np = nd2name.at(k);
    out << "  \"" << np.first << "\"[";
    if (pt) {
        out << "shape=point ";
    }
    if ((!pt) && (writeLabel || nd->isTip())) {
        out << "label=\"" << np.second << "\" ";
    } else {
        out << "label=\"\" ";
    }
    if (!style.empty()) {
        out << style;
    }
    out << "];\n";
}

void writeDOTEdge(std::ostream & out,
                  const ToDotKey anc,
                  const ToDotKey des,
                  NodeToDotNames & nd2name,
                  const std::string &style,
                  bool /*toMidEdge*/) {
    out << "    \"" << nd2name.at(anc).first << "\" -> \"" << nd2name.at(des).first << '\"';
    if (!style.empty()) {
        out << "[" << style <<']';
    }
    out << ";\n";
}

void writeDOTCrossEdge(std::ostream & out,
                  const ToDotKey anc,
                  const ToDotKey des,
                  NodeToDotNames & nd2name,
                  const std::string &style) {
    std::string s = "arrowhead=none ";
    s += style;
    writeDOTEdge(out, anc, des, nd2name, s, true);
}

void writeOneSideOfPathPairingToDOT(std::ostream & out,
                                     const NodeWithSplits * pn,
                                     const NodeWithSplits * pd,
                                     const NodeWithSplits * sd,
                                     const ToDotKey & midPointKey,
                                     const NamePair & namePair,
                                     NodeToDotNames & nd2name,
                                     const std::string & style,
                                     const char * prefix);

void writeOneSideOfPathPairingToDOT(std::ostream & out,
                           const NodeWithSplits * pn,
                           const NodeWithSplits * pd,
                           const NodeWithSplits * sd,
                           const ToDotKey & midPointKey,
                           const NamePair & namePair,
                           NodeToDotNames & nd2name,
                           const std::string & style,
                           const char * prefix) {
    writeNodeDOT(out, pn, nd2name, style, true, prefix, false, false);
    writeNodeDOT(out, pd, nd2name, style, false, prefix, false, false);
    nd2name[midPointKey] = namePair;
    writeNodeDOT(out, pd, nd2name, style, false, "_path", false, true);
    writeDOTEdge(out, ToDotKey{pn, prefix}, midPointKey, nd2name, style, true);
    if (pd->isTip() && sd != pd) {
        writeDOTEdge(out, midPointKey, ToDotKey{sd, ""}, nd2name, style, false);
    } else {
        writeDOTEdge(out, midPointKey, ToDotKey{pd, prefix}, nd2name, style, false);
    }

}

void writePathPairingToDOT(std::ostream & out,
                           const PathPairingWithSplits & pp,
                           NodeToDotNames & nd2name,
                           std::set<const PathPairingWithSplits *> & pathSet,
                           const char * color,
                           const char * prefix) {
    if (contains(pathSet, &pp)) {
        return;
    }
    const std::string emptyStr;
    pathSet.insert(&pp);
    std::string style = "fontcolor=\"";
    style.append(color);
    style.append("\" style=\"dashed\" color=\"");
    style.append(color);
    style.append("\"");
    // The midpoint nodes are unlabeled dots with IDs that are _addr or __addr
    const std::string pname ="_" + std::to_string((long)(&pp));
    const std::string sname ="__" + std::to_string((long)(&pp));
    const NamePair pv{pname, emptyStr};
    const NamePair sv{pname, emptyStr};
    const auto * pn = pp.phyloParent;
    const auto * pd = pp.phyloChild;
    const auto * sd = pp.scaffoldDes;
    const ToDotKey pk{pd, "_phpath"};
    writeOneSideOfPathPairingToDOT(out, pn, pd, sd, pk, pv, nd2name, color, prefix);
    const auto * sn = pp.scaffoldAnc;
    const ToDotKey sk{sd, "_scpath"};
    writeOneSideOfPathPairingToDOT(out, sn, sd, sd, sk, sv, nd2name, color, prefix);
    style.append(" style=\"dotted\"");
    writeDOTCrossEdge(out, pk, sk, nd2name, style);
}

void writeDOTEmbeddingForNode(std::ostream & out,
                              const NodeEmbeddingWithSplits & thr,
                              NodeToDotNames & nd2name,
                              std::set<const PathPairingWithSplits *> & pathSet,
                              const char * color,
                              const char * prefix,
                              std::size_t treeIndex
                              ) {
    const auto eait = thr.edgeBelowEmbeddings.find(treeIndex);
    if (eait != thr.edgeBelowEmbeddings.end()) {
        for (const auto & pp : eait->second) {
            writePathPairingToDOT(out, *pp, nd2name, pathSet, color, prefix);
        }
    }
    const auto lait = thr.loopEmbeddings.find(treeIndex);
    if (lait != thr.loopEmbeddings.end()) {
        for (const auto & pp : lait->second) {
            writePathPairingToDOT(out, *pp, nd2name, pathSet, color, prefix);
        }
    }
}

void writeDOTForEmbedding(std::ostream & out,
                     const NodeWithSplits * nd,
                     const std::vector<TreeMappedWithSplits *> & tv,
                     const std::map<const NodeWithSplits *, NodeEmbeddingWithSplits> & eForNd,
                     bool entireSubtree) {
    NodeToDotNames nd2name;
    std::string emptyStr;
    out << "digraph G{\n";
    for (auto n : iter_pre_n_const(nd)) {
        writeNodeDOT(out, n, nd2name, "", false, "", true, false);
    }
    for (auto n : iter_pre_n_const(nd)) {
        auto p = n->getParent();
        if (p == nullptr) {
            continue;
        }
        const ToDotKey nk{n, ""};
        const ToDotKey pk{p, ""};
        writeDOTEdge(out, pk, nk, nd2name, emptyStr, false);
    }
    std::set<const PathPairingWithSplits *> pathSet;
    const auto nt = tv.size();
    for (auto n : iter_pre_n_const(nd)) {
        const NodeEmbeddingWithSplits & thr = eForNd.at(n);
        for (auto i = 0U; i < nt; ++i) {
            const std::string tP = std::string("t") + std::to_string(i);
            auto colorIndex = std::min(LAST_COLOR_IND, i);
            const char * color = COLORS[colorIndex];
            writeDOTEmbeddingForNode(out, thr, nd2name, pathSet, color, tP.c_str(), i);
        }
        if (!entireSubtree) {
            break;
        }
    }
    out << "}\n";
}

} // namespace otc

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: salogl.cxx,v $
 *
 *  $Revision: 1.17 $
 *
 *  last change: $Author: hr $ $Date: 2006-08-11 17:51:50 $
 *
 *  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 <salunx.h>

#ifndef _SV_SALDATA_HXX
#include <saldata.hxx>
#endif

#ifndef _SV_SALDISP_HXX
#include <saldisp.hxx>
#endif

#ifndef _SV_SALOGL_H
#include <salogl.h>
#endif

#ifndef _SV_SALGDI_H
#include <salgdi.h>
#endif

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

using namespace rtl;

// ------------
// - Lib-Name -
// ------------

#ifdef MACOSX
#define OGL_LIBNAME "libGL.dylib"
#else
#define OGL_LIBNAME "libGL.so.1"
#endif

// ----------
// - Macros -
// ----------

// -----------------
// - Statics init. -
// -----------------

// Members
GLXContext      X11SalOpenGL::maGLXContext = 0;
Display*        X11SalOpenGL::mpDisplay    = 0;
XVisualInfo*    X11SalOpenGL::mpVisualInfo = 0;
BOOL            X11SalOpenGL::mbHaveGLVisual = FALSE;

oslModule      X11SalOpenGL::mpGLLib    = 0;
#ifdef SOLARIS
oslModule      aMotifLib;
#endif

ULONG       X11SalOpenGL::mnOGLState = OGL_STATE_UNLOADED;

GLXContext (*X11SalOpenGL::pCreateContext)( Display *, XVisualInfo *, GLXContext, Bool ) = 0;
void       (*X11SalOpenGL::pDestroyContext)( Display *, GLXContext ) = 0;
GLXContext (*X11SalOpenGL::pGetCurrentContext)( ) = 0;
Bool       (*X11SalOpenGL::pMakeCurrent)( Display *, GLXDrawable, GLXContext ) = 0;
void        (*X11SalOpenGL::pSwapBuffers)( Display*, GLXDrawable ) = 0;
int         (*X11SalOpenGL::pGetConfig)( Display*, XVisualInfo*, int, int* ) = 0;
void       (*X11SalOpenGL::pFlush)() = 0;

// -------------
// - X11SalOpenGL -
// -------------

X11SalOpenGL::X11SalOpenGL( SalGraphics* pSGraphics )
{
    X11SalGraphics* pGraphics = static_cast<X11SalGraphics*>(pSGraphics);
    mpDisplay    = pGraphics->GetXDisplay();
    mpVisualInfo = pGraphics->GetDisplay()->GetVisual();
    maDrawable   = pGraphics->GetDrawable();
}

// ------------------------------------------------------------------------

X11SalOpenGL::~X11SalOpenGL()
{
}

// ------------------------------------------------------------------------

bool X11SalOpenGL::IsValid()
{
    if( OGL_STATE_UNLOADED == mnOGLState )
    {
        BOOL bHasGLX = FALSE;
        char **ppExtensions;
        int nExtensions;

        if( *DisplayString( mpDisplay ) == ':'                          ||
            ! strncmp( DisplayString( mpDisplay ), "localhost:", 10 )
            )
        {
            // GLX only on local displays due to strange problems
            // with remote GLX
            ppExtensions = XListExtensions( mpDisplay, &nExtensions );
            for( int i=0; i < nExtensions; i++ )
            {
                if( ! strncmp( "GLX", ppExtensions[ i ], 3 ) )
                {
                    bHasGLX = TRUE;
                    break;
                }
            }
            XFreeExtensionList( ppExtensions );
#if OSL_DEBUG_LEVEL > 1
            if( ! bHasGLX )
                fprintf( stderr, "XServer does not support GLX extension\n" );
#endif
            if( bHasGLX )
            {
                /*
                 *  #82406# the XFree4.0 GLX module does not seem
                 *  to work that great, at least not the one that comes
                 *  with the default installation and Matrox cards.
                 *  Since these are common we disable usage of
                 *  OpenGL per default.
                 */
                static const char* pOverrideGLX = getenv( "SAL_ENABLE_GLX_XFREE4" );
                if( ! strncmp( ServerVendor( mpDisplay ), "The XFree86 Project, Inc", 24 ) &&
                    VendorRelease( mpDisplay ) >= 4000 &&
                    ! pOverrideGLX
                    )
                {
#if OSL_DEBUG_LEVEL > 1
                    fprintf( stderr, "disabling GLX usage on XFree >= 4.0\n" );
#endif
                    bHasGLX = FALSE;
                }
            }
        }
        if( bHasGLX && mpVisualInfo->c_class == TrueColor && ImplInit() )
        {
            int nDoubleBuffer = 0;
            int nHaveGL = 0;
            pGetConfig( mpDisplay, mpVisualInfo,
                        GLX_USE_GL, &nHaveGL );
            pGetConfig( mpDisplay, mpVisualInfo,
                        GLX_DOUBLEBUFFER, &nDoubleBuffer );
            if( nHaveGL && ! nDoubleBuffer )
            {
                SalDisplay* pSalDisplay = GetX11SalData()->GetDisplay();
                BOOL bPreviousState =
                    pSalDisplay->GetXLib()->GetIgnoreXErrors();
                pSalDisplay->GetXLib()->SetIgnoreXErrors( TRUE );
                mbHaveGLVisual = TRUE;

                maGLXContext = pCreateContext( mpDisplay, mpVisualInfo, 0, True );
                if( pSalDisplay->GetXLib()->WasXError() )
                    mbHaveGLVisual = FALSE;
                else
                    pMakeCurrent( mpDisplay, maDrawable, maGLXContext );
                if( pSalDisplay->GetXLib()->WasXError() )
                    mbHaveGLVisual = FALSE;
                pSalDisplay->GetXLib()->SetIgnoreXErrors( bPreviousState );

                if( mbHaveGLVisual )
                    mnOGLState = OGL_STATE_VALID;
                else
                    maGLXContext = None;
            }
        }
        if( mnOGLState != OGL_STATE_VALID )
            mnOGLState = OGL_STATE_INVALID;
#if OSL_DEBUG_LEVEL > 1
        if( mnOGLState == OGL_STATE_VALID )
            fprintf( stderr, "Using GLX on visual id %x.\n", mpVisualInfo->visualid );
        else
            fprintf( stderr, "Not using GLX.\n" );
#endif
    }

    return mnOGLState == OGL_STATE_VALID ? TRUE : FALSE;
}

void X11SalOpenGL::Release()
{
    if( maGLXContext && pDestroyContext )
        pDestroyContext( mpDisplay, maGLXContext );
}

// ------------------------------------------------------------------------

void X11SalOpenGL::ReleaseLib()
{
    if( mpGLLib )
    {
        osl_unloadModule( mpGLLib );
        #ifdef SOLARIS
        if( aMotifLib )
            osl_unloadModule( aMotifLib );
        #endif

        mpGLLib             = 0;
        pCreateContext      = 0;
        pDestroyContext     = 0;
        pGetCurrentContext  = 0;
        pMakeCurrent        = 0;
        pSwapBuffers        = 0;
        pGetConfig          = 0;

        mnOGLState          = OGL_STATE_UNLOADED;
    }
}

// ------------------------------------------------------------------------

oglFunction X11SalOpenGL::GetOGLFnc( const char *pFncName )
{
    return resolveSymbol( pFncName );
}

// ------------------------------------------------------------------------

void X11SalOpenGL::OGLEntry( SalGraphics* pGraphics )
{
    GLXDrawable aDrawable = static_cast<X11SalGraphics*>(pGraphics)->GetDrawable();
    if( aDrawable != maDrawable )
    {
        maDrawable = aDrawable;
        pMakeCurrent( mpDisplay, maDrawable, maGLXContext );
    }
}

// ------------------------------------------------------------------------

void X11SalOpenGL::OGLExit( SalGraphics* )
{
}

// ------------------------------------------------------------------------

oglFunction X11SalOpenGL::resolveSymbol( const char* pSymbol )
{
    oglFunction pSym = NULL;
    if( mpGLLib )
    {
        OUString aSym = OUString::createFromAscii( pSymbol );
        pSym = osl_getFunctionSymbol( mpGLLib, aSym.pData );
    }
    return pSym;
}

BOOL X11SalOpenGL::ImplInit()
{
    if( ! mpGLLib )
    {
        ByteString sNoGL( getenv( "SAL_NOOPENGL" ) );
        if( sNoGL.ToLowerAscii() == "true"  )
            return FALSE;

        sal_Int32 nRtldMode = SAL_LOADMODULE_NOW;
        #ifdef SOLARIS
        /* #i36866# an obscure interaction with jvm can let java crash
        *  if we do not use SAL_LOADMODULE_GLOBAL here
        */
        nRtldMode |= SAL_LOADMODULE_GLOBAL;

        /* #i36899# and we need Xm, too, else jvm will not work properly.
        */
        OUString aMotifName( RTL_CONSTASCII_USTRINGPARAM( "libXm.so" ) );
        aMotifLib = osl_loadModule( aMotifName.pData, nRtldMode );
        #endif
        OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( OGL_LIBNAME ) );
        mpGLLib = osl_loadModule( aLibName.pData, nRtldMode );
    }
    if( ! mpGLLib )
    {
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, OGL_LIBNAME "could not be opened\n" );
#endif
        return FALSE;
    }

    // Internal use
    pCreateContext     = (GLXContext(*)(Display*,XVisualInfo*,GLXContext,Bool ))
        resolveSymbol( "glXCreateContext" );
    pDestroyContext    = (void(*)(Display*,GLXContext))
        resolveSymbol( "glXDestroyContext" );
    pGetCurrentContext = (GLXContext(*)())
        resolveSymbol( "glXGetCurrentContext" );
    pMakeCurrent       = (Bool(*)(Display*,GLXDrawable,GLXContext))
        resolveSymbol( "glXMakeCurrent" );
    pSwapBuffers=(void(*)(Display*, GLXDrawable))
        resolveSymbol( "glXSwapBuffers" );
    pGetConfig = (int(*)(Display*, XVisualInfo*, int, int* ))
        resolveSymbol( "glXGetConfig" );
    pFlush = (void(*)())
        resolveSymbol( "glFlush" );

    BOOL bRet = pCreateContext && pDestroyContext && pGetCurrentContext && pMakeCurrent && pSwapBuffers && pGetConfig ? TRUE : FALSE;

#if OSL_DEBUG_LEVEL > 1
    if( ! bRet )
        fprintf( stderr, "could not find all needed symbols in " OGL_LIBNAME "\n" );
#endif

    return bRet;
}

void X11SalOpenGL::StartScene( SalGraphics* )
{
    // flush pending operations which otherwise might be drawn
    // at the wrong time
    XSync( mpDisplay, False );
}

void X11SalOpenGL::StopScene()
{
    if( maDrawable )
    {
        pSwapBuffers( mpDisplay, maDrawable );
        pFlush();
    }
}

void X11SalOpenGL::MakeVisualWeights( Display* pDisplay,
                                   XVisualInfo* pInfos,
                                   int *pWeights,
                                   int nVisuals )
{
    BOOL bHasGLX = FALSE;
    char **ppExtensions;
    int nExtensions,i ;

    // GLX only on local displays due to strange problems
    // with remote GLX
    if( ! ( *DisplayString( pDisplay ) == ':'                           ||
            !strncmp( DisplayString( pDisplay ), "localhost:", 10 )
            ) )
        return;

    ppExtensions = XListExtensions( pDisplay, &nExtensions );
    for( i=0; i < nExtensions; i++ )
    {
        if( ! strncmp( "GLX", ppExtensions[ i ], 3 ) )
        {
            bHasGLX = TRUE;
            break;
        }
    }
    XFreeExtensionList( ppExtensions );
    if( ! bHasGLX )
        return;

    if( ! ImplInit() )
        return;

    for( i = 0; i < nVisuals; i++ )
    {
        int nDoubleBuffer = 0;
        int nHaveGL = 0;
        // a weight lesser than zero indicates an invalid visual (wrong screen)
        if( pInfos[i].c_class == TrueColor && pInfos[i].depth > 14 && pWeights[i] >= 0)
        {
            pGetConfig( pDisplay, &pInfos[ i ], GLX_USE_GL, &nHaveGL );
            pGetConfig( pDisplay, &pInfos[ i ], GLX_DOUBLEBUFFER, &nDoubleBuffer );
            if( nHaveGL && ! nDoubleBuffer )
            {
                mbHaveGLVisual = TRUE;
                pWeights[ i ] += 65536;
            }
        }
    }
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.17.4); FILE MERGED 2006/09/01 17:58:09 kaib 1.17.4.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: salogl.cxx,v $
 *
 *  $Revision: 1.18 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 12:39: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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"

#include <salunx.h>

#ifndef _SV_SALDATA_HXX
#include <saldata.hxx>
#endif

#ifndef _SV_SALDISP_HXX
#include <saldisp.hxx>
#endif

#ifndef _SV_SALOGL_H
#include <salogl.h>
#endif

#ifndef _SV_SALGDI_H
#include <salgdi.h>
#endif

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

using namespace rtl;

// ------------
// - Lib-Name -
// ------------

#ifdef MACOSX
#define OGL_LIBNAME "libGL.dylib"
#else
#define OGL_LIBNAME "libGL.so.1"
#endif

// ----------
// - Macros -
// ----------

// -----------------
// - Statics init. -
// -----------------

// Members
GLXContext      X11SalOpenGL::maGLXContext = 0;
Display*        X11SalOpenGL::mpDisplay    = 0;
XVisualInfo*    X11SalOpenGL::mpVisualInfo = 0;
BOOL            X11SalOpenGL::mbHaveGLVisual = FALSE;

oslModule      X11SalOpenGL::mpGLLib    = 0;
#ifdef SOLARIS
oslModule      aMotifLib;
#endif

ULONG       X11SalOpenGL::mnOGLState = OGL_STATE_UNLOADED;

GLXContext (*X11SalOpenGL::pCreateContext)( Display *, XVisualInfo *, GLXContext, Bool ) = 0;
void       (*X11SalOpenGL::pDestroyContext)( Display *, GLXContext ) = 0;
GLXContext (*X11SalOpenGL::pGetCurrentContext)( ) = 0;
Bool       (*X11SalOpenGL::pMakeCurrent)( Display *, GLXDrawable, GLXContext ) = 0;
void        (*X11SalOpenGL::pSwapBuffers)( Display*, GLXDrawable ) = 0;
int         (*X11SalOpenGL::pGetConfig)( Display*, XVisualInfo*, int, int* ) = 0;
void       (*X11SalOpenGL::pFlush)() = 0;

// -------------
// - X11SalOpenGL -
// -------------

X11SalOpenGL::X11SalOpenGL( SalGraphics* pSGraphics )
{
    X11SalGraphics* pGraphics = static_cast<X11SalGraphics*>(pSGraphics);
    mpDisplay    = pGraphics->GetXDisplay();
    mpVisualInfo = pGraphics->GetDisplay()->GetVisual();
    maDrawable   = pGraphics->GetDrawable();
}

// ------------------------------------------------------------------------

X11SalOpenGL::~X11SalOpenGL()
{
}

// ------------------------------------------------------------------------

bool X11SalOpenGL::IsValid()
{
    if( OGL_STATE_UNLOADED == mnOGLState )
    {
        BOOL bHasGLX = FALSE;
        char **ppExtensions;
        int nExtensions;

        if( *DisplayString( mpDisplay ) == ':'                          ||
            ! strncmp( DisplayString( mpDisplay ), "localhost:", 10 )
            )
        {
            // GLX only on local displays due to strange problems
            // with remote GLX
            ppExtensions = XListExtensions( mpDisplay, &nExtensions );
            for( int i=0; i < nExtensions; i++ )
            {
                if( ! strncmp( "GLX", ppExtensions[ i ], 3 ) )
                {
                    bHasGLX = TRUE;
                    break;
                }
            }
            XFreeExtensionList( ppExtensions );
#if OSL_DEBUG_LEVEL > 1
            if( ! bHasGLX )
                fprintf( stderr, "XServer does not support GLX extension\n" );
#endif
            if( bHasGLX )
            {
                /*
                 *  #82406# the XFree4.0 GLX module does not seem
                 *  to work that great, at least not the one that comes
                 *  with the default installation and Matrox cards.
                 *  Since these are common we disable usage of
                 *  OpenGL per default.
                 */
                static const char* pOverrideGLX = getenv( "SAL_ENABLE_GLX_XFREE4" );
                if( ! strncmp( ServerVendor( mpDisplay ), "The XFree86 Project, Inc", 24 ) &&
                    VendorRelease( mpDisplay ) >= 4000 &&
                    ! pOverrideGLX
                    )
                {
#if OSL_DEBUG_LEVEL > 1
                    fprintf( stderr, "disabling GLX usage on XFree >= 4.0\n" );
#endif
                    bHasGLX = FALSE;
                }
            }
        }
        if( bHasGLX && mpVisualInfo->c_class == TrueColor && ImplInit() )
        {
            int nDoubleBuffer = 0;
            int nHaveGL = 0;
            pGetConfig( mpDisplay, mpVisualInfo,
                        GLX_USE_GL, &nHaveGL );
            pGetConfig( mpDisplay, mpVisualInfo,
                        GLX_DOUBLEBUFFER, &nDoubleBuffer );
            if( nHaveGL && ! nDoubleBuffer )
            {
                SalDisplay* pSalDisplay = GetX11SalData()->GetDisplay();
                BOOL bPreviousState =
                    pSalDisplay->GetXLib()->GetIgnoreXErrors();
                pSalDisplay->GetXLib()->SetIgnoreXErrors( TRUE );
                mbHaveGLVisual = TRUE;

                maGLXContext = pCreateContext( mpDisplay, mpVisualInfo, 0, True );
                if( pSalDisplay->GetXLib()->WasXError() )
                    mbHaveGLVisual = FALSE;
                else
                    pMakeCurrent( mpDisplay, maDrawable, maGLXContext );
                if( pSalDisplay->GetXLib()->WasXError() )
                    mbHaveGLVisual = FALSE;
                pSalDisplay->GetXLib()->SetIgnoreXErrors( bPreviousState );

                if( mbHaveGLVisual )
                    mnOGLState = OGL_STATE_VALID;
                else
                    maGLXContext = None;
            }
        }
        if( mnOGLState != OGL_STATE_VALID )
            mnOGLState = OGL_STATE_INVALID;
#if OSL_DEBUG_LEVEL > 1
        if( mnOGLState == OGL_STATE_VALID )
            fprintf( stderr, "Using GLX on visual id %x.\n", mpVisualInfo->visualid );
        else
            fprintf( stderr, "Not using GLX.\n" );
#endif
    }

    return mnOGLState == OGL_STATE_VALID ? TRUE : FALSE;
}

void X11SalOpenGL::Release()
{
    if( maGLXContext && pDestroyContext )
        pDestroyContext( mpDisplay, maGLXContext );
}

// ------------------------------------------------------------------------

void X11SalOpenGL::ReleaseLib()
{
    if( mpGLLib )
    {
        osl_unloadModule( mpGLLib );
        #ifdef SOLARIS
        if( aMotifLib )
            osl_unloadModule( aMotifLib );
        #endif

        mpGLLib             = 0;
        pCreateContext      = 0;
        pDestroyContext     = 0;
        pGetCurrentContext  = 0;
        pMakeCurrent        = 0;
        pSwapBuffers        = 0;
        pGetConfig          = 0;

        mnOGLState          = OGL_STATE_UNLOADED;
    }
}

// ------------------------------------------------------------------------

oglFunction X11SalOpenGL::GetOGLFnc( const char *pFncName )
{
    return resolveSymbol( pFncName );
}

// ------------------------------------------------------------------------

void X11SalOpenGL::OGLEntry( SalGraphics* pGraphics )
{
    GLXDrawable aDrawable = static_cast<X11SalGraphics*>(pGraphics)->GetDrawable();
    if( aDrawable != maDrawable )
    {
        maDrawable = aDrawable;
        pMakeCurrent( mpDisplay, maDrawable, maGLXContext );
    }
}

// ------------------------------------------------------------------------

void X11SalOpenGL::OGLExit( SalGraphics* )
{
}

// ------------------------------------------------------------------------

oglFunction X11SalOpenGL::resolveSymbol( const char* pSymbol )
{
    oglFunction pSym = NULL;
    if( mpGLLib )
    {
        OUString aSym = OUString::createFromAscii( pSymbol );
        pSym = osl_getFunctionSymbol( mpGLLib, aSym.pData );
    }
    return pSym;
}

BOOL X11SalOpenGL::ImplInit()
{
    if( ! mpGLLib )
    {
        ByteString sNoGL( getenv( "SAL_NOOPENGL" ) );
        if( sNoGL.ToLowerAscii() == "true"  )
            return FALSE;

        sal_Int32 nRtldMode = SAL_LOADMODULE_NOW;
        #ifdef SOLARIS
        /* #i36866# an obscure interaction with jvm can let java crash
        *  if we do not use SAL_LOADMODULE_GLOBAL here
        */
        nRtldMode |= SAL_LOADMODULE_GLOBAL;

        /* #i36899# and we need Xm, too, else jvm will not work properly.
        */
        OUString aMotifName( RTL_CONSTASCII_USTRINGPARAM( "libXm.so" ) );
        aMotifLib = osl_loadModule( aMotifName.pData, nRtldMode );
        #endif
        OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( OGL_LIBNAME ) );
        mpGLLib = osl_loadModule( aLibName.pData, nRtldMode );
    }
    if( ! mpGLLib )
    {
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, OGL_LIBNAME "could not be opened\n" );
#endif
        return FALSE;
    }

    // Internal use
    pCreateContext     = (GLXContext(*)(Display*,XVisualInfo*,GLXContext,Bool ))
        resolveSymbol( "glXCreateContext" );
    pDestroyContext    = (void(*)(Display*,GLXContext))
        resolveSymbol( "glXDestroyContext" );
    pGetCurrentContext = (GLXContext(*)())
        resolveSymbol( "glXGetCurrentContext" );
    pMakeCurrent       = (Bool(*)(Display*,GLXDrawable,GLXContext))
        resolveSymbol( "glXMakeCurrent" );
    pSwapBuffers=(void(*)(Display*, GLXDrawable))
        resolveSymbol( "glXSwapBuffers" );
    pGetConfig = (int(*)(Display*, XVisualInfo*, int, int* ))
        resolveSymbol( "glXGetConfig" );
    pFlush = (void(*)())
        resolveSymbol( "glFlush" );

    BOOL bRet = pCreateContext && pDestroyContext && pGetCurrentContext && pMakeCurrent && pSwapBuffers && pGetConfig ? TRUE : FALSE;

#if OSL_DEBUG_LEVEL > 1
    if( ! bRet )
        fprintf( stderr, "could not find all needed symbols in " OGL_LIBNAME "\n" );
#endif

    return bRet;
}

void X11SalOpenGL::StartScene( SalGraphics* )
{
    // flush pending operations which otherwise might be drawn
    // at the wrong time
    XSync( mpDisplay, False );
}

void X11SalOpenGL::StopScene()
{
    if( maDrawable )
    {
        pSwapBuffers( mpDisplay, maDrawable );
        pFlush();
    }
}

void X11SalOpenGL::MakeVisualWeights( Display* pDisplay,
                                   XVisualInfo* pInfos,
                                   int *pWeights,
                                   int nVisuals )
{
    BOOL bHasGLX = FALSE;
    char **ppExtensions;
    int nExtensions,i ;

    // GLX only on local displays due to strange problems
    // with remote GLX
    if( ! ( *DisplayString( pDisplay ) == ':'                           ||
            !strncmp( DisplayString( pDisplay ), "localhost:", 10 )
            ) )
        return;

    ppExtensions = XListExtensions( pDisplay, &nExtensions );
    for( i=0; i < nExtensions; i++ )
    {
        if( ! strncmp( "GLX", ppExtensions[ i ], 3 ) )
        {
            bHasGLX = TRUE;
            break;
        }
    }
    XFreeExtensionList( ppExtensions );
    if( ! bHasGLX )
        return;

    if( ! ImplInit() )
        return;

    for( i = 0; i < nVisuals; i++ )
    {
        int nDoubleBuffer = 0;
        int nHaveGL = 0;
        // a weight lesser than zero indicates an invalid visual (wrong screen)
        if( pInfos[i].c_class == TrueColor && pInfos[i].depth > 14 && pWeights[i] >= 0)
        {
            pGetConfig( pDisplay, &pInfos[ i ], GLX_USE_GL, &nHaveGL );
            pGetConfig( pDisplay, &pInfos[ i ], GLX_DOUBLEBUFFER, &nDoubleBuffer );
            if( nHaveGL && ! nDoubleBuffer )
            {
                mbHaveGLVisual = TRUE;
                pWeights[ i ] += 65536;
            }
        }
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: salogl.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 13:08:05 $
 *
 *  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 <salunx.h>

#ifndef _SV_SALDATA_HXX
#include <saldata.hxx>
#endif

#ifndef _SV_SALDISP_HXX
#include <saldisp.hxx>
#endif

#ifndef _SV_SALOGL_H
#include <salogl.h>
#endif

#ifndef _SV_SALGDI_H
#include <salgdi.h>
#endif

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

using namespace rtl;

// ------------
// - Lib-Name -
// ------------

#ifdef MACOSX
#define OGL_LIBNAME "libGL.dylib"
#else
#define OGL_LIBNAME "libGL.so.1"
#endif

// ----------
// - Macros -
// ----------

// -----------------
// - Statics init. -
// -----------------

// Members
GLXContext      X11SalOpenGL::maGLXContext = 0;
Display*        X11SalOpenGL::mpDisplay    = 0;
XVisualInfo*    X11SalOpenGL::mpVisualInfo = 0;
BOOL            X11SalOpenGL::mbHaveGLVisual = FALSE;

oslModule      X11SalOpenGL::mpGLLib    = 0;
#ifdef SOLARIS
oslModule      aMotifLib;
#endif

ULONG       X11SalOpenGL::mnOGLState = OGL_STATE_UNLOADED;

GLXContext (*X11SalOpenGL::pCreateContext)( Display *, XVisualInfo *, GLXContext, Bool ) = 0;
void       (*X11SalOpenGL::pDestroyContext)( Display *, GLXContext ) = 0;
GLXContext (*X11SalOpenGL::pGetCurrentContext)( ) = 0;
Bool       (*X11SalOpenGL::pMakeCurrent)( Display *, GLXDrawable, GLXContext ) = 0;
void        (*X11SalOpenGL::pSwapBuffers)( Display*, GLXDrawable ) = 0;
int         (*X11SalOpenGL::pGetConfig)( Display*, XVisualInfo*, int, int* ) = 0;
void       (*X11SalOpenGL::pFlush)() = 0;

// -------------
// - X11SalOpenGL -
// -------------

X11SalOpenGL::X11SalOpenGL( SalGraphics* pSGraphics )
{
    X11SalGraphics* pGraphics = static_cast<X11SalGraphics*>(pSGraphics);
    mpDisplay    = pGraphics->GetXDisplay();
    mpVisualInfo = pGraphics->GetDisplay()->GetVisual();
    maDrawable   = pGraphics->GetDrawable();
}

// ------------------------------------------------------------------------

X11SalOpenGL::~X11SalOpenGL()
{
}

// ------------------------------------------------------------------------

bool X11SalOpenGL::IsValid()
{
    if( OGL_STATE_UNLOADED == mnOGLState )
    {
        BOOL bHasGLX = FALSE;
        char **ppExtensions;
        int nExtensions;

        if( *DisplayString( mpDisplay ) == ':'                          ||
            ! strncmp( DisplayString( mpDisplay ), "localhost:", 10 )
            )
        {
            // GLX only on local displays due to strange problems
            // with remote GLX
            ppExtensions = XListExtensions( mpDisplay, &nExtensions );
            for( int i=0; i < nExtensions; i++ )
            {
                if( ! strncmp( "GLX", ppExtensions[ i ], 3 ) )
                {
                    bHasGLX = TRUE;
                    break;
                }
            }
            XFreeExtensionList( ppExtensions );
#if OSL_DEBUG_LEVEL > 1
            if( ! bHasGLX )
                fprintf( stderr, "XServer does not support GLX extension\n" );
#endif
            if( bHasGLX )
            {
                /*
                 *  #82406# the XFree4.0 GLX module does not seem
                 *  to work that great, at least not the one that comes
                 *  with the default installation and Matrox cards.
                 *  Since these are common we disable usage of
                 *  OpenGL per default.
                 */
                static const char* pOverrideGLX = getenv( "SAL_ENABLE_GLX_XFREE4" );
                if( ! strncmp( ServerVendor( mpDisplay ), "The XFree86 Project, Inc", 24 ) &&
                    VendorRelease( mpDisplay ) >= 4000 &&
                    ! pOverrideGLX
                    )
                {
#if OSL_DEBUG_LEVEL > 1
                    fprintf( stderr, "disabling GLX usage on XFree >= 4.0\n" );
#endif
                    bHasGLX = FALSE;
                }
            }
        }
        if( bHasGLX && mpVisualInfo->c_class == TrueColor && ImplInit() )
        {
            int nDoubleBuffer = 0;
            int nHaveGL = 0;
            pGetConfig( mpDisplay, mpVisualInfo,
                        GLX_USE_GL, &nHaveGL );
            pGetConfig( mpDisplay, mpVisualInfo,
                        GLX_DOUBLEBUFFER, &nDoubleBuffer );
            if( nHaveGL && ! nDoubleBuffer )
            {
                SalDisplay* pSalDisplay = GetSalData()->GetDisplay();
                BOOL bPreviousState =
                    pSalDisplay->GetXLib()->GetIgnoreXErrors();
                pSalDisplay->GetXLib()->SetIgnoreXErrors( TRUE );
                mbHaveGLVisual = TRUE;

                maGLXContext = pCreateContext( mpDisplay, mpVisualInfo, 0, True );
                if( pSalDisplay->GetXLib()->WasXError() )
                    mbHaveGLVisual = FALSE;
                else
                    pMakeCurrent( mpDisplay, maDrawable, maGLXContext );
                if( pSalDisplay->GetXLib()->WasXError() )
                    mbHaveGLVisual = FALSE;
                pSalDisplay->GetXLib()->SetIgnoreXErrors( bPreviousState );

                if( mbHaveGLVisual )
                    mnOGLState = OGL_STATE_VALID;
                else
                    maGLXContext = None;
            }
        }
        if( mnOGLState != OGL_STATE_VALID )
            mnOGLState = OGL_STATE_INVALID;
#if OSL_DEBUG_LEVEL > 1
        if( mnOGLState == OGL_STATE_VALID )
            fprintf( stderr, "Using GLX on visual id %x.\n", mpVisualInfo->visualid );
        else
            fprintf( stderr, "Not using GLX.\n" );
#endif
    }

    return mnOGLState == OGL_STATE_VALID ? TRUE : FALSE;
}

void X11SalOpenGL::Release()
{
    if( maGLXContext && pDestroyContext )
        pDestroyContext( mpDisplay, maGLXContext );
}

// ------------------------------------------------------------------------

void X11SalOpenGL::ReleaseLib()
{
    if( mpGLLib )
    {
        osl_unloadModule( mpGLLib );
        #ifdef SOLARIS
        if( aMotifLib )
            osl_unloadModule( aMotifLib );
        #endif

        mpGLLib             = 0;
        pCreateContext      = 0;
        pDestroyContext     = 0;
        pGetCurrentContext  = 0;
        pMakeCurrent        = 0;
        pSwapBuffers        = 0;
        pGetConfig          = 0;

        mnOGLState          = OGL_STATE_UNLOADED;
    }
}

// ------------------------------------------------------------------------

void* X11SalOpenGL::GetOGLFnc( const char *pFncName )
{
    return resolveSymbol( pFncName );
}

// ------------------------------------------------------------------------

void X11SalOpenGL::OGLEntry( SalGraphics* pGraphics )
{
    GLXDrawable aDrawable = static_cast<X11SalGraphics*>(pGraphics)->GetDrawable();
    if( aDrawable != maDrawable )
    {
        maDrawable = aDrawable;
        pMakeCurrent( mpDisplay, maDrawable, maGLXContext );
    }
}

// ------------------------------------------------------------------------

void X11SalOpenGL::OGLExit( SalGraphics* pGraphics )
{
}

// ------------------------------------------------------------------------

void* X11SalOpenGL::resolveSymbol( const char* pSymbol )
{
    void* pSym = NULL;
    if( mpGLLib )
    {
        OUString aSym = OUString::createFromAscii( pSymbol );
        pSym = osl_getSymbol( mpGLLib, aSym.pData );
    }
    return pSym;
}

BOOL X11SalOpenGL::ImplInit()
{
    if( ! mpGLLib )
    {
        ByteString sNoGL( getenv( "SAL_NOOPENGL" ) );
        if( sNoGL.ToLowerAscii() == "true"  )
            return FALSE;

        sal_Int32 nRtldMode = SAL_LOADMODULE_NOW;
        #ifdef SOLARIS
        /* #i36866# an obscure interaction with jvm can let java crash
        *  if we do not use SAL_LOADMODULE_GLOBAL here
        */
        nRtldMode |= SAL_LOADMODULE_GLOBAL;

        /* #i36899# and we need Xm, too, else jvm will not work properly.
        */
        OUString aMotifName( RTL_CONSTASCII_USTRINGPARAM( "libXm.so" ) );
        aMotifLib = osl_loadModule( aMotifName.pData, nRtldMode );
        #endif
        OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( OGL_LIBNAME ) );
        mpGLLib = osl_loadModule( aLibName.pData, nRtldMode );
    }
    if( ! mpGLLib )
    {
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, OGL_LIBNAME "could not be opened\n" );
#endif
        return FALSE;
    }

    // Internal use
    pCreateContext     = (GLXContext(*)(Display*,XVisualInfo*,GLXContext,Bool ))
        resolveSymbol( "glXCreateContext" );
    pDestroyContext    = (void(*)(Display*,GLXContext))
        resolveSymbol( "glXDestroyContext" );
    pGetCurrentContext = (GLXContext(*)())
        resolveSymbol( "glXGetCurrentContext" );
    pMakeCurrent       = (Bool(*)(Display*,GLXDrawable,GLXContext))
        resolveSymbol( "glXMakeCurrent" );
    pSwapBuffers=(void(*)(Display*, GLXDrawable))
        resolveSymbol( "glXSwapBuffers" );
    pGetConfig = (int(*)(Display*, XVisualInfo*, int, int* ))
        resolveSymbol( "glXGetConfig" );
    pFlush = (void(*)())
        resolveSymbol( "glFlush" );

    BOOL bRet = pCreateContext && pDestroyContext && pGetCurrentContext && pMakeCurrent && pSwapBuffers && pGetConfig ? TRUE : FALSE;

#if OSL_DEBUG_LEVEL > 1
    if( ! bRet )
        fprintf( stderr, "could not find all needed symbols in " OGL_LIBNAME "\n" );
#endif

    return bRet;
}

void X11SalOpenGL::StartScene( SalGraphics* pGraphics )
{
    // flush pending operations which otherwise might be drawn
    // at the wrong time
    XSync( mpDisplay, False );
}

void X11SalOpenGL::StopScene()
{
    if( maDrawable )
    {
        pSwapBuffers( mpDisplay, maDrawable );
        pFlush();
    }
}

void X11SalOpenGL::MakeVisualWeights( Display* pDisplay,
                                   XVisualInfo* pInfos,
                                   int *pWeights,
                                   int nVisuals )
{
    BOOL bHasGLX = FALSE;
    char **ppExtensions;
    int nExtensions,i ;

    // GLX only on local displays due to strange problems
    // with remote GLX
    if( ! ( *DisplayString( pDisplay ) == ':'                           ||
            !strncmp( DisplayString( pDisplay ), "localhost:", 10 )
            ) )
        return;

    ppExtensions = XListExtensions( pDisplay, &nExtensions );
    for( i=0; i < nExtensions; i++ )
    {
        if( ! strncmp( "GLX", ppExtensions[ i ], 3 ) )
        {
            bHasGLX = TRUE;
            break;
        }
    }
    XFreeExtensionList( ppExtensions );
    if( ! bHasGLX )
        return;

    if( ! ImplInit() )
        return;

    for( i = 0; i < nVisuals; i++ )
    {
        int nDoubleBuffer = 0;
        int nHaveGL = 0;
        // a weight lesser than zero indicates an invalid visual (wrong screen)
        if( pInfos[i].c_class == TrueColor && pInfos[i].depth > 14 && pWeights[i] >= 0)
        {
            pGetConfig( pDisplay, &pInfos[ i ], GLX_USE_GL, &nHaveGL );
            pGetConfig( pDisplay, &pInfos[ i ], GLX_DOUBLEBUFFER, &nDoubleBuffer );
            if( nHaveGL && ! nDoubleBuffer )
            {
                mbHaveGLVisual = TRUE;
                pWeights[ i ] += 65536;
            }
        }
    }
}
<commit_msg>INTEGRATION: CWS warnings01 (1.15.70); FILE MERGED 2005/11/11 14:31:28 pl 1.15.70.1: #i55991# removed warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: salogl.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 19:55:10 $
 *
 *  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 <salunx.h>

#ifndef _SV_SALDATA_HXX
#include <saldata.hxx>
#endif

#ifndef _SV_SALDISP_HXX
#include <saldisp.hxx>
#endif

#ifndef _SV_SALOGL_H
#include <salogl.h>
#endif

#ifndef _SV_SALGDI_H
#include <salgdi.h>
#endif

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

using namespace rtl;

// ------------
// - Lib-Name -
// ------------

#ifdef MACOSX
#define OGL_LIBNAME "libGL.dylib"
#else
#define OGL_LIBNAME "libGL.so.1"
#endif

// ----------
// - Macros -
// ----------

// -----------------
// - Statics init. -
// -----------------

// Members
GLXContext      X11SalOpenGL::maGLXContext = 0;
Display*        X11SalOpenGL::mpDisplay    = 0;
XVisualInfo*    X11SalOpenGL::mpVisualInfo = 0;
BOOL            X11SalOpenGL::mbHaveGLVisual = FALSE;

oslModule      X11SalOpenGL::mpGLLib    = 0;
#ifdef SOLARIS
oslModule      aMotifLib;
#endif

ULONG       X11SalOpenGL::mnOGLState = OGL_STATE_UNLOADED;

GLXContext (*X11SalOpenGL::pCreateContext)( Display *, XVisualInfo *, GLXContext, Bool ) = 0;
void       (*X11SalOpenGL::pDestroyContext)( Display *, GLXContext ) = 0;
GLXContext (*X11SalOpenGL::pGetCurrentContext)( ) = 0;
Bool       (*X11SalOpenGL::pMakeCurrent)( Display *, GLXDrawable, GLXContext ) = 0;
void        (*X11SalOpenGL::pSwapBuffers)( Display*, GLXDrawable ) = 0;
int         (*X11SalOpenGL::pGetConfig)( Display*, XVisualInfo*, int, int* ) = 0;
void       (*X11SalOpenGL::pFlush)() = 0;

// -------------
// - X11SalOpenGL -
// -------------

X11SalOpenGL::X11SalOpenGL( SalGraphics* pSGraphics )
{
    X11SalGraphics* pGraphics = static_cast<X11SalGraphics*>(pSGraphics);
    mpDisplay    = pGraphics->GetXDisplay();
    mpVisualInfo = pGraphics->GetDisplay()->GetVisual();
    maDrawable   = pGraphics->GetDrawable();
}

// ------------------------------------------------------------------------

X11SalOpenGL::~X11SalOpenGL()
{
}

// ------------------------------------------------------------------------

bool X11SalOpenGL::IsValid()
{
    if( OGL_STATE_UNLOADED == mnOGLState )
    {
        BOOL bHasGLX = FALSE;
        char **ppExtensions;
        int nExtensions;

        if( *DisplayString( mpDisplay ) == ':'                          ||
            ! strncmp( DisplayString( mpDisplay ), "localhost:", 10 )
            )
        {
            // GLX only on local displays due to strange problems
            // with remote GLX
            ppExtensions = XListExtensions( mpDisplay, &nExtensions );
            for( int i=0; i < nExtensions; i++ )
            {
                if( ! strncmp( "GLX", ppExtensions[ i ], 3 ) )
                {
                    bHasGLX = TRUE;
                    break;
                }
            }
            XFreeExtensionList( ppExtensions );
#if OSL_DEBUG_LEVEL > 1
            if( ! bHasGLX )
                fprintf( stderr, "XServer does not support GLX extension\n" );
#endif
            if( bHasGLX )
            {
                /*
                 *  #82406# the XFree4.0 GLX module does not seem
                 *  to work that great, at least not the one that comes
                 *  with the default installation and Matrox cards.
                 *  Since these are common we disable usage of
                 *  OpenGL per default.
                 */
                static const char* pOverrideGLX = getenv( "SAL_ENABLE_GLX_XFREE4" );
                if( ! strncmp( ServerVendor( mpDisplay ), "The XFree86 Project, Inc", 24 ) &&
                    VendorRelease( mpDisplay ) >= 4000 &&
                    ! pOverrideGLX
                    )
                {
#if OSL_DEBUG_LEVEL > 1
                    fprintf( stderr, "disabling GLX usage on XFree >= 4.0\n" );
#endif
                    bHasGLX = FALSE;
                }
            }
        }
        if( bHasGLX && mpVisualInfo->c_class == TrueColor && ImplInit() )
        {
            int nDoubleBuffer = 0;
            int nHaveGL = 0;
            pGetConfig( mpDisplay, mpVisualInfo,
                        GLX_USE_GL, &nHaveGL );
            pGetConfig( mpDisplay, mpVisualInfo,
                        GLX_DOUBLEBUFFER, &nDoubleBuffer );
            if( nHaveGL && ! nDoubleBuffer )
            {
                SalDisplay* pSalDisplay = GetSalData()->GetDisplay();
                BOOL bPreviousState =
                    pSalDisplay->GetXLib()->GetIgnoreXErrors();
                pSalDisplay->GetXLib()->SetIgnoreXErrors( TRUE );
                mbHaveGLVisual = TRUE;

                maGLXContext = pCreateContext( mpDisplay, mpVisualInfo, 0, True );
                if( pSalDisplay->GetXLib()->WasXError() )
                    mbHaveGLVisual = FALSE;
                else
                    pMakeCurrent( mpDisplay, maDrawable, maGLXContext );
                if( pSalDisplay->GetXLib()->WasXError() )
                    mbHaveGLVisual = FALSE;
                pSalDisplay->GetXLib()->SetIgnoreXErrors( bPreviousState );

                if( mbHaveGLVisual )
                    mnOGLState = OGL_STATE_VALID;
                else
                    maGLXContext = None;
            }
        }
        if( mnOGLState != OGL_STATE_VALID )
            mnOGLState = OGL_STATE_INVALID;
#if OSL_DEBUG_LEVEL > 1
        if( mnOGLState == OGL_STATE_VALID )
            fprintf( stderr, "Using GLX on visual id %x.\n", mpVisualInfo->visualid );
        else
            fprintf( stderr, "Not using GLX.\n" );
#endif
    }

    return mnOGLState == OGL_STATE_VALID ? TRUE : FALSE;
}

void X11SalOpenGL::Release()
{
    if( maGLXContext && pDestroyContext )
        pDestroyContext( mpDisplay, maGLXContext );
}

// ------------------------------------------------------------------------

void X11SalOpenGL::ReleaseLib()
{
    if( mpGLLib )
    {
        osl_unloadModule( mpGLLib );
        #ifdef SOLARIS
        if( aMotifLib )
            osl_unloadModule( aMotifLib );
        #endif

        mpGLLib             = 0;
        pCreateContext      = 0;
        pDestroyContext     = 0;
        pGetCurrentContext  = 0;
        pMakeCurrent        = 0;
        pSwapBuffers        = 0;
        pGetConfig          = 0;

        mnOGLState          = OGL_STATE_UNLOADED;
    }
}

// ------------------------------------------------------------------------

oglFunction X11SalOpenGL::GetOGLFnc( const char *pFncName )
{
    return resolveSymbol( pFncName );
}

// ------------------------------------------------------------------------

void X11SalOpenGL::OGLEntry( SalGraphics* pGraphics )
{
    GLXDrawable aDrawable = static_cast<X11SalGraphics*>(pGraphics)->GetDrawable();
    if( aDrawable != maDrawable )
    {
        maDrawable = aDrawable;
        pMakeCurrent( mpDisplay, maDrawable, maGLXContext );
    }
}

// ------------------------------------------------------------------------

void X11SalOpenGL::OGLExit( SalGraphics* )
{
}

// ------------------------------------------------------------------------

oglFunction X11SalOpenGL::resolveSymbol( const char* pSymbol )
{
    oglFunction pSym = NULL;
    if( mpGLLib )
    {
        OUString aSym = OUString::createFromAscii( pSymbol );
        pSym = osl_getFunctionSymbol( mpGLLib, aSym.pData );
    }
    return pSym;
}

BOOL X11SalOpenGL::ImplInit()
{
    if( ! mpGLLib )
    {
        ByteString sNoGL( getenv( "SAL_NOOPENGL" ) );
        if( sNoGL.ToLowerAscii() == "true"  )
            return FALSE;

        sal_Int32 nRtldMode = SAL_LOADMODULE_NOW;
        #ifdef SOLARIS
        /* #i36866# an obscure interaction with jvm can let java crash
        *  if we do not use SAL_LOADMODULE_GLOBAL here
        */
        nRtldMode |= SAL_LOADMODULE_GLOBAL;

        /* #i36899# and we need Xm, too, else jvm will not work properly.
        */
        OUString aMotifName( RTL_CONSTASCII_USTRINGPARAM( "libXm.so" ) );
        aMotifLib = osl_loadModule( aMotifName.pData, nRtldMode );
        #endif
        OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( OGL_LIBNAME ) );
        mpGLLib = osl_loadModule( aLibName.pData, nRtldMode );
    }
    if( ! mpGLLib )
    {
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, OGL_LIBNAME "could not be opened\n" );
#endif
        return FALSE;
    }

    // Internal use
    pCreateContext     = (GLXContext(*)(Display*,XVisualInfo*,GLXContext,Bool ))
        resolveSymbol( "glXCreateContext" );
    pDestroyContext    = (void(*)(Display*,GLXContext))
        resolveSymbol( "glXDestroyContext" );
    pGetCurrentContext = (GLXContext(*)())
        resolveSymbol( "glXGetCurrentContext" );
    pMakeCurrent       = (Bool(*)(Display*,GLXDrawable,GLXContext))
        resolveSymbol( "glXMakeCurrent" );
    pSwapBuffers=(void(*)(Display*, GLXDrawable))
        resolveSymbol( "glXSwapBuffers" );
    pGetConfig = (int(*)(Display*, XVisualInfo*, int, int* ))
        resolveSymbol( "glXGetConfig" );
    pFlush = (void(*)())
        resolveSymbol( "glFlush" );

    BOOL bRet = pCreateContext && pDestroyContext && pGetCurrentContext && pMakeCurrent && pSwapBuffers && pGetConfig ? TRUE : FALSE;

#if OSL_DEBUG_LEVEL > 1
    if( ! bRet )
        fprintf( stderr, "could not find all needed symbols in " OGL_LIBNAME "\n" );
#endif

    return bRet;
}

void X11SalOpenGL::StartScene( SalGraphics* )
{
    // flush pending operations which otherwise might be drawn
    // at the wrong time
    XSync( mpDisplay, False );
}

void X11SalOpenGL::StopScene()
{
    if( maDrawable )
    {
        pSwapBuffers( mpDisplay, maDrawable );
        pFlush();
    }
}

void X11SalOpenGL::MakeVisualWeights( Display* pDisplay,
                                   XVisualInfo* pInfos,
                                   int *pWeights,
                                   int nVisuals )
{
    BOOL bHasGLX = FALSE;
    char **ppExtensions;
    int nExtensions,i ;

    // GLX only on local displays due to strange problems
    // with remote GLX
    if( ! ( *DisplayString( pDisplay ) == ':'                           ||
            !strncmp( DisplayString( pDisplay ), "localhost:", 10 )
            ) )
        return;

    ppExtensions = XListExtensions( pDisplay, &nExtensions );
    for( i=0; i < nExtensions; i++ )
    {
        if( ! strncmp( "GLX", ppExtensions[ i ], 3 ) )
        {
            bHasGLX = TRUE;
            break;
        }
    }
    XFreeExtensionList( ppExtensions );
    if( ! bHasGLX )
        return;

    if( ! ImplInit() )
        return;

    for( i = 0; i < nVisuals; i++ )
    {
        int nDoubleBuffer = 0;
        int nHaveGL = 0;
        // a weight lesser than zero indicates an invalid visual (wrong screen)
        if( pInfos[i].c_class == TrueColor && pInfos[i].depth > 14 && pWeights[i] >= 0)
        {
            pGetConfig( pDisplay, &pInfos[ i ], GLX_USE_GL, &nHaveGL );
            pGetConfig( pDisplay, &pInfos[ i ], GLX_DOUBLEBUFFER, &nDoubleBuffer );
            if( nHaveGL && ! nDoubleBuffer )
            {
                mbHaveGLVisual = TRUE;
                pWeights[ i ] += 65536;
            }
        }
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: undoheaderfooter.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-08-23 08:23:02 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SD_UNDOHEADERFOOTER_HXX
#define _SD_UNDOHEADERFOOTER_HXX

#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif

#ifndef _SD_SDUNDO_HXX
#include "sdundo.hxx"
#endif
#ifndef _SDPAGE_HXX
#include "sdpage.hxx"
#endif

#ifndef INCLUDED_SDDLLAPI_H
#include "sddllapi.h"
#endif

class SdDrawDocument;

/************************************************************************/

class SD_DLLPUBLIC SdHeaderFooterUndoAction : public SdUndoAction
{
    SdPage*     mpPage;

    const sd::HeaderFooterSettings  maOldSettings;
    const sd::HeaderFooterSettings  maNewSettings;

public:
    TYPEINFO();
    SdHeaderFooterUndoAction( SdDrawDocument* pDoc, SdPage* pPage, const sd::HeaderFooterSettings& rNewSettings );
    virtual ~SdHeaderFooterUndoAction();

    virtual void Undo();
    virtual void Redo();
    virtual void Repeat();
};

#endif      // _SD_UNDOHEADERFOOTER_HXX

<commit_msg>INTEGRATION: CWS ooo19126 (1.3.374); FILE MERGED 2005/09/05 13:23:31 rt 1.3.374.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: undoheaderfooter.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 05:57:39 $
 *
 *  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 _SD_UNDOHEADERFOOTER_HXX
#define _SD_UNDOHEADERFOOTER_HXX

#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif

#ifndef _SD_SDUNDO_HXX
#include "sdundo.hxx"
#endif
#ifndef _SDPAGE_HXX
#include "sdpage.hxx"
#endif

#ifndef INCLUDED_SDDLLAPI_H
#include "sddllapi.h"
#endif

class SdDrawDocument;

/************************************************************************/

class SD_DLLPUBLIC SdHeaderFooterUndoAction : public SdUndoAction
{
    SdPage*     mpPage;

    const sd::HeaderFooterSettings  maOldSettings;
    const sd::HeaderFooterSettings  maNewSettings;

public:
    TYPEINFO();
    SdHeaderFooterUndoAction( SdDrawDocument* pDoc, SdPage* pPage, const sd::HeaderFooterSettings& rNewSettings );
    virtual ~SdHeaderFooterUndoAction();

    virtual void Undo();
    virtual void Redo();
    virtual void Repeat();
};

#endif      // _SD_UNDOHEADERFOOTER_HXX

<|endoftext|>


<commit_before>/*
 * Copyright 2011 Simon A. F. Lund <safl@safl.dk>
 *
 * This file is part of cphVB.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */
#include <cphvb.h>
#include "cphvb_ve_simple.h"

static cphvb_com *myself = NULL;
static cphvb_userfunc_impl reduce_impl = NULL;
static cphvb_intp reduce_impl_id = 0;
static cphvb_userfunc_impl random_impl = NULL;
static cphvb_intp random_impl_id = 0;

cphvb_error cphvb_ve_simple_init(cphvb_com *self)
{
    myself = self;
    return CPHVB_SUCCESS;
}

cphvb_error cphvb_ve_simple_execute( cphvb_intp instruction_count, cphvb_instruction* instruction_list )
{
    cphvb_intp count, nops, i;
    cphvb_instruction* inst;
    cphvb_error ret = CPHVB_SUCCESS;

    for(count=0; count < instruction_count; count++)
    {
        inst = &instruction_list[count];

        if(inst->status == CPHVB_INST_DONE)     // SKIP instruction
        {
            continue;
        }

        nops = cphvb_operands(inst->opcode);    // Allocate memory for operands
        for(i=0; i<nops; i++)
        {
            if (!cphvb_is_constant(inst->operand[i]))
            {
                if (cphvb_data_malloc(inst->operand[i]) != CPHVB_SUCCESS)
                {
                    return CPHVB_OUT_OF_MEMORY; // EXIT
                }
            }

        }

        switch(inst->opcode)                    // Dispatch instruction
        {
            case CPHVB_NONE:                    // NOOP.
            case CPHVB_DISCARD:
            case CPHVB_SYNC:
                inst->status = CPHVB_INST_DONE;
                break;

            case CPHVB_USERFUNC:                // External libraries

                if(inst->userfunc->id == reduce_impl_id)
                {
                    ret = reduce_impl(inst->userfunc, NULL);
                    inst->status = (ret == CPHVB_SUCCESS) ? CPHVB_INST_DONE : CPHVB_INST_UNDONE;
                }
                else if(inst->userfunc->id == random_impl_id)
                {
                    ret = random_impl(inst->userfunc, NULL);
                    inst->status = (ret == CPHVB_SUCCESS) ? CPHVB_INST_DONE : CPHVB_INST_UNDONE;
                }
                else                            // Unsupported userfunc
                {
                    ret = CPHVB_TYPE_NOT_SUPPORTED;
                }

                break;

            default:                            // Built-in operations
                ret = cphvb_compute_apply( inst );
                inst->status = (ret == CPHVB_SUCCESS) ? CPHVB_INST_DONE : CPHVB_INST_UNDONE;
        }

        if (inst->status != CPHVB_INST_DONE)    // Instruction failed
        {
            return ret;                         // EXIT
        }

    }
                                                // All instructions succeeded.
    return ret;                                 // EXIT

}

cphvb_error cphvb_ve_simple_shutdown( void )
{
    return CPHVB_SUCCESS;
}

cphvb_error cphvb_ve_simple_reg_func(char *lib, char *fun, cphvb_intp *id) {

    if(strcmp("cphvb_reduce", fun) && reduce_impl == NULL)
    {
        cphvb_com_get_func(myself, lib, fun, &reduce_impl);
        reduce_impl_id = *id;
    }
    else if(strcmp("cphvb_random", fun) && random_impl == NULL)
    {
        cphvb_com_get_func(myself, lib, fun, &random_impl);
        random_impl_id = *id;
    }
    return CPHVB_SUCCESS;
}

cphvb_error cphvb_reduce( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_reduce( arg, ve_arg );
}

cphvb_error cphvb_random( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_random( arg, ve_arg );
}
<commit_msg>Adjusted return-value of simple engine.<commit_after>/*
 * Copyright 2011 Simon A. F. Lund <safl@safl.dk>
 *
 * This file is part of cphVB.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */
#include <cphvb.h>
#include "cphvb_ve_simple.h"

static cphvb_com *myself = NULL;
static cphvb_userfunc_impl reduce_impl = NULL;
static cphvb_intp reduce_impl_id = 0;
static cphvb_userfunc_impl random_impl = NULL;
static cphvb_intp random_impl_id = 0;

cphvb_error cphvb_ve_simple_init(cphvb_com *self)
{
    myself = self;
    return CPHVB_SUCCESS;
}

cphvb_error cphvb_ve_simple_execute( cphvb_intp instruction_count, cphvb_instruction* instruction_list )
{
    cphvb_intp count, nops, i;
    cphvb_instruction* inst;
    cphvb_error ret = CPHVB_SUCCESS;

    for(count=0; count < instruction_count; count++)
    {
        inst = &instruction_list[count];

        if(inst->status == CPHVB_INST_DONE)     // SKIP instruction
        {
            continue;
        }

        nops = cphvb_operands(inst->opcode);    // Allocate memory for operands
        for(i=0; i<nops; i++)
        {
            if (!cphvb_is_constant(inst->operand[i]))
            {
                if (cphvb_data_malloc(inst->operand[i]) != CPHVB_SUCCESS)
                {
                    return CPHVB_OUT_OF_MEMORY; // EXIT
                }
            }

        }

        switch(inst->opcode)                    // Dispatch instruction
        {
            case CPHVB_NONE:                    // NOOP.
            case CPHVB_DISCARD:
            case CPHVB_SYNC:
                inst->status = CPHVB_INST_DONE;
                break;

            case CPHVB_USERFUNC:                // External libraries

                if(inst->userfunc->id == reduce_impl_id)
                {
                    ret = reduce_impl(inst->userfunc, NULL);
                    inst->status = (ret == CPHVB_SUCCESS) ? CPHVB_INST_DONE : CPHVB_INST_UNDONE;
                }
                else if(inst->userfunc->id == random_impl_id)
                {
                    ret = random_impl(inst->userfunc, NULL);
                    inst->status = (ret == CPHVB_SUCCESS) ? CPHVB_INST_DONE : CPHVB_INST_UNDONE;
                }
                else                            // Unsupported userfunc
                {
                    inst->status = CPHVB_INST_UNDONE;
                }

                break;

            default:                            // Built-in operations
                ret = cphvb_compute_apply( inst );
                inst->status = (ret == CPHVB_SUCCESS) ? CPHVB_INST_DONE : CPHVB_INST_UNDONE;
        }

        if (inst->status != CPHVB_INST_DONE)    // Instruction failed
        {
            break;
        }

    }

    if (count == instruction_count) {
        return CPHVB_SUCCESS;
    } else {
        return CPHVB_PARTIAL_SUCCESS;
    }

}

cphvb_error cphvb_ve_simple_shutdown( void )
{
    return CPHVB_SUCCESS;
}

cphvb_error cphvb_ve_simple_reg_func(char *lib, char *fun, cphvb_intp *id) {

    if(strcmp("cphvb_reduce", fun) && reduce_impl == NULL)
    {
        cphvb_com_get_func(myself, lib, fun, &reduce_impl);
        reduce_impl_id = *id;
    }
    else if(strcmp("cphvb_random", fun) && random_impl == NULL)
    {
        cphvb_com_get_func(myself, lib, fun, &random_impl);
        random_impl_id = *id;
    }
    return CPHVB_SUCCESS;
}

cphvb_error cphvb_reduce( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_reduce( arg, ve_arg );
}

cphvb_error cphvb_random( cphvb_userfunc *arg, void* ve_arg)
{
    return cphvb_compute_random( arg, ve_arg );
}
<|endoftext|>