<commit_before>#include "TriggerRepeat.hpp"

#include "../Component/RigidBody.hpp"
#include "../Entity/Entity.hpp"
#include "../Manager/Managers.hpp"
#include "../Manager/PhysicsManager.hpp"
#include "../Manager/ScriptManager.hpp"

TriggerRepeat::TriggerRepeat() {

}

TriggerRepeat::~TriggerRepeat() {

}

void TriggerRepeat::OnEnter() {
    if (collidedEntity && collidedEntity->GetComponent<Component::RigidBody>()) {
        Component::RigidBody* rigidBodyComp = collidedEntity->GetComponent<Component::RigidBody>();
        Managers().physicsManager->ForgetTriggerEnter(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerRetain(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerLeave(triggerVolume, rigidBodyComp);
        Managers().physicsManager->OnTriggerEnter(triggerVolume, rigidBodyComp, std::bind(&TriggerRepeat::HandleTriggerEvent, this));
    }
}

void TriggerRepeat::OnRetain() {
    if (collidedEntity && collidedEntity->GetComponent<Component::RigidBody>()) {
        Component::RigidBody* rigidBodyComp = collidedEntity->GetComponent<Component::RigidBody>();
        Managers().physicsManager->ForgetTriggerEnter(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerRetain(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerLeave(triggerVolume, rigidBodyComp);
        Managers().physicsManager->OnTriggerRetain(triggerVolume, rigidBodyComp, std::bind(&TriggerRepeat::HandleTriggerEvent, this));
    }
}

void TriggerRepeat::OnLeave() {
    if (collidedEntity && collidedEntity->GetComponent<Component::RigidBody>()) {
        Component::RigidBody* rigidBodyComp = collidedEntity->GetComponent<Component::RigidBody>();
        Managers().physicsManager->ForgetTriggerEnter(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerRetain(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerLeave(triggerVolume, rigidBodyComp);
        Managers().physicsManager->OnTriggerLeave(triggerVolume, rigidBodyComp, std::bind(&TriggerRepeat::HandleTriggerEvent, this));
    }
}

std::string TriggerRepeat::GetName() {
    return name;
}

void TriggerRepeat::SetName(std::string value) {
    name = value;
}

std::string TriggerRepeat::GetTargetFunction() {
    return targetFunction;
}

void TriggerRepeat::SetTargetFunction(std::string value) {
    targetFunction = value;
}

bool TriggerRepeat::GetStartActive() {
    return startActive;
}

void TriggerRepeat::SetStartActive(bool value) {
    startActive = value;
}

float TriggerRepeat::GetDelay() {
    return delay;
}

void TriggerRepeat::SetDelay(float value) {
    delay = value;
}

float TriggerRepeat::GetCooldown() {
    return cooldown;
}

void TriggerRepeat::SetCooldown(float value) {
    cooldown = value;
}

float TriggerRepeat::GetTriggerCharges() {
    return triggerCharges;
}

void TriggerRepeat::SetTriggerCharges(float value) {
    triggerCharges = value;
}

Entity* TriggerRepeat::GetTargetEntity() {
    return targetEntity;
}

void TriggerRepeat::SetTargetEntity(Entity* value) {
    targetEntity = value;
}

Entity* TriggerRepeat::GetCollidedEntity() {
    return collidedEntity;
}

void TriggerRepeat::SetCollidedEntity(Entity* value) {
    collidedEntity = value;
}

void TriggerRepeat::HandleTriggerEvent() {
    triggered = true;
}

void TriggerRepeat::Process() {
    if (triggered)
        Managers().scriptManager->ExecuteScriptMethod(targetEntity, targetFunction);
}
<commit_msg>Reset trigger tracking after processing a repeat trigger.<commit_after>#include "TriggerRepeat.hpp"

#include "../Component/RigidBody.hpp"
#include "../Entity/Entity.hpp"
#include "../Manager/Managers.hpp"
#include "../Manager/PhysicsManager.hpp"
#include "../Manager/ScriptManager.hpp"

TriggerRepeat::TriggerRepeat() {

}

TriggerRepeat::~TriggerRepeat() {

}

void TriggerRepeat::OnEnter() {
    if (collidedEntity && collidedEntity->GetComponent<Component::RigidBody>()) {
        Component::RigidBody* rigidBodyComp = collidedEntity->GetComponent<Component::RigidBody>();
        Managers().physicsManager->ForgetTriggerEnter(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerRetain(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerLeave(triggerVolume, rigidBodyComp);
        Managers().physicsManager->OnTriggerEnter(triggerVolume, rigidBodyComp, std::bind(&TriggerRepeat::HandleTriggerEvent, this));
    }
}

void TriggerRepeat::OnRetain() {
    if (collidedEntity && collidedEntity->GetComponent<Component::RigidBody>()) {
        Component::RigidBody* rigidBodyComp = collidedEntity->GetComponent<Component::RigidBody>();
        Managers().physicsManager->ForgetTriggerEnter(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerRetain(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerLeave(triggerVolume, rigidBodyComp);
        Managers().physicsManager->OnTriggerRetain(triggerVolume, rigidBodyComp, std::bind(&TriggerRepeat::HandleTriggerEvent, this));
    }
}

void TriggerRepeat::OnLeave() {
    if (collidedEntity && collidedEntity->GetComponent<Component::RigidBody>()) {
        Component::RigidBody* rigidBodyComp = collidedEntity->GetComponent<Component::RigidBody>();
        Managers().physicsManager->ForgetTriggerEnter(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerRetain(triggerVolume, rigidBodyComp);
        Managers().physicsManager->ForgetTriggerLeave(triggerVolume, rigidBodyComp);
        Managers().physicsManager->OnTriggerLeave(triggerVolume, rigidBodyComp, std::bind(&TriggerRepeat::HandleTriggerEvent, this));
    }
}

std::string TriggerRepeat::GetName() {
    return name;
}

void TriggerRepeat::SetName(std::string value) {
    name = value;
}

std::string TriggerRepeat::GetTargetFunction() {
    return targetFunction;
}

void TriggerRepeat::SetTargetFunction(std::string value) {
    targetFunction = value;
}

bool TriggerRepeat::GetStartActive() {
    return startActive;
}

void TriggerRepeat::SetStartActive(bool value) {
    startActive = value;
}

float TriggerRepeat::GetDelay() {
    return delay;
}

void TriggerRepeat::SetDelay(float value) {
    delay = value;
}

float TriggerRepeat::GetCooldown() {
    return cooldown;
}

void TriggerRepeat::SetCooldown(float value) {
    cooldown = value;
}

float TriggerRepeat::GetTriggerCharges() {
    return triggerCharges;
}

void TriggerRepeat::SetTriggerCharges(float value) {
    triggerCharges = value;
}

Entity* TriggerRepeat::GetTargetEntity() {
    return targetEntity;
}

void TriggerRepeat::SetTargetEntity(Entity* value) {
    targetEntity = value;
}

Entity* TriggerRepeat::GetCollidedEntity() {
    return collidedEntity;
}

void TriggerRepeat::SetCollidedEntity(Entity* value) {
    collidedEntity = value;
}

void TriggerRepeat::HandleTriggerEvent() {
    triggered = true;
}

void TriggerRepeat::Process() {
    if (triggered) {
        Managers().scriptManager->ExecuteScriptMethod(targetEntity, targetFunction);
        triggered = false;
    }
}
<|endoftext|>


<commit_before>// File_Cdxa - Info for CDXA files
// Copyright (C) 2004-2008 Jerome Martinez, Zen@MediaArea.net
//
// 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 3 of the License, or
// 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, see <http://www.gnu.org/licenses/>.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//---------------------------------------------------------------------------
// Compilation conditions
#include <MediaInfo/Setup.h>
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_CDXA_YES)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Multiple/File_Cdxa.h"
#include "ZenLib/Utils.h"
#include "MediaInfo/MediaInfo.h"
using namespace ZenLib;
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Format
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// CDXA = RIFF header + Raw sectors
// Riff header size = 44
// Raw sector size = 2352
//
// Raw sector :
// Sync             12 bytes (00 FF .. FF 00)
// Header           4 bytes
// SubHeader        8 bytes
// Datas            2324 bytes
// EDC (CRC)        4 bytes
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//***************************************************************************
// Constructor/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
File_Cdxa::File_Cdxa()
:File__Analyze()
{
    //Basic configuration
    Synched=false;
    File_MaximumOffset=64*1024;
    Frame_Count_Valid=16;

    //Buffer
    Element_Size=0;

    //Temp - Global
    Frame_Count=0;

    //Pointers
    MI=NULL;
}

//---------------------------------------------------------------------------
File_Cdxa::~File_Cdxa()
{
    delete MI; //MI=NULL;
}

//***************************************************************************
// Format
//***************************************************************************

//---------------------------------------------------------------------------
void File_Cdxa::Read_Buffer_Finalize ()
{
    //If nothing
    if (MI->Info==NULL|| MI->Count_Get(Stream_General)==0)
    {
        Fill(Stream_General, 0, General_Format, "CDXA");
    }
    else
    {

        //General
        Open_Buffer_Finalize(MI);
        Merge(*(MI->Info));
        Merge(*(MI->Info), Stream_General, 0, 0);
        const Ztring &Format=Retrieve(Stream_General, 0, General_Format);
        Fill(Stream_General, 0, General_Format, (Ztring(_T("CDXA/"))+Format).c_str(), Unlimited, true);
        Fill(Stream_General, 0, General_Duration, "", Unlimited, true);
        Fill(Stream_Video, 0, Video_Duration, "", Unlimited, true);
    }

    //Purge what is not needed anymore
    if (!File_Name.empty()) //Only if this is not a buffer, with buffer we can have more data
    {
        delete MI; MI=NULL;
    }
}

//***************************************************************************
// Buffer
//***************************************************************************

//---------------------------------------------------------------------------
// RIFF Header, 44 bytes
// RIFF header                      4 bytes, Pos=0
// RIFF data size                   4 bytes, Pos=4
// Format (CDXA)                    4 bytes, Pos=8
// Format Header                    4 bytes, Pos=12
// Format Size                      4 bytes, Pos=16
// Format user_id                   2 bytes, Pos=20
// Format group_id                  2 bytes, Pos=22
// Format attributes                2 bytes, Pos=24
// Format xa_signature              2 bytes, Pos=26 ("XA")
// Format xa_track_number           4 bytes, Pos=28
// Format Reserved                  4 bytes, Pos=32
// Data Header                      4 bytes, Pos=36
// Data Size                        4 bytes, Pos=40
//
// Attributes (big endian):
// 15 Directory
// 14 CDDA
// 13 Interleaved
// 12 Mode2Form2 --> 2324 bytes/block
// 11 Mode2Form1 --> 2048 bytes/block
// 10 Exec_Other
// 09 Reserved
// 08 Read_Other
// 07 Reserved
// 06 Exec_Group
// 05 Reserved
// 04 Read_Group
// 03 Reserved
// 02 Exec_User
// 01 Reserved
// 00 Read_User
//
void File_Cdxa::FileHeader_Parse()
{
    if (Element_Size<44)
    {
        Element_WaitForMoreData();
        return;
    }

    //Parsing
    if (                CC4(Buffer+Buffer_Offset+0x00)!=CC4("RIFF")
     || LittleEndian2int32u(Buffer+Buffer_Offset+0x04)!=LittleEndian2int32u(Buffer+Buffer_Offset+0x28)+0x24 //Sizes of chunks
     ||                 CC4(Buffer+Buffer_Offset+0x08)!=CC4("CDXA")
     ||                 CC4(Buffer+Buffer_Offset+0x0C)!=CC4("fmt ")
     || LittleEndian2int32u(Buffer+Buffer_Offset+0x10)!=0x10
     ||                 CC4(Buffer+Buffer_Offset+0x24)!=CC4("data")
       )
    {
        Finnished();
        return;
    }

    //Parsing
    Element_Begin("CDXA header");
    Skip_C4(                                                    "RIFF header");
    Skip_L4(                                                    "RIFF data size");
    Skip_C4(                                                    "CDXA");
    Skip_C4(                                                    "fmt header");
    Skip_L4(                                                    "fmt size");
    Skip_L2(                                                    "user_id");
    Skip_L2(                                                    "group_id");
    Skip_L2(                                                    "attributes");
    Skip_C2(                                                    "xa_signature");
    Skip_L4(                                                    "xa_track_number");
    Skip_L4(                                                    "reserved");
    Skip_C4(                                                    "data header");
    Skip_L4(                                                    "data size");
    Element_End();

    FILLING_BEGIN();
        if (MI==NULL)
        {
            MI=new MediaInfo_Internal;
            MI->Option(_T("File_IsSub"), _T("1"));
        }

        Stream_Prepare(Stream_General);
    FILLING_END();
}

//---------------------------------------------------------------------------
bool File_Cdxa::Header_Begin()
{
    //Must have enough buffer for having header
    if (Buffer_Offset+12>Buffer_Size)
        return false;

    //Quick test of synchro
    if (Synched && !(CC8(Buffer+Buffer_Offset)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+8)==0xFFFFFF00))
    {
        Trusted_IsNot("CDXA, Synchronisation lost");
        Synched=false;
    }

    //Synchro
    if (!Synched && !Synchronize())
        return false;

    //All should be OK...
    return true;
}

//---------------------------------------------------------------------------
void File_Cdxa::Header_Parse()
{
    //Parsing
    Skip_B4(                                                    "Sync1");
    Skip_B4(                                                    "Sync2");
    Skip_B4(                                                    "Sync3");
    Skip_B4(                                                    "Header");
    Skip_B8(                                                    "SubHeader");

    //Filling
    Header_Fill_Size(2352);
    Header_Fill_Code(0, "Chunk");
}

//---------------------------------------------------------------------------
void File_Cdxa::Data_Parse()
{
    if (MI==NULL)
    {
        //Where is the header? --> Problem
        Finnished();
        return;
    }

    //CRC or not?
    int64u CRC_Size=4;
    if (Element_Size!=2328)
        CRC_Size=0;

    //Parsing
    Skip_XX(Element_Size-CRC_Size,                              "Data");
    if (CRC_Size>0)
        Skip_B4(                                                "CRC");

    //Preparing to fill MediaInfo with a buffer
    MI->Open_Buffer_Init(File_Size, File_Offset+Buffer_Offset);

    //Sending the buffer to MediaInfo
    if (MI->Open_Buffer_Continue(Buffer+Buffer_Offset, (size_t)(Element_Size-CRC_Size))==0)
        Finnished(); //Get out of the loop, there was an error during the parsing

    //Testing if MediaInfo always need data
    File_GoTo=MI->Open_Buffer_Continue_GoTo_Get();
    if (File_GoTo!=(int64u)-1)
        Info("CDXA, Jumping to end of file");

    //Details
    #ifndef MEDIAINFO_MINIMIZESIZE
    if (MediaInfoLib::Config.Details_Get())
    {
        if (!MI->Inform().empty())
            Element_Show_Add(MI->Inform());
    }
    #endif //MEDIAINFO_MINIMIZESIZE

    //Demux
    Demux(Buffer+Buffer_Offset, (size_t)(Element_Size-CRC_Size), _T("xxx"));
}

//***************************************************************************
// Elements
//***************************************************************************

//***************************************************************************
// Helpers
//***************************************************************************

//---------------------------------------------------------------------------
bool File_Cdxa::Synchronize()
{
    //Synchronizing
    while (           Buffer_Offset+2352*3+12<=Buffer_Size
      && !(CC8(Buffer+Buffer_Offset+2352*0)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*0+8)==0xFFFFFF00
        && CC8(Buffer+Buffer_Offset+2352*1)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*1+8)==0xFFFFFF00
        && CC8(Buffer+Buffer_Offset+2352*2)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*2+8)==0xFFFFFF00
        && CC8(Buffer+Buffer_Offset+2352*3)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*3+8)==0xFFFFFF00))
        Buffer_Offset++;
    if (Buffer_Offset+2352*3+12>Buffer_Size)
    {
        return false;
    }

    //Synched is OK
    Synched=true;
    return true;
}

    /*
//---------------------------------------------------------------------------
void File_Cdxa::Detect_EOF()
{
    //Jump to the end of the file
    if (File_Size!=(int64u)-1 && File_Size>File_Offset+Buffer_Size+1*1024*1024 && (
       (File_Offset>1*1024*1024)
    || (MI!=NULL && MI->Open_Buffer_Continue_GoTo_Get()!=(int64u)-1)
    ))
    {
        Info("CDXA, Jumping to end of file");
        File_GoTo=File_Size-1*1024*1024;
    }
}
    */

//***************************************************************************
// Information
//***************************************************************************

//---------------------------------------------------------------------------
void File_Cdxa::HowTo(stream_t StreamKind)
{
    switch (StreamKind)
    {
        case (Stream_General) :
            Fill_HowTo("Format", "R");
            break;
        case (Stream_Video) :
            Fill_HowTo("Codec", "R");
            Fill_HowTo("BitRate", "R|Overall BitRate - Audio BitRates");
            Fill_HowTo("Width", "R");
            Fill_HowTo("Height", "R");
            Fill_HowTo("DisplayAspectRatio", "R");
            break;
        case (Stream_Audio) :
            break;
        case (Stream_Text) :
            break;
        case (Stream_Chapters) :
            break;
        case (Stream_Image) :
            break;
        case (Stream_Menu) :
            break;
        case (Stream_Max) :
            break;
    }
}

} //NameSpace

#endif //MEDIAINFO_CDXA_YES

<commit_msg>Improving Library detection<commit_after>// File_Cdxa - Info for CDXA files
// Copyright (C) 2004-2008 Jerome Martinez, Zen@MediaArea.net
//
// 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 3 of the License, or
// 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, see <http://www.gnu.org/licenses/>.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//---------------------------------------------------------------------------
// Compilation conditions
#include <MediaInfo/Setup.h>
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_CDXA_YES)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Multiple/File_Cdxa.h"
#include "ZenLib/Utils.h"
#include "MediaInfo/MediaInfo.h"
using namespace ZenLib;
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Format
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// CDXA = RIFF header + Raw sectors
// Riff header size = 44
// Raw sector size = 2352
//
// Raw sector :
// Sync             12 bytes (00 FF .. FF 00)
// Header           4 bytes
// SubHeader        8 bytes
// Datas            2324 bytes
// EDC (CRC)        4 bytes
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//***************************************************************************
// Constructor/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
File_Cdxa::File_Cdxa()
:File__Analyze()
{
    //Basic configuration
    Synched=false;
    File_MaximumOffset=64*1024;
    Frame_Count_Valid=16;

    //Buffer
    Element_Size=0;

    //Temp - Global
    Frame_Count=0;

    //Pointers
    MI=NULL;
}

//---------------------------------------------------------------------------
File_Cdxa::~File_Cdxa()
{
    delete MI; //MI=NULL;
}

//***************************************************************************
// Format
//***************************************************************************

//---------------------------------------------------------------------------
void File_Cdxa::Read_Buffer_Finalize ()
{
    //If nothing
    if (MI->Info==NULL|| MI->Count_Get(Stream_General)==0)
    {
        Fill(Stream_General, 0, General_Format, "CDXA");
    }
    else
    {

        //General
        Open_Buffer_Finalize(MI->Info);
        Merge(*(MI->Info));
        Merge(*(MI->Info), Stream_General, 0, 0);
        const Ztring &Format=Retrieve(Stream_General, 0, General_Format);
        Fill(Stream_General, 0, General_Format, (Ztring(_T("CDXA/"))+Format).c_str(), Unlimited, true);
        Fill(Stream_General, 0, General_Duration, "", Unlimited, true);
        Fill(Stream_Video, 0, Video_Duration, "", Unlimited, true);
    }

    //Purge what is not needed anymore
    if (!File_Name.empty()) //Only if this is not a buffer, with buffer we can have more data
    {
        delete MI; MI=NULL;
    }
}

//***************************************************************************
// Buffer
//***************************************************************************

//---------------------------------------------------------------------------
// RIFF Header, 44 bytes
// RIFF header                      4 bytes, Pos=0
// RIFF data size                   4 bytes, Pos=4
// Format (CDXA)                    4 bytes, Pos=8
// Format Header                    4 bytes, Pos=12
// Format Size                      4 bytes, Pos=16
// Format user_id                   2 bytes, Pos=20
// Format group_id                  2 bytes, Pos=22
// Format attributes                2 bytes, Pos=24
// Format xa_signature              2 bytes, Pos=26 ("XA")
// Format xa_track_number           4 bytes, Pos=28
// Format Reserved                  4 bytes, Pos=32
// Data Header                      4 bytes, Pos=36
// Data Size                        4 bytes, Pos=40
//
// Attributes (big endian):
// 15 Directory
// 14 CDDA
// 13 Interleaved
// 12 Mode2Form2 --> 2324 bytes/block
// 11 Mode2Form1 --> 2048 bytes/block
// 10 Exec_Other
// 09 Reserved
// 08 Read_Other
// 07 Reserved
// 06 Exec_Group
// 05 Reserved
// 04 Read_Group
// 03 Reserved
// 02 Exec_User
// 01 Reserved
// 00 Read_User
//
void File_Cdxa::FileHeader_Parse()
{
    if (Element_Size<44)
    {
        Element_WaitForMoreData();
        return;
    }

    //Parsing
    if (                CC4(Buffer+Buffer_Offset+0x00)!=CC4("RIFF")
     || LittleEndian2int32u(Buffer+Buffer_Offset+0x04)!=LittleEndian2int32u(Buffer+Buffer_Offset+0x28)+0x24 //Sizes of chunks
     ||                 CC4(Buffer+Buffer_Offset+0x08)!=CC4("CDXA")
     ||                 CC4(Buffer+Buffer_Offset+0x0C)!=CC4("fmt ")
     || LittleEndian2int32u(Buffer+Buffer_Offset+0x10)!=0x10
     ||                 CC4(Buffer+Buffer_Offset+0x24)!=CC4("data")
       )
    {
        Finnished();
        return;
    }

    //Parsing
    Element_Begin("CDXA header");
    Skip_C4(                                                    "RIFF header");
    Skip_L4(                                                    "RIFF data size");
    Skip_C4(                                                    "CDXA");
    Skip_C4(                                                    "fmt header");
    Skip_L4(                                                    "fmt size");
    Skip_L2(                                                    "user_id");
    Skip_L2(                                                    "group_id");
    Skip_L2(                                                    "attributes");
    Skip_C2(                                                    "xa_signature");
    Skip_L4(                                                    "xa_track_number");
    Skip_L4(                                                    "reserved");
    Skip_C4(                                                    "data header");
    Skip_L4(                                                    "data size");
    Element_End();

    FILLING_BEGIN();
        if (MI==NULL)
        {
            MI=new MediaInfo_Internal;
            MI->Option(_T("File_IsSub"), _T("1"));
        }

        Stream_Prepare(Stream_General);
    FILLING_END();
}

//---------------------------------------------------------------------------
bool File_Cdxa::Header_Begin()
{
    //Must have enough buffer for having header
    if (Buffer_Offset+12>Buffer_Size)
        return false;

    //Quick test of synchro
    if (Synched && !(CC8(Buffer+Buffer_Offset)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+8)==0xFFFFFF00))
    {
        Trusted_IsNot("CDXA, Synchronisation lost");
        Synched=false;
    }

    //Synchro
    if (!Synched && !Synchronize())
        return false;

    //All should be OK...
    return true;
}

//---------------------------------------------------------------------------
void File_Cdxa::Header_Parse()
{
    //Parsing
    Skip_B4(                                                    "Sync1");
    Skip_B4(                                                    "Sync2");
    Skip_B4(                                                    "Sync3");
    Skip_B4(                                                    "Header");
    Skip_B8(                                                    "SubHeader");

    //Filling
    Header_Fill_Size(2352);
    Header_Fill_Code(0, "Chunk");
}

//---------------------------------------------------------------------------
void File_Cdxa::Data_Parse()
{
    if (MI==NULL)
    {
        //Where is the header? --> Problem
        Finnished();
        return;
    }

    //CRC or not?
    int64u CRC_Size=4;
    if (Element_Size!=2328)
        CRC_Size=0;

    //Parsing
    Skip_XX(Element_Size-CRC_Size,                              "Data");
    if (CRC_Size>0)
        Skip_B4(                                                "CRC");

    //Preparing to fill MediaInfo with a buffer
    MI->Open_Buffer_Init(File_Size, File_Offset+Buffer_Offset);

    //Sending the buffer to MediaInfo
    if (MI->Open_Buffer_Continue(Buffer+Buffer_Offset, (size_t)(Element_Size-CRC_Size))==0)
        Finnished(); //Get out of the loop, there was an error during the parsing

    //Testing if MediaInfo always need data
    File_GoTo=MI->Open_Buffer_Continue_GoTo_Get();
    if (File_GoTo!=(int64u)-1)
        Info("CDXA, Jumping to end of file");

    //Details
    #ifndef MEDIAINFO_MINIMIZESIZE
    if (MediaInfoLib::Config.Details_Get())
    {
        if (!MI->Inform().empty())
            Element_Show_Add(MI->Inform());
    }
    #endif //MEDIAINFO_MINIMIZESIZE

    //Demux
    Demux(Buffer+Buffer_Offset, (size_t)(Element_Size-CRC_Size), _T("xxx"));
}

//***************************************************************************
// Elements
//***************************************************************************

//***************************************************************************
// Helpers
//***************************************************************************

//---------------------------------------------------------------------------
bool File_Cdxa::Synchronize()
{
    //Synchronizing
    while (           Buffer_Offset+2352*3+12<=Buffer_Size
      && !(CC8(Buffer+Buffer_Offset+2352*0)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*0+8)==0xFFFFFF00
        && CC8(Buffer+Buffer_Offset+2352*1)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*1+8)==0xFFFFFF00
        && CC8(Buffer+Buffer_Offset+2352*2)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*2+8)==0xFFFFFF00
        && CC8(Buffer+Buffer_Offset+2352*3)==0x00FFFFFFFFFFFFFFLL && CC4(Buffer+Buffer_Offset+2352*3+8)==0xFFFFFF00))
        Buffer_Offset++;
    if (Buffer_Offset+2352*3+12>Buffer_Size)
    {
        return false;
    }

    //Synched is OK
    Synched=true;
    return true;
}

    /*
//---------------------------------------------------------------------------
void File_Cdxa::Detect_EOF()
{
    //Jump to the end of the file
    if (File_Size!=(int64u)-1 && File_Size>File_Offset+Buffer_Size+1*1024*1024 && (
       (File_Offset>1*1024*1024)
    || (MI!=NULL && MI->Open_Buffer_Continue_GoTo_Get()!=(int64u)-1)
    ))
    {
        Info("CDXA, Jumping to end of file");
        File_GoTo=File_Size-1*1024*1024;
    }
}
    */

//***************************************************************************
// Information
//***************************************************************************

//---------------------------------------------------------------------------
void File_Cdxa::HowTo(stream_t StreamKind)
{
    switch (StreamKind)
    {
        case (Stream_General) :
            Fill_HowTo("Format", "R");
            break;
        case (Stream_Video) :
            Fill_HowTo("Codec", "R");
            Fill_HowTo("BitRate", "R|Overall BitRate - Audio BitRates");
            Fill_HowTo("Width", "R");
            Fill_HowTo("Height", "R");
            Fill_HowTo("DisplayAspectRatio", "R");
            break;
        case (Stream_Audio) :
            break;
        case (Stream_Text) :
            break;
        case (Stream_Chapters) :
            break;
        case (Stream_Image) :
            break;
        case (Stream_Menu) :
            break;
        case (Stream_Max) :
            break;
    }
}

} //NameSpace

#endif //MEDIAINFO_CDXA_YES

<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2008 Nokia Corporation
 *
 * 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
 */

#include <TelepathyQt4/Client/AccountManager>
#include "TelepathyQt4/Client/account-manager-internal.h"

#include "TelepathyQt4/Client/_gen/account-manager.moc.hpp"
#include "TelepathyQt4/Client/_gen/account-manager-internal.moc.hpp"
#include "TelepathyQt4/_gen/cli-account-manager.moc.hpp"
#include "TelepathyQt4/_gen/cli-account-manager-body.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Client/PendingSuccess>
#include <TelepathyQt4/Constants>

#include <QQueue>
#include <QSet>
#include <QTimer>

/**
 * \addtogroup clientsideproxies Client-side proxies
 *
 * Proxy objects representing remote service objects accessed via D-Bus.
 *
 * In addition to providing direct access to methods, signals and properties
 * exported by the remote objects, some of these proxies offer features like
 * automatic inspection of remote object capabilities, property tracking,
 * backwards compatibility helpers for older services and other utilities.
 */

/**
 * \defgroup clientaccount Account and Account Manager proxies
 * \ingroup clientsideproxies
 *
 * Proxy objects representing the Telepathy Account Manager and the Accounts
 * that it manages, and their optional interfaces.
 */

namespace Telepathy
{
namespace Client
{

AccountManager::Private::PendingReady::PendingReady(AccountManager *parent)
    : PendingOperation(parent)
{
}

AccountManager::Private::Private(AccountManager *parent)
    : QObject(parent),
      baseInterface(new AccountManagerInterface(parent->dbusConnection(),
                            parent->busName(), parent->objectPath(), parent)),
      ready(false),
      pendingReady(0),
      introspectQueue(),
      features(0)
{
    debug() << "Creating new AccountManager:" << parent->busName();

    connect(baseInterface,
            SIGNAL(AccountValidityChanged(const QDBusObjectPath &, bool)),
            SLOT(onAccountValidityChanged(const QDBusObjectPath &, bool)));
    connect(baseInterface,
            SIGNAL(AccountRemoved(const QDBusObjectPath &)),
            SLOT(onAccountRemoved(const QDBusObjectPath &)));

    introspectQueue.enqueue(&Private::callGetAll);
    QTimer::singleShot(0, this, SLOT(continueIntrospection()));
}

AccountManager::Private::~Private()
{
}

void AccountManager::Private::callGetAll()
{
    debug() << "Calling Properties::GetAll(AccountManager)";
    AccountManager *am = static_cast<AccountManager *>(parent());
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
            am->propertiesInterface()->GetAll(
                TELEPATHY_INTERFACE_ACCOUNT_MANAGER), this);
    connect(watcher,
            SIGNAL(finished(QDBusPendingCallWatcher *)),
            SLOT(onGetAllAccountManagerReturn(QDBusPendingCallWatcher *)));
}

void AccountManager::Private::setAccountPaths(QSet<QDBusObjectPath> &set,
        const QVariant &variant)
{
    Telepathy::ObjectPathList paths = qdbus_cast<Telepathy::ObjectPathList>(variant);

    if (paths.size() == 0) {
        // maybe the AccountManager is buggy, like Mission Control
        // 5.0.beta45, and returns an array of strings rather than
        // an array of object paths?

        QStringList wronglyTypedPaths = qdbus_cast<QStringList>(variant);
        if (wronglyTypedPaths.size() > 0) {
            warning() << "AccountManager returned wrong type "
                "(expected 'ao', got 'as'); working around it";
            Q_FOREACH (QString path, wronglyTypedPaths) {
                paths << QDBusObjectPath(path);
            }
        }
    }

    Q_FOREACH (const QDBusObjectPath &path, paths) {
        set << path;
    }
}

void AccountManager::Private::onGetAllAccountManagerReturn(
        QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QVariantMap> reply = *watcher;
    QVariantMap props;

    if (!reply.isError()) {
        debug() << "Got reply to Properties.GetAll(AccountManager)";
        props = reply.value();
    } else {
        warning().nospace() <<
            "GetAll(AccountManager) failed: " <<
            reply.error().name() << ": " << reply.error().message();
    }

    if (props.contains("Interfaces")) {
        interfaces = qdbus_cast<QStringList>(props["Interfaces"]);
    }

    if (props.contains("ValidAccounts")) {
        setAccountPaths(validAccountPaths,
                props["ValidAccounts"]);
    }

    if (props.contains("InvalidAccounts")) {
        setAccountPaths(invalidAccountPaths,
                props["InvalidAccounts"]);
    }

    continueIntrospection();
}

void AccountManager::Private::onAccountValidityChanged(const QDBusObjectPath &path,
        bool nowValid)
{
    bool newAccount = false;

    if (!validAccountPaths.contains(path) && !invalidAccountPaths.contains(path)) {
        newAccount = true;
    }

    if (nowValid) {
        debug() << "Account created or became valid:" << path.path();
        invalidAccountPaths.remove(path);
        validAccountPaths.insert(path);
    }
    else {
        debug() << "Account became invalid:" << path.path();
        validAccountPaths.remove(path);
        invalidAccountPaths.insert(path);
    }

    if (newAccount) {
        Q_EMIT accountCreated(path);
        // if the newly created account is invalid (shouldn't be the case)
        // emit also accountValidityChanged indicating this
        if (!nowValid) {
            Q_EMIT accountValidityChanged(path, nowValid);
        }
    }
    else {
        Q_EMIT accountValidityChanged(path, nowValid);
    }
}

void AccountManager::Private::onAccountRemoved(const QDBusObjectPath &path)
{
    debug() << "Account removed:" << path.path();
    validAccountPaths.remove(path);
    invalidAccountPaths.remove(path);

    Q_EMIT accountRemoved(path);
}

void AccountManager::Private::continueIntrospection()
{
    if (!ready) {
        if (introspectQueue.isEmpty()) {
            debug() << "AccountManager is ready";
            ready = true;

            if (pendingReady) {
                pendingReady->setFinished();
                // it will delete itself later
                pendingReady = 0;
            }
        }
        else {
            (this->*(introspectQueue.dequeue()))();
        }
    }
}

/**
 * \class AccountManager
 * \ingroup clientaccount
 * \headerfile TelepathyQt4/Client/account-manager.h> <TelepathyQt4/Client/AccountManager>
 *
 * Object representing a Telepathy account manager.
 *
 * \param parent Object parent.
 */
AccountManager::AccountManager(QObject* parent)
    : StatelessDBusProxy(QDBusConnection::sessionBus(),
            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_BUS_NAME),
            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_OBJECT_PATH), parent),
      mPriv(new Private(this))
{
    init();
}

/**
 * \class AccountManager
 * \ingroup clientaccount
 * \headerfile TelepathyQt4/Client/account-manager.h> <TelepathyQt4/Client/AccountManager>
 *
 * Object representing a Telepathy account manager.
 *
 * \param bus QDBusConnection to use.
 * \param parent Object parent.
 */
AccountManager::AccountManager(const QDBusConnection& bus,
        QObject* parent)
    : StatelessDBusProxy(bus,
            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_BUS_NAME),
            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_OBJECT_PATH), parent),
      mPriv(new Private(this))
{
    init();
}

/**
 * Class destructor.
 */
AccountManager::~AccountManager()
{
    delete mPriv;
}

QStringList AccountManager::interfaces() const
{
    return mPriv->interfaces;
}

/**
 * \fn DBus::propertiesInterface *AccountManager::propertiesInterface() const
 *
 * Convenience function for getting a Properties interface proxy. The
 * AccountManager interface relies on properties, so this interface is
 * always assumed to be present.
 */

/**
 * Return a list of QDBusObjectPath for all valid accounts.
 *
 * \return A list of QDBusObjectPath.
 */
Telepathy::ObjectPathList AccountManager::validAccountPaths() const
{
    Telepathy::ObjectPathList result;
    result.append(mPriv->validAccountPaths.values());
    return result;
}

/**
 * Return a list of QDBusObjectPath for all invalid accounts.
 *
 * \return A list of QDBusObjectPath.
 */
Telepathy::ObjectPathList AccountManager::invalidAccountPaths() const
{
    Telepathy::ObjectPathList result;
    result.append(mPriv->invalidAccountPaths.values());
    return result;
}

/**
 * Return a list of QDBusObjectPath for all accounts.
 *
 * \return A list of QDBusObjectPath.
 */
Telepathy::ObjectPathList AccountManager::allAccountPaths() const
{
    ObjectPathList result;
    result.append(mPriv->validAccountPaths.values());
    result.append(mPriv->invalidAccountPaths.values());
    return result;
}

#if 0
/**
 * Return a list of pending operations for all valid accounts from which
 * Accounts can be retrieved if it succeeds.
 *
 * Note that the account objects won't be cached by account manager, and
 * should be done by the application itself.
 *
 * \return A list of PendingAccount which each one will emit
 *         PendingAccount::finished when it has finished or failed creating the
 *         account object.
 */
PendingAccounts *AccountManager::validAccounts() const
{
    return 0;
}

/**
 * Return a list of pending operations for all invalid accounts from which
 * Accounts can be retrieved if it succeeds.
 *
 * Note that the account objects won't be cached by account manager, and
 * should be done by the application itself.
 *
 * \return A list of PendingAccount which each one will emit
 *         PendingAccount::finished when it has finished or failed creating the
 *         account object.
 */
PendingAccounts *AccountManager::invalidAccounts() const
{
    return 0;
}

/**
 * Return a list of pending operations for all accounts from which
 * Accounts can be retrieved if it succeeds.
 *
 * Note that the account objects won't be cached by account manager, and
 * should be done by the application itself.
 *
 * \return A list of PendingAccount which each one will emit
 *         PendingAccount::finished when it has finished or failed creating the
 *         account object.
 */
PendingAccounts *AccountManager::allAccounts() const
{
    return 0;
}

PendingAccount *AccountManager::accountForPath(const QString &path) const
{
    return 0;
}

/**
 * Create an account with the given parameters.
 *
 * Return a pending operation representing the account which will succeed
 * when the account has been created or fail if an error occurred.
 *
 * \param connectionManager Name of the connection manager to create the account for.
 * \param protocol Name of the protocol to create the account for.
 * \param displayName Account display name.
 * \param parameters Account parameters.
 * \return A PendingOperation which will emit PendingAccount::finished
 *         when the account has been created of failed its creation process.
 */
PendingAccount *AccountManager::createAccount(const QString &connectionManager,
        const QString &protocol, const QString &displayName,
        const QVariantMap &parameters)
{
    return 0;
}
#endif

/**
 * Return whether this object has finished its initial setup.
 *
 * This is mostly useful as a sanity check, in code that shouldn't be run
 * until the object is ready. To wait for the object to be ready, call
 * becomeReady() and connect to the finished signal on the result.
 *
 * \param features Which features should be tested.
 * \return \c true if the object has finished initial setup.
 */
bool AccountManager::isReady(Features features) const
{
    return mPriv->ready
        && ((mPriv->features & features) == features);
}

/**
 * Return a pending operation which will succeed when this object finishes
 * its initial setup, or will fail if a fatal error occurs during this
 * initial setup.
 *
 * \param features Which features should be tested.
 * \return A PendingOperation which will emit PendingOperation::finished
 *         when this object has finished or failed its initial setup.
 */
PendingOperation *AccountManager::becomeReady(Features features)
{
    if (isReady(features)) {
        return new PendingSuccess(this);
    }

    if (features != 0) {
        return new PendingFailure(this, "org.freedesktop.Telepathy.Qt.DoesntWork",
                "Unimplemented");
    }

    if (!mPriv->pendingReady) {
        mPriv->pendingReady = new Private::PendingReady(this);
    }
    return mPriv->pendingReady;
}

/**
 * Get the AccountManagerInterface for this AccountManager. This
 * method is protected since the convenience methods provided by this
 * class should generally be used instead of calling D-Bus methods
 * directly.
 *
 * \return A pointer to the existing AccountManagerInterface for this
 *         AccountManager.
 */
AccountManagerInterface *AccountManager::baseInterface() const
{
    return mPriv->baseInterface;
}

void AccountManager::init()
{
    connect(mPriv,
            SIGNAL(accountCreated(const QDBusObjectPath &)),
            SIGNAL(accountCreated(const QDBusObjectPath &)));
    connect(mPriv,
            SIGNAL(accountRemoved(const QDBusObjectPath &)),
            SIGNAL(accountRemoved(const QDBusObjectPath &)));
    connect(mPriv,
            SIGNAL(accountValidityChanged(const QDBusObjectPath &, bool)),
            SIGNAL(accountValidityChanged(const QDBusObjectPath &, bool)));
}

} // Telepathy::Client
} // Telepathy
<commit_msg>Updated AccountManager documentation.<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2008 Nokia Corporation
 *
 * 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
 */

#include <TelepathyQt4/Client/AccountManager>
#include "TelepathyQt4/Client/account-manager-internal.h"

#include "TelepathyQt4/Client/_gen/account-manager.moc.hpp"
#include "TelepathyQt4/Client/_gen/account-manager-internal.moc.hpp"
#include "TelepathyQt4/_gen/cli-account-manager.moc.hpp"
#include "TelepathyQt4/_gen/cli-account-manager-body.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Client/PendingSuccess>
#include <TelepathyQt4/Constants>

#include <QQueue>
#include <QSet>
#include <QTimer>

/**
 * \addtogroup clientsideproxies Client-side proxies
 *
 * Proxy objects representing remote service objects accessed via D-Bus.
 *
 * In addition to providing direct access to methods, signals and properties
 * exported by the remote objects, some of these proxies offer features like
 * automatic inspection of remote object capabilities, property tracking,
 * backwards compatibility helpers for older services and other utilities.
 */

/**
 * \defgroup clientaccount Account and Account Manager proxies
 * \ingroup clientsideproxies
 *
 * Proxy objects representing the Telepathy Account Manager and the Accounts
 * that it manages, and their optional interfaces.
 */

namespace Telepathy
{
namespace Client
{

AccountManager::Private::PendingReady::PendingReady(AccountManager *parent)
    : PendingOperation(parent)
{
}

AccountManager::Private::Private(AccountManager *parent)
    : QObject(parent),
      baseInterface(new AccountManagerInterface(parent->dbusConnection(),
                            parent->busName(), parent->objectPath(), parent)),
      ready(false),
      pendingReady(0),
      introspectQueue(),
      features(0)
{
    debug() << "Creating new AccountManager:" << parent->busName();

    connect(baseInterface,
            SIGNAL(AccountValidityChanged(const QDBusObjectPath &, bool)),
            SLOT(onAccountValidityChanged(const QDBusObjectPath &, bool)));
    connect(baseInterface,
            SIGNAL(AccountRemoved(const QDBusObjectPath &)),
            SLOT(onAccountRemoved(const QDBusObjectPath &)));

    introspectQueue.enqueue(&Private::callGetAll);
    QTimer::singleShot(0, this, SLOT(continueIntrospection()));
}

AccountManager::Private::~Private()
{
}

void AccountManager::Private::callGetAll()
{
    debug() << "Calling Properties::GetAll(AccountManager)";
    AccountManager *am = static_cast<AccountManager *>(parent());
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
            am->propertiesInterface()->GetAll(
                TELEPATHY_INTERFACE_ACCOUNT_MANAGER), this);
    connect(watcher,
            SIGNAL(finished(QDBusPendingCallWatcher *)),
            SLOT(onGetAllAccountManagerReturn(QDBusPendingCallWatcher *)));
}

void AccountManager::Private::setAccountPaths(QSet<QDBusObjectPath> &set,
        const QVariant &variant)
{
    Telepathy::ObjectPathList paths = qdbus_cast<Telepathy::ObjectPathList>(variant);

    if (paths.size() == 0) {
        // maybe the AccountManager is buggy, like Mission Control
        // 5.0.beta45, and returns an array of strings rather than
        // an array of object paths?

        QStringList wronglyTypedPaths = qdbus_cast<QStringList>(variant);
        if (wronglyTypedPaths.size() > 0) {
            warning() << "AccountManager returned wrong type "
                "(expected 'ao', got 'as'); working around it";
            Q_FOREACH (QString path, wronglyTypedPaths) {
                paths << QDBusObjectPath(path);
            }
        }
    }

    Q_FOREACH (const QDBusObjectPath &path, paths) {
        set << path;
    }
}

void AccountManager::Private::onGetAllAccountManagerReturn(
        QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QVariantMap> reply = *watcher;
    QVariantMap props;

    if (!reply.isError()) {
        debug() << "Got reply to Properties.GetAll(AccountManager)";
        props = reply.value();
    } else {
        warning().nospace() <<
            "GetAll(AccountManager) failed: " <<
            reply.error().name() << ": " << reply.error().message();
    }

    if (props.contains("Interfaces")) {
        interfaces = qdbus_cast<QStringList>(props["Interfaces"]);
    }

    if (props.contains("ValidAccounts")) {
        setAccountPaths(validAccountPaths,
                props["ValidAccounts"]);
    }

    if (props.contains("InvalidAccounts")) {
        setAccountPaths(invalidAccountPaths,
                props["InvalidAccounts"]);
    }

    continueIntrospection();
}

void AccountManager::Private::onAccountValidityChanged(const QDBusObjectPath &path,
        bool nowValid)
{
    bool newAccount = false;

    if (!validAccountPaths.contains(path) && !invalidAccountPaths.contains(path)) {
        newAccount = true;
    }

    if (nowValid) {
        debug() << "Account created or became valid:" << path.path();
        invalidAccountPaths.remove(path);
        validAccountPaths.insert(path);
    }
    else {
        debug() << "Account became invalid:" << path.path();
        validAccountPaths.remove(path);
        invalidAccountPaths.insert(path);
    }

    if (newAccount) {
        Q_EMIT accountCreated(path);
        // if the newly created account is invalid (shouldn't be the case)
        // emit also accountValidityChanged indicating this
        if (!nowValid) {
            Q_EMIT accountValidityChanged(path, nowValid);
        }
    }
    else {
        Q_EMIT accountValidityChanged(path, nowValid);
    }
}

void AccountManager::Private::onAccountRemoved(const QDBusObjectPath &path)
{
    debug() << "Account removed:" << path.path();
    validAccountPaths.remove(path);
    invalidAccountPaths.remove(path);

    Q_EMIT accountRemoved(path);
}

void AccountManager::Private::continueIntrospection()
{
    if (!ready) {
        if (introspectQueue.isEmpty()) {
            debug() << "AccountManager is ready";
            ready = true;

            if (pendingReady) {
                pendingReady->setFinished();
                // it will delete itself later
                pendingReady = 0;
            }
        }
        else {
            (this->*(introspectQueue.dequeue()))();
        }
    }
}

/**
 * \class AccountManager
 * \ingroup clientaccount
 * \headerfile TelepathyQt4/Client/account-manager.h> <TelepathyQt4/Client/AccountManager>
 *
 * Object representing a Telepathy account manager.
 */

/**
 * Construct a new AccountManager object.
 *
 * \param parent Object parent.
 */
AccountManager::AccountManager(QObject* parent)
    : StatelessDBusProxy(QDBusConnection::sessionBus(),
            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_BUS_NAME),
            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_OBJECT_PATH), parent),
      mPriv(new Private(this))
{
    init();
}

/**
 * Construct a new AccountManager object.
 *
 * \param bus QDBusConnection to use.
 * \param parent Object parent.
 */
AccountManager::AccountManager(const QDBusConnection& bus,
        QObject* parent)
    : StatelessDBusProxy(bus,
            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_BUS_NAME),
            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_OBJECT_PATH), parent),
      mPriv(new Private(this))
{
    init();
}

/**
 * Class destructor.
 */
AccountManager::~AccountManager()
{
    delete mPriv;
}

QStringList AccountManager::interfaces() const
{
    return mPriv->interfaces;
}

/**
 * \fn DBus::propertiesInterface *AccountManager::propertiesInterface() const
 *
 * Convenience function for getting a Properties interface proxy. The
 * AccountManager interface relies on properties, so this interface is
 * always assumed to be present.
 */

/**
 * Return a list of QDBusObjectPath for all valid accounts.
 *
 * \return A list of QDBusObjectPath.
 */
Telepathy::ObjectPathList AccountManager::validAccountPaths() const
{
    Telepathy::ObjectPathList result;
    result.append(mPriv->validAccountPaths.values());
    return result;
}

/**
 * Return a list of QDBusObjectPath for all invalid accounts.
 *
 * \return A list of QDBusObjectPath.
 */
Telepathy::ObjectPathList AccountManager::invalidAccountPaths() const
{
    Telepathy::ObjectPathList result;
    result.append(mPriv->invalidAccountPaths.values());
    return result;
}

/**
 * Return a list of QDBusObjectPath for all accounts.
 *
 * \return A list of QDBusObjectPath.
 */
Telepathy::ObjectPathList AccountManager::allAccountPaths() const
{
    ObjectPathList result;
    result.append(mPriv->validAccountPaths.values());
    result.append(mPriv->invalidAccountPaths.values());
    return result;
}

#if 0
/**
 * Return a list of pending operations for all valid accounts from which
 * Accounts can be retrieved if it succeeds.
 *
 * Note that the account objects won't be cached by account manager, and
 * should be done by the application itself.
 *
 * \return A list of PendingAccount which each one will emit
 *         PendingAccount::finished when it has finished or failed creating the
 *         account object.
 */
PendingAccounts *AccountManager::validAccounts() const
{
    return 0;
}

/**
 * Return a list of pending operations for all invalid accounts from which
 * Accounts can be retrieved if it succeeds.
 *
 * Note that the account objects won't be cached by account manager, and
 * should be done by the application itself.
 *
 * \return A list of PendingAccount which each one will emit
 *         PendingAccount::finished when it has finished or failed creating the
 *         account object.
 */
PendingAccounts *AccountManager::invalidAccounts() const
{
    return 0;
}

/**
 * Return a list of pending operations for all accounts from which
 * Accounts can be retrieved if it succeeds.
 *
 * Note that the account objects won't be cached by account manager, and
 * should be done by the application itself.
 *
 * \return A list of PendingAccount which each one will emit
 *         PendingAccount::finished when it has finished or failed creating the
 *         account object.
 */
PendingAccounts *AccountManager::allAccounts() const
{
    return 0;
}

PendingAccount *AccountManager::accountForPath(const QString &path) const
{
    return 0;
}

/**
 * Create an account with the given parameters.
 *
 * Return a pending operation representing the account which will succeed
 * when the account has been created or fail if an error occurred.
 *
 * \param connectionManager Name of the connection manager to create the account for.
 * \param protocol Name of the protocol to create the account for.
 * \param displayName Account display name.
 * \param parameters Account parameters.
 * \return A PendingOperation which will emit PendingAccount::finished
 *         when the account has been created of failed its creation process.
 */
PendingAccount *AccountManager::createAccount(const QString &connectionManager,
        const QString &protocol, const QString &displayName,
        const QVariantMap &parameters)
{
    return 0;
}
#endif

/**
 * Return whether this object has finished its initial setup.
 *
 * This is mostly useful as a sanity check, in code that shouldn't be run
 * until the object is ready. To wait for the object to be ready, call
 * becomeReady() and connect to the finished signal on the result.
 *
 * \param features Which features should be tested.
 * \return \c true if the object has finished initial setup.
 */
bool AccountManager::isReady(Features features) const
{
    return mPriv->ready
        && ((mPriv->features & features) == features);
}

/**
 * Return a pending operation which will succeed when this object finishes
 * its initial setup, or will fail if a fatal error occurs during this
 * initial setup.
 *
 * \param features Which features should be tested.
 * \return A PendingOperation which will emit PendingOperation::finished
 *         when this object has finished or failed its initial setup.
 */
PendingOperation *AccountManager::becomeReady(Features features)
{
    if (isReady(features)) {
        return new PendingSuccess(this);
    }

    if (features != 0) {
        return new PendingFailure(this, "org.freedesktop.Telepathy.Qt.DoesntWork",
                "Unimplemented");
    }

    if (!mPriv->pendingReady) {
        mPriv->pendingReady = new Private::PendingReady(this);
    }
    return mPriv->pendingReady;
}

/**
 * Get the AccountManagerInterface for this AccountManager. This
 * method is protected since the convenience methods provided by this
 * class should generally be used instead of calling D-Bus methods
 * directly.
 *
 * \return A pointer to the existing AccountManagerInterface for this
 *         AccountManager.
 */
AccountManagerInterface *AccountManager::baseInterface() const
{
    return mPriv->baseInterface;
}

void AccountManager::init()
{
    connect(mPriv,
            SIGNAL(accountCreated(const QDBusObjectPath &)),
            SIGNAL(accountCreated(const QDBusObjectPath &)));
    connect(mPriv,
            SIGNAL(accountRemoved(const QDBusObjectPath &)),
            SIGNAL(accountRemoved(const QDBusObjectPath &)));
    connect(mPriv,
            SIGNAL(accountValidityChanged(const QDBusObjectPath &, bool)),
            SIGNAL(accountValidityChanged(const QDBusObjectPath &, bool)));
}

} // Telepathy::Client
} // Telepathy
<|endoftext|>


<commit_before>//
// Name:		SceneGraphDlg.cpp
//
// Copyright (c) 2001-2004 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#ifdef __GNUG__
	#pragma implementation "SceneGraphDlg.cpp"
#endif

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "wx/treectrl.h"
#include "wx/image.h"

#include "vtlib/vtlib.h"
#include "vtlib/core/Engine.h"
#include "vtui/wxString2.h"
#include "SceneGraphDlg.h"

#include <typeinfo>
using namespace std;

#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__)
#  include "icon1.xpm"
#  include "icon2.xpm"
#  include "icon3.xpm"
#  include "icon4.xpm"
#  include "icon5.xpm"
#  include "icon6.xpm"
#  include "icon7.xpm"
#  include "icon8.xpm"
#  include "icon9.xpm"
#  include "icon10.xpm"
#endif

/////////////////////////////

class MyTreeItemData : public wxTreeItemData
{
public:
	MyTreeItemData(vtNodeBase *pNode, vtEngine *pEngine)
	{
		m_pNode = pNode;
		m_pEngine = pEngine;
	}
	vtNodeBase *m_pNode;
	vtEngine *m_pEngine;
};

// WDR: class implementations

//----------------------------------------------------------------------------
// SceneGraphDlg
//----------------------------------------------------------------------------

// WDR: event table for SceneGraphDlg

BEGIN_EVENT_TABLE(SceneGraphDlg,wxDialog)
	EVT_INIT_DIALOG (SceneGraphDlg::OnInitDialog)
	EVT_TREE_SEL_CHANGED( ID_SCENETREE, SceneGraphDlg::OnTreeSelChanged )
	EVT_CHECKBOX( ID_ENABLED, SceneGraphDlg::OnEnabled )
	EVT_BUTTON( ID_ZOOMTO, SceneGraphDlg::OnZoomTo )
	EVT_BUTTON( ID_REFRESH, SceneGraphDlg::OnRefresh )
END_EVENT_TABLE()

SceneGraphDlg::SceneGraphDlg( wxWindow *parent, wxWindowID id, const wxString &title,
	const wxPoint &position, const wxSize& size, long style ) :
	wxDialog( parent, id, title, position, size, style )
{
	SceneGraphFunc( this, TRUE );

	m_pZoomTo = GetZoomto();
	m_pEnabled = GetEnabled();
	m_pTree = GetScenetree();

	m_pZoomTo->Enable(false);

	m_imageListNormal = NULL;
	CreateImageList(16);
}

SceneGraphDlg::~SceneGraphDlg()
{
	delete m_imageListNormal;
}

///////////

void SceneGraphDlg::CreateImageList(int size)
{
	delete m_imageListNormal;

	if ( size == -1 )
	{
		m_imageListNormal = NULL;
		return;
	}
	// Make an image list containing small icons
	m_imageListNormal = new wxImageList(size, size, TRUE);

	wxIcon icons[10];
	icons[0] = wxICON(icon1);
	icons[1] = wxICON(icon2);
	icons[2] = wxICON(icon3);
	icons[3] = wxICON(icon4);
	icons[4] = wxICON(icon5);
	icons[5] = wxICON(icon6);
	icons[6] = wxICON(icon7);
	icons[7] = wxICON(icon8);
	icons[8] = wxICON(icon9);
	icons[9] = wxICON(icon10);

	int sizeOrig = icons[0].GetWidth();
	for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
	{
		if ( size == sizeOrig )
			m_imageListNormal->Add(icons[i]);
		else
			m_imageListNormal->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
	}
	m_pTree->SetImageList(m_imageListNormal);
}

void SceneGraphDlg::RefreshTreeContents()
{
	vtScene* scene = vtGetScene();
	if (!scene)
		return;

	// start with a blank slate
	m_pTree->DeleteAllItems();

	// Fill in the tree with nodes
	m_bFirst = true;
	vtNode *pRoot = scene->GetRoot();
	if (pRoot) AddNodeItemsRecursively(wxTreeItemId(), pRoot, 0);

	wxTreeItemId hRoot = m_pTree->GetRootItem();
	wxTreeItemId hEngRoot = m_pTree->AppendItem(hRoot, _("Engines"), 7, 7);

	vtEngine *pEngine = scene->GetRootEngine();
	if (pEngine) AddEnginesRecursively(hEngRoot, pEngine, 0);
	m_pTree->Expand(hEngRoot);

/*	// Fill in the tree with engines
	int num = scene->GetNumEngines();
	vtTarget *target;
	for (int i = 0; i < num; i++)
	{
		vtEngine *pEng = scene->GetEngine(i);
		wxString2 str = pEng->GetName2();
		int targets = pEng->NumTargets();
		target = pEng->GetTarget();
		if (target)
		{
			str += _T(" -> ");
			vtNodeBase *node = dynamic_cast<vtNodeBase*>(target);
			if (node)
			{
				str += _T("\"");
				str += wxString::FromAscii(node->GetName2());
				str += _T("\"");
			}
			else
				str += _("(non-node)");
		}
		if (targets > 1)
		{
			wxString2 plus;
			plus.Printf(_(" (%d targets total)"), targets);
			str += plus;
		}
		wxTreeItemId hEng = m_pTree->AppendItem(hEngRoot, str, 1, 1);
		m_pTree->SetItemData(hEng, new MyTreeItemData(NULL, pEng));
	}
	m_pTree->Expand(hEngRoot);
*/
	m_pSelectedEngine = NULL;
	m_pSelectedNode = NULL;
}

void SceneGraphDlg::AddNodeItemsRecursively(wxTreeItemId hParentItem,
										vtNodeBase *pNode, int depth)
{
	wxString str;
	int nImage;
	wxTreeItemId hNewItem;

	if (!pNode) return;

	if (dynamic_cast<vtLight*>(pNode))
	{
		str = _("Light");
		nImage = 4;
	}
	else if (dynamic_cast<vtGeom*>(pNode))
	{
		str = _("Geometry");
		nImage = 2;
	}
	else if (dynamic_cast<vtLOD*>(pNode))
	{
		str = _T("LOD");
		nImage = 5;
	}
	else if (dynamic_cast<vtTransform*>(pNode))
	{
		str = _T("XForm");
		nImage = 9;
	}
	else if (dynamic_cast<vtGroupBase*>(pNode))
	{
		// must be just a group for grouping's sake
		str = _("Group");
		nImage = 3;
	}
	else
	{
		// must be something else
		str = _("Other");
		nImage = 8;
	}
	if (pNode->GetName2())
	{
		str += _T(" \"");
		str += wxString::FromAscii(pNode->GetName2());
		str += _T("\"");
	}

	if (m_bFirst)
	{
		hNewItem = m_pTree->AddRoot(str);
		m_bFirst = false;
	}
	else
		hNewItem = m_pTree->AppendItem(hParentItem, str, nImage, nImage);

	const std::type_info &t1 = typeid(*pNode);
	if (t1 == typeid(vtGeom))
	{
		vtGeom *pGeom = dynamic_cast<vtGeom*>(pNode);
		int num_mesh = pGeom->GetNumMeshes();
		wxTreeItemId	hGeomItem;

		for (int i = 0; i < num_mesh; i++)
		{
			vtMesh *pMesh = pGeom->GetMesh(i);
			if (pMesh)
			{
				int iNumPrim = pMesh->GetNumPrims();
				int iNumVert = pMesh->GetNumVertices();

				GLenum pt = pMesh->GetPrimType();
				const char *mtype="";
				switch (pt)
				{
				case GL_POINTS: mtype = "Points"; break;
				case GL_LINES: mtype = "Lines"; break;
				case GL_LINE_LOOP: mtype = "LineLoop"; break;
				case GL_LINE_STRIP: mtype = "LineStrip"; break;
				case GL_TRIANGLES: mtype = "Triangles"; break;
				case GL_TRIANGLE_STRIP: mtype = "TriStrip"; break;
				case GL_TRIANGLE_FAN: mtype = "TriFan"; break;
				case GL_QUADS: mtype = "Quads"; break;
				case GL_QUAD_STRIP: mtype = "QuadStrip"; break;
				case GL_POLYGON: mtype = "Polygon"; break;
				}
				str.Printf(_("Mesh %d, %hs, %d verts, %d prims"), i, mtype, iNumVert, iNumPrim);
				hGeomItem = m_pTree->AppendItem(hNewItem, str, 6, 6);
			}
			else
				hGeomItem = m_pTree->AppendItem(hNewItem, _("Text Mesh"), 6, 6);
		}
	}

	m_pTree->SetItemData(hNewItem, new MyTreeItemData(pNode, NULL));

	wxTreeItemId hSubItem;
	vtGroupBase *pGroup = dynamic_cast<vtGroupBase*>(pNode);
	if (pGroup)
	{
		int num_children = pGroup->GetNumChildren();
		if (num_children > 200)
		{
			str.Printf(_("(%d children)"), num_children);
			hSubItem = m_pTree->AppendItem(hNewItem, str, 8, 8);
		}
		else
		{
			for (int i = 0; i < num_children; i++)
			{
				vtNode *pChild = pGroup->GetChild(i);
				if (pChild)
					AddNodeItemsRecursively(hNewItem, pChild, depth+1);
				else
					hSubItem = m_pTree->AppendItem(hNewItem, _("(internal node)"), 8, 8);
			}
		}
	}
	// expand a bit so that the tree is initially partially exposed
	if (depth < 2)
		m_pTree->Expand(hNewItem);
}

void SceneGraphDlg::AddEnginesRecursively(wxTreeItemId hParentItem,
										vtEngine *pEng, int depth)
{
	wxTreeItemId hNewItem;

	if (!pEng) return;

	wxString2 str = pEng->GetName2();
	if (str == "")
		str = "unnamed";

	int targets = pEng->NumTargets();
	vtTarget *target = pEng->GetTarget();
	if (target)
	{
		str += _T(" -> ");
		vtNodeBase *node = dynamic_cast<vtNodeBase*>(target);
		if (node)
		{
			str += _T("\"");
			str += wxString::FromAscii(node->GetName2());
			str += _T("\"");
		}
		else
			str += _("(non-node)");
	}
	if (targets > 1)
	{
		wxString2 plus;
		plus.Printf(_(" (%d targets total)"), targets);
		str += plus;
	}

	hNewItem = m_pTree->AppendItem(hParentItem, str, 1, 1);
	m_pTree->SetItemData(hNewItem, new MyTreeItemData(NULL, pEng));

	for (unsigned int i = 0; i < pEng->NumChildren(); i++)
	{
		vtEngine *pChild = pEng->GetChild(i);
		AddEnginesRecursively(hNewItem, pChild, depth+1);
	}

	// always expand engines
	m_pTree->Expand(hNewItem);
}

// WDR: handler implementations for SceneGraphDlg

void SceneGraphDlg::OnRefresh( wxCommandEvent &event )
{
	RefreshTreeContents();
}

void SceneGraphDlg::OnZoomTo( wxCommandEvent &event )
{
	if (m_pSelectedNode)
	{
		FSphere sph;
		m_pSelectedNode->GetBoundSphere(sph, true);	// global bounds

		// a bit back to make sure whole volume of bounding sphere is in view
		vtCamera *pCam = vtGetScene()->GetCamera();
		float smallest = min(pCam->GetFOV(), pCam->GetVertFOV());
		float alpha = smallest / 2.0f;
		float distance = sph.radius / tanf(alpha);
		sph.radius = distance;

		pCam->ZoomToSphere(sph);
	}
}

void SceneGraphDlg::OnEnabled( wxCommandEvent &event )
{
	if (m_pSelectedEngine)
		m_pSelectedEngine->SetEnabled(m_pEnabled->GetValue());
	if (m_pSelectedNode)
		m_pSelectedNode->SetEnabled(m_pEnabled->GetValue());
}

void SceneGraphDlg::OnTreeSelChanged( wxTreeEvent &event )
{
	wxTreeItemId item = event.GetItem();
	MyTreeItemData *data = (MyTreeItemData *)m_pTree->GetItemData(item);

	m_pEnabled->Enable(data != NULL);

	m_pSelectedEngine = NULL;
	m_pSelectedNode = NULL;

	if (data && data->m_pEngine)
	{
		m_pSelectedEngine = data->m_pEngine;
		m_pEnabled->SetValue(m_pSelectedEngine->GetEnabled());
	}
	if (data && data->m_pNode)
	{
		m_pSelectedNode = data->m_pNode;
		m_pEnabled->SetValue(m_pSelectedNode->GetEnabled());
		m_pZoomTo->Enable(true);
	}
	else
		m_pZoomTo->Enable(false);
}

void SceneGraphDlg::OnInitDialog(wxInitDialogEvent& event)
{
	RefreshTreeContents();

	wxWindow::OnInitDialog(event);
}

<commit_msg>unicode build fix<commit_after>//
// Name:		SceneGraphDlg.cpp
//
// Copyright (c) 2001-2004 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#ifdef __GNUG__
	#pragma implementation "SceneGraphDlg.cpp"
#endif

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "wx/treectrl.h"
#include "wx/image.h"

#include "vtlib/vtlib.h"
#include "vtlib/core/Engine.h"
#include "vtui/wxString2.h"
#include "SceneGraphDlg.h"

#include <typeinfo>
using namespace std;

#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__)
#  include "icon1.xpm"
#  include "icon2.xpm"
#  include "icon3.xpm"
#  include "icon4.xpm"
#  include "icon5.xpm"
#  include "icon6.xpm"
#  include "icon7.xpm"
#  include "icon8.xpm"
#  include "icon9.xpm"
#  include "icon10.xpm"
#endif

/////////////////////////////

class MyTreeItemData : public wxTreeItemData
{
public:
	MyTreeItemData(vtNodeBase *pNode, vtEngine *pEngine)
	{
		m_pNode = pNode;
		m_pEngine = pEngine;
	}
	vtNodeBase *m_pNode;
	vtEngine *m_pEngine;
};

// WDR: class implementations

//----------------------------------------------------------------------------
// SceneGraphDlg
//----------------------------------------------------------------------------

// WDR: event table for SceneGraphDlg

BEGIN_EVENT_TABLE(SceneGraphDlg,wxDialog)
	EVT_INIT_DIALOG (SceneGraphDlg::OnInitDialog)
	EVT_TREE_SEL_CHANGED( ID_SCENETREE, SceneGraphDlg::OnTreeSelChanged )
	EVT_CHECKBOX( ID_ENABLED, SceneGraphDlg::OnEnabled )
	EVT_BUTTON( ID_ZOOMTO, SceneGraphDlg::OnZoomTo )
	EVT_BUTTON( ID_REFRESH, SceneGraphDlg::OnRefresh )
END_EVENT_TABLE()

SceneGraphDlg::SceneGraphDlg( wxWindow *parent, wxWindowID id, const wxString &title,
	const wxPoint &position, const wxSize& size, long style ) :
	wxDialog( parent, id, title, position, size, style )
{
	SceneGraphFunc( this, TRUE );

	m_pZoomTo = GetZoomto();
	m_pEnabled = GetEnabled();
	m_pTree = GetScenetree();

	m_pZoomTo->Enable(false);

	m_imageListNormal = NULL;
	CreateImageList(16);
}

SceneGraphDlg::~SceneGraphDlg()
{
	delete m_imageListNormal;
}

///////////

void SceneGraphDlg::CreateImageList(int size)
{
	delete m_imageListNormal;

	if ( size == -1 )
	{
		m_imageListNormal = NULL;
		return;
	}
	// Make an image list containing small icons
	m_imageListNormal = new wxImageList(size, size, TRUE);

	wxIcon icons[10];
	icons[0] = wxICON(icon1);
	icons[1] = wxICON(icon2);
	icons[2] = wxICON(icon3);
	icons[3] = wxICON(icon4);
	icons[4] = wxICON(icon5);
	icons[5] = wxICON(icon6);
	icons[6] = wxICON(icon7);
	icons[7] = wxICON(icon8);
	icons[8] = wxICON(icon9);
	icons[9] = wxICON(icon10);

	int sizeOrig = icons[0].GetWidth();
	for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
	{
		if ( size == sizeOrig )
			m_imageListNormal->Add(icons[i]);
		else
			m_imageListNormal->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
	}
	m_pTree->SetImageList(m_imageListNormal);
}

void SceneGraphDlg::RefreshTreeContents()
{
	vtScene* scene = vtGetScene();
	if (!scene)
		return;

	// start with a blank slate
	m_pTree->DeleteAllItems();

	// Fill in the tree with nodes
	m_bFirst = true;
	vtNode *pRoot = scene->GetRoot();
	if (pRoot) AddNodeItemsRecursively(wxTreeItemId(), pRoot, 0);

	wxTreeItemId hRoot = m_pTree->GetRootItem();
	wxTreeItemId hEngRoot = m_pTree->AppendItem(hRoot, _("Engines"), 7, 7);

	vtEngine *pEngine = scene->GetRootEngine();
	if (pEngine) AddEnginesRecursively(hEngRoot, pEngine, 0);
	m_pTree->Expand(hEngRoot);

	m_pSelectedEngine = NULL;
	m_pSelectedNode = NULL;
}

void SceneGraphDlg::AddNodeItemsRecursively(wxTreeItemId hParentItem,
										vtNodeBase *pNode, int depth)
{
	wxString str;
	int nImage;
	wxTreeItemId hNewItem;

	if (!pNode) return;

	if (dynamic_cast<vtLight*>(pNode))
	{
		str = _("Light");
		nImage = 4;
	}
	else if (dynamic_cast<vtGeom*>(pNode))
	{
		str = _("Geometry");
		nImage = 2;
	}
	else if (dynamic_cast<vtLOD*>(pNode))
	{
		str = _T("LOD");
		nImage = 5;
	}
	else if (dynamic_cast<vtTransform*>(pNode))
	{
		str = _T("XForm");
		nImage = 9;
	}
	else if (dynamic_cast<vtGroupBase*>(pNode))
	{
		// must be just a group for grouping's sake
		str = _("Group");
		nImage = 3;
	}
	else
	{
		// must be something else
		str = _("Other");
		nImage = 8;
	}
	if (pNode->GetName2())
	{
		str += _T(" \"");
		str += wxString::FromAscii(pNode->GetName2());
		str += _T("\"");
	}

	if (m_bFirst)
	{
		hNewItem = m_pTree->AddRoot(str);
		m_bFirst = false;
	}
	else
		hNewItem = m_pTree->AppendItem(hParentItem, str, nImage, nImage);

	const std::type_info &t1 = typeid(*pNode);
	if (t1 == typeid(vtGeom))
	{
		vtGeom *pGeom = dynamic_cast<vtGeom*>(pNode);
		int num_mesh = pGeom->GetNumMeshes();
		wxTreeItemId	hGeomItem;

		for (int i = 0; i < num_mesh; i++)
		{
			vtMesh *pMesh = pGeom->GetMesh(i);
			if (pMesh)
			{
				int iNumPrim = pMesh->GetNumPrims();
				int iNumVert = pMesh->GetNumVertices();

				GLenum pt = pMesh->GetPrimType();
				const char *mtype="";
				switch (pt)
				{
				case GL_POINTS: mtype = "Points"; break;
				case GL_LINES: mtype = "Lines"; break;
				case GL_LINE_LOOP: mtype = "LineLoop"; break;
				case GL_LINE_STRIP: mtype = "LineStrip"; break;
				case GL_TRIANGLES: mtype = "Triangles"; break;
				case GL_TRIANGLE_STRIP: mtype = "TriStrip"; break;
				case GL_TRIANGLE_FAN: mtype = "TriFan"; break;
				case GL_QUADS: mtype = "Quads"; break;
				case GL_QUAD_STRIP: mtype = "QuadStrip"; break;
				case GL_POLYGON: mtype = "Polygon"; break;
				}
				str.Printf(_("Mesh %d, %hs, %d verts, %d prims"), i, mtype, iNumVert, iNumPrim);
				hGeomItem = m_pTree->AppendItem(hNewItem, str, 6, 6);
			}
			else
				hGeomItem = m_pTree->AppendItem(hNewItem, _("Text Mesh"), 6, 6);
		}
	}

	m_pTree->SetItemData(hNewItem, new MyTreeItemData(pNode, NULL));

	wxTreeItemId hSubItem;
	vtGroupBase *pGroup = dynamic_cast<vtGroupBase*>(pNode);
	if (pGroup)
	{
		int num_children = pGroup->GetNumChildren();
		if (num_children > 200)
		{
			str.Printf(_("(%d children)"), num_children);
			hSubItem = m_pTree->AppendItem(hNewItem, str, 8, 8);
		}
		else
		{
			for (int i = 0; i < num_children; i++)
			{
				vtNode *pChild = pGroup->GetChild(i);
				if (pChild)
					AddNodeItemsRecursively(hNewItem, pChild, depth+1);
				else
					hSubItem = m_pTree->AppendItem(hNewItem, _("(internal node)"), 8, 8);
			}
		}
	}
	// expand a bit so that the tree is initially partially exposed
	if (depth < 2)
		m_pTree->Expand(hNewItem);
}

void SceneGraphDlg::AddEnginesRecursively(wxTreeItemId hParentItem,
										vtEngine *pEng, int depth)
{
	wxTreeItemId hNewItem;

	if (!pEng) return;

	wxString2 str = pEng->GetName2();
	if (str == wxString2(""))
		str = "unnamed";

	int targets = pEng->NumTargets();
	vtTarget *target = pEng->GetTarget();
	if (target)
	{
		str += _T(" -> ");
		vtNodeBase *node = dynamic_cast<vtNodeBase*>(target);
		if (node)
		{
			str += _T("\"");
			str += wxString::FromAscii(node->GetName2());
			str += _T("\"");
		}
		else
			str += _("(non-node)");
	}
	if (targets > 1)
	{
		wxString2 plus;
		plus.Printf(_(" (%d targets total)"), targets);
		str += plus;
	}

	hNewItem = m_pTree->AppendItem(hParentItem, str, 1, 1);
	m_pTree->SetItemData(hNewItem, new MyTreeItemData(NULL, pEng));

	for (unsigned int i = 0; i < pEng->NumChildren(); i++)
	{
		vtEngine *pChild = pEng->GetChild(i);
		AddEnginesRecursively(hNewItem, pChild, depth+1);
	}

	// always expand engines
	m_pTree->Expand(hNewItem);
}

// WDR: handler implementations for SceneGraphDlg

void SceneGraphDlg::OnRefresh( wxCommandEvent &event )
{
	RefreshTreeContents();
}

void SceneGraphDlg::OnZoomTo( wxCommandEvent &event )
{
	if (m_pSelectedNode)
	{
		FSphere sph;
		m_pSelectedNode->GetBoundSphere(sph, true);	// global bounds

		// a bit back to make sure whole volume of bounding sphere is in view
		vtCamera *pCam = vtGetScene()->GetCamera();
		float smallest = min(pCam->GetFOV(), pCam->GetVertFOV());
		float alpha = smallest / 2.0f;
		float distance = sph.radius / tanf(alpha);
		sph.radius = distance;

		pCam->ZoomToSphere(sph);
	}
}

void SceneGraphDlg::OnEnabled( wxCommandEvent &event )
{
	if (m_pSelectedEngine)
		m_pSelectedEngine->SetEnabled(m_pEnabled->GetValue());
	if (m_pSelectedNode)
		m_pSelectedNode->SetEnabled(m_pEnabled->GetValue());
}

void SceneGraphDlg::OnTreeSelChanged( wxTreeEvent &event )
{
	wxTreeItemId item = event.GetItem();
	MyTreeItemData *data = (MyTreeItemData *)m_pTree->GetItemData(item);

	m_pEnabled->Enable(data != NULL);

	m_pSelectedEngine = NULL;
	m_pSelectedNode = NULL;

	if (data && data->m_pEngine)
	{
		m_pSelectedEngine = data->m_pEngine;
		m_pEnabled->SetValue(m_pSelectedEngine->GetEnabled());
	}
	if (data && data->m_pNode)
	{
		m_pSelectedNode = data->m_pNode;
		m_pEnabled->SetValue(m_pSelectedNode->GetEnabled());
		m_pZoomTo->Enable(true);
	}
	else
		m_pZoomTo->Enable(false);
}

void SceneGraphDlg::OnInitDialog(wxInitDialogEvent& event)
{
	RefreshTreeContents();

	wxWindow::OnInitDialog(event);
}

<|endoftext|>


<commit_before>#include <test/unit/math/test_ad.hpp>
#include <vector>

TEST(mathMixMatFun, generalized_inverse) {
  auto f = [](const auto& x) { return stan::math::generalized_inverse(x); };

  Eigen::MatrixXd t(0, 0);
  stan::test::expect_ad(f, t);
  //  stan::test::expect_ad_matvar(f, t);

  Eigen::MatrixXd u(1, 1);
  u << 2;
  stan::test::expect_ad(f, u);
  //  stan::test::expect_ad_matvar(f, u);
  //
  Eigen::MatrixXd v(2, 3);
  v << 1, 3, 5, 2, 4, 6;
  stan::test::expect_ad(f, v);
  //  stan::test::expect_ad_matvar(f, v);
  v << 1.9, 1.3, 2.5, 0.4, 1.7, 0.1;
  stan::test::expect_ad(f, v);
  //  stan::test::expect_ad_matvar(f, v);

  // issues around zero require looser tolerances for hessians
  stan::test::ad_tolerances tols;
  tols.hessian_hessian_ = 0.1;
  tols.hessian_fvar_hessian_ = 0.1;

  Eigen::MatrixXd w(3, 4);
  w << 2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 27, 29;
  stan::test::expect_ad(tols, f, w);
  //  stan::test::expect_ad_matvar(tols, f, w);

  // even lower tolerance, again for cases around zero
  stan::test::ad_tolerances tols2;
  tols2.hessian_hessian_ = 3.0;
  tols2.hessian_fvar_hessian_ = 3.0;

  Eigen::MatrixXd x(4, 4);
  x << 2, 3, 4, 5, 9, -1, 2, 2, 4, 3, 7, -1, 0, 1, 19, 112;
  stan::test::expect_ad(tols2, f, x);
  //  stan::test::expect_ad_matvar(tols2, f, x);

  Eigen::MatrixXd z(2, 2);
  z << 1, 2, 5, std::numeric_limits<double>::quiet_NaN();
  EXPECT_NO_THROW(stan::math::generalized_inverse(z));

  // autodiff throws, so following fails (throw behavior must match to pass)
  // stan::test::expect_ad(f, z);

  Eigen::MatrixXd a(2, 2);
  a << 1.9, 0.3, 0.3, std::numeric_limits<double>::infinity();
  stan::test::expect_ad(f, a);
  //  stan::test::expect_ad_matvar(f, a);

  // singular matrix, should use the
  // alias to input small amount of jitter on the diagonal
  Eigen::MatrixXd m(3, 2);
  m << 1, 2, 2, 4, 1, 2;
  EXPECT_THROW(stan::math::generalized_inverse(m), std::domain_error);
}

<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#include <test/unit/math/test_ad.hpp>
#include <vector>

TEST(mathMixMatFun, generalized_inverse) {
  auto f = [](const auto& x) { return stan::math::generalized_inverse(x); };

  Eigen::MatrixXd t(0, 0);
  stan::test::expect_ad(f, t);
  //  stan::test::expect_ad_matvar(f, t);

  Eigen::MatrixXd u(1, 1);
  u << 2;
  stan::test::expect_ad(f, u);
  //  stan::test::expect_ad_matvar(f, u);
  //
  Eigen::MatrixXd v(2, 3);
  v << 1, 3, 5, 2, 4, 6;
  stan::test::expect_ad(f, v);
  //  stan::test::expect_ad_matvar(f, v);
  v << 1.9, 1.3, 2.5, 0.4, 1.7, 0.1;
  stan::test::expect_ad(f, v);
  //  stan::test::expect_ad_matvar(f, v);

  // issues around zero require looser tolerances for hessians
  stan::test::ad_tolerances tols;
  tols.hessian_hessian_ = 0.1;
  tols.hessian_fvar_hessian_ = 0.1;

  Eigen::MatrixXd w(3, 4);
  w << 2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 27, 29;
  stan::test::expect_ad(tols, f, w);
  //  stan::test::expect_ad_matvar(tols, f, w);

  // even lower tolerance, again for cases around zero
  stan::test::ad_tolerances tols2;
  tols2.hessian_hessian_ = 3.0;
  tols2.hessian_fvar_hessian_ = 3.0;

  Eigen::MatrixXd x(4, 4);
  x << 2, 3, 4, 5, 9, -1, 2, 2, 4, 3, 7, -1, 0, 1, 19, 112;
  stan::test::expect_ad(tols2, f, x);
  //  stan::test::expect_ad_matvar(tols2, f, x);

  Eigen::MatrixXd z(2, 2);
  z << 1, 2, 5, std::numeric_limits<double>::quiet_NaN();
  EXPECT_NO_THROW(stan::math::generalized_inverse(z));

  // autodiff throws, so following fails (throw behavior must match to pass)
  // stan::test::expect_ad(f, z);

  Eigen::MatrixXd a(2, 2);
  a << 1.9, 0.3, 0.3, std::numeric_limits<double>::infinity();
  stan::test::expect_ad(f, a);
  //  stan::test::expect_ad_matvar(f, a);

  // singular matrix, should use the
  // alias to input small amount of jitter on the diagonal
  Eigen::MatrixXd m(3, 2);
  m << 1, 2, 2, 4, 1, 2;
  EXPECT_THROW(stan::math::generalized_inverse(m), std::domain_error);
}
<|endoftext|>


<commit_before>#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkDevice.h"
#include "SkPaint.h"
#include "SkShader.h"

static SkShader* createChecker() {
    SkBitmap bm;
    bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
    bm.allocPixels();
    bm.lockPixels();
    *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(0xFFFFFFFF);
    *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(0xFFCCCCCC);
    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                               SkShader::kRepeat_TileMode);

    SkMatrix m;
    m.setScale(12, 12);
    s->setLocalMatrix(m);
    return s;
}

static SkBitmap createBitmap(int n) {
    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kARGB_8888_Config, n, n);
    bitmap.allocPixels();
    bitmap.eraseColor(0);

    SkCanvas canvas(bitmap);
    SkRect r;
    r.set(0, 0, SkIntToScalar(n), SkIntToScalar(n));
    r.inset(SK_Scalar1, SK_Scalar1);

    SkPaint paint;
    paint.setAntiAlias(true);

    paint.setColor(SK_ColorRED);
    canvas.drawOval(r, paint);

    r.inset(SK_Scalar1*n/4, SK_Scalar1*n/4);
    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    paint.setColor(0x800000FF);
    canvas.drawOval(r, paint);

    return bitmap;
}

class ColorFilterView : public SampleView {
    SkBitmap fBitmap;
    SkShader* fShader;
    enum {
        N = 64
    };
public:
    ColorFilterView() {
        fBitmap = createBitmap(N);
        fShader = createChecker();
    }

    virtual ~ColorFilterView() {
        fShader->unref();
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "ColorFilter");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawBackground(SkCanvas* canvas) {
        SkPaint paint;
        paint.setShader(fShader);
        canvas->drawPaint(paint);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        if (false) {
            SkPaint p;
            p.setAntiAlias(true);
            SkRect r = { 20.4f, 10, 20.6f, 20 };
            canvas->drawRect(r, p);
            r.set(30.9f, 10, 31.1f, 20);
            canvas->drawRect(r, p);
            return;
        }

        static const SkXfermode::Mode gModes[] = {
            SkXfermode::kClear_Mode,
            SkXfermode::kSrc_Mode,
            SkXfermode::kDst_Mode,
            SkXfermode::kSrcOver_Mode,
            SkXfermode::kDstOver_Mode,
            SkXfermode::kSrcIn_Mode,
            SkXfermode::kDstIn_Mode,
            SkXfermode::kSrcOut_Mode,
            SkXfermode::kDstOut_Mode,
            SkXfermode::kSrcATop_Mode,
            SkXfermode::kDstATop_Mode,
            SkXfermode::kXor_Mode,
            SkXfermode::kPlus_Mode,
            SkXfermode::kMultiply_Mode,
        };

        static const SkColor gColors[] = {
            0xFF000000,
            0x80000000,
            0xFF00FF00,
            0x8000FF00,
            0x00000000,
        };

        float scale = 1.5f;
        SkPaint paint;
        canvas->translate(N / 8, N / 8);

        for (size_t y = 0; y < SK_ARRAY_COUNT(gColors); y++) {
            for (size_t x = 0; x < SK_ARRAY_COUNT(gModes); x++) {
                SkColorFilter* cf = SkColorFilter::CreateModeFilter(gColors[y], gModes[x]);
                SkSafeUnref(paint.setColorFilter(cf));
                canvas->drawBitmap(fBitmap, x * N * 1.25f, y * N * scale, &paint);
            }
        }

    }

private:
    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new ColorFilterView; }
static SkViewRegister reg(MyFactory);

<commit_msg>checkpoint for 8->5 bit reduction<commit_after>#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkDevice.h"
#include "SkPaint.h"
#include "SkShader.h"

static int inflate5To8(int x) {
    return (x << 3) | (x >> 2);
}

static int trunc5(int x) {
    return x >> 3;
}

#define SK_R16_BITS 5

static int round5_slow(int x) {
    int orig = x & 7;
    int fake = x >> 5;
    int trunc = x >> 3;

    int diff = fake - orig;

    int bias = 0;
    if (diff > 4) {
        bias = -1;
    } else if (diff < -4) {
        bias = 1;
    }
    return trunc + bias;
}

static int round5_fast(int x) {
    int result = x + 3 - (x >> 5) + (x >> 7);
    result >>= 3;

    {
        int r2 = round5_slow(x);
        SkASSERT(r2 == result);
    }
    return result;
}

static void test_5bits() {
    int e0 = 0;
    int e1 = 0;
    int e2 = 0;
    int ae0 = 0;
    int ae1 = 0;
    int ae2 = 0;
    for (int i = 0; i < 256; i++) {
        int t0 = trunc5(i);
        int t1 = round5_fast(i);
        int t2 = trunc5(i);
        int v0 = inflate5To8(t0);
        int v1 = inflate5To8(t1);
        int v2 = inflate5To8(t2);
        int err0 = i - v0;
        int err1 = i - v1;
        int err2 = i - v2;
        SkDebugf("--- %3d : trunc=%3d (%2d) round:%3d (%2d) \n"/*new:%d (%2d)\n"*/, i,
                 v0, err0, v1, err1, v2, err2);

        e0 += err0;
        e1 += err1;
        e2 += err2;
        ae0 += SkAbs32(err0);
        ae1 += SkAbs32(err1);
        ae2 += SkAbs32(err2);
    }
    SkDebugf("--- trunc: %d %d  round: %d %d new: %d %d\n", e0, ae0, e1, ae1, e2, ae2);
}

static SkShader* createChecker() {
    SkBitmap bm;
    bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
    bm.allocPixels();
    bm.lockPixels();
    *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(0xFFFFFFFF);
    *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(0xFFCCCCCC);
    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                               SkShader::kRepeat_TileMode);

    SkMatrix m;
    m.setScale(12, 12);
    s->setLocalMatrix(m);
    return s;
}

static SkBitmap createBitmap(int n) {
    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kARGB_8888_Config, n, n);
    bitmap.allocPixels();
    bitmap.eraseColor(0);

    SkCanvas canvas(bitmap);
    SkRect r;
    r.set(0, 0, SkIntToScalar(n), SkIntToScalar(n));
    r.inset(SK_Scalar1, SK_Scalar1);

    SkPaint paint;
    paint.setAntiAlias(true);

    paint.setColor(SK_ColorRED);
    canvas.drawOval(r, paint);

    r.inset(SK_Scalar1*n/4, SK_Scalar1*n/4);
    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    paint.setColor(0x800000FF);
    canvas.drawOval(r, paint);

    return bitmap;
}

class ColorFilterView : public SampleView {
    SkBitmap fBitmap;
    SkShader* fShader;
    enum {
        N = 64
    };
public:
    ColorFilterView() {
        fBitmap = createBitmap(N);
        fShader = createChecker();

//        test_5bits();
    }

    virtual ~ColorFilterView() {
        fShader->unref();
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "ColorFilter");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual void onDrawBackground(SkCanvas* canvas) {
        SkPaint paint;
        paint.setShader(fShader);
        canvas->drawPaint(paint);
    }

    virtual void onDrawContent(SkCanvas* canvas) {
        if (false) {
            SkPaint p;
            p.setAntiAlias(true);
            SkRect r = { 20.4f, 10, 20.6f, 20 };
            canvas->drawRect(r, p);
            r.set(30.9f, 10, 31.1f, 20);
            canvas->drawRect(r, p);
            return;
        }

        static const SkXfermode::Mode gModes[] = {
            SkXfermode::kClear_Mode,
            SkXfermode::kSrc_Mode,
            SkXfermode::kDst_Mode,
            SkXfermode::kSrcOver_Mode,
            SkXfermode::kDstOver_Mode,
            SkXfermode::kSrcIn_Mode,
            SkXfermode::kDstIn_Mode,
            SkXfermode::kSrcOut_Mode,
            SkXfermode::kDstOut_Mode,
            SkXfermode::kSrcATop_Mode,
            SkXfermode::kDstATop_Mode,
            SkXfermode::kXor_Mode,
            SkXfermode::kPlus_Mode,
            SkXfermode::kMultiply_Mode,
        };

        static const SkColor gColors[] = {
            0xFF000000,
            0x80000000,
            0xFF00FF00,
            0x8000FF00,
            0x00000000,
        };

        float scale = 1.5f;
        SkPaint paint;
        canvas->translate(N / 8, N / 8);

        for (size_t y = 0; y < SK_ARRAY_COUNT(gColors); y++) {
            for (size_t x = 0; x < SK_ARRAY_COUNT(gModes); x++) {
                SkColorFilter* cf = SkColorFilter::CreateModeFilter(gColors[y], gModes[x]);
                SkSafeUnref(paint.setColorFilter(cf));
                canvas->drawBitmap(fBitmap, x * N * 1.25f, y * N * scale, &paint);
            }
        }

    }

private:
    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new ColorFilterView; }
static SkViewRegister reg(MyFactory);

<|endoftext|>