<commit_before>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2018 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 * @file QRCodeWidget.cpp
 *
 * This file implements the QRCodeWidget that displays a QRCode centered on the screen
 * It generates a CHIP SetupPayload containing the device's Soft-AP SSID and then
 * encodes that into a QRCode.
 *
 */

#include "esp_log.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "qrcodegen.h"

#include <platform/CHIPDeviceLayer.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <support/CodeUtils.h>

#include "Display.h"
#include "QRCodeWidget.h"

#define MAX_SSID_LEN 32
// A temporary value assigned for this example's QRCode
// Spells CHIP on a dialer
#define EXAMPLE_VENDOR_ID 3447
// Used to indicate that an SSID has been added to the QRCode
#define EXAMPLE_VENDOR_TAG_SSID 1
// Used to indicate that an IP address has been added to the QRCode
#define EXAMPLE_VENDOR_TAG_IP 2

#if CONFIG_HAVE_DISPLAY

extern const char * TAG;

using namespace ::chip;
using namespace ::chip::DeviceLayer;

// QRCode config
enum
{
    kQRCodeVersion       = 4,
    kQRCodeModuleSizePix = 4,
    kQRCodePadding       = 2
};

// TODO Pull this from the configuration manager
void GetAPName(char * ssid, size_t ssid_len)
{
    uint8_t mac[6];
    CHIP_ERROR err = esp_wifi_get_mac(ESP_IF_WIFI_STA, mac);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "esp_wifi_get_mac(ESP_IF_WIFI_STA) failed: %s", chip::ErrorStr(err));
    }
    snprintf(ssid, ssid_len, "%s%02X%02X", "CHIP_DEMO-", mac[4], mac[5]);
}

void GetGatewayIP(char * ip_buf, size_t ip_len)
{

    tcpip_adapter_ip_info_t ip;
    tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip);
    IPAddress::FromIPv4(ip.ip).ToString(ip_buf, ip_len);
    ESP_LOGE(TAG, "Got gateway ip %s", ip_buf);
}

string createSetupPayload()
{
    char ap_ssid[MAX_SSID_LEN];
    GetAPName(ap_ssid, sizeof(ap_ssid));
    SetupPayload payload;
    payload.version   = 1;
    payload.vendorID  = EXAMPLE_VENDOR_ID;
    payload.productID = 1;
    payload.addVendorOptionalData(EXAMPLE_VENDOR_TAG_SSID, ap_ssid);

    char gw_ip[INET6_ADDRSTRLEN];
    GetGatewayIP(gw_ip, sizeof(gw_ip));
    payload.addVendorOptionalData(EXAMPLE_VENDOR_TAG_IP, gw_ip);

    QRCodeSetupPayloadGenerator generator(payload);
    string result;
    size_t tlvDataLen = sizeof(ap_ssid) + sizeof(gw_ip);
    uint8_t tlvDataStart[tlvDataLen];
    CHIP_ERROR err = generator.payloadBase41Representation(result, tlvDataStart, tlvDataLen);
    if (err != CHIP_NO_ERROR)
    {
        ESP_LOGE(TAG, "Couldn't get payload string %d", generator.payloadBase41Representation(result));
    }
    return result;
};

QRCodeWidget::QRCodeWidget()
{
    QRCodeColor = TFT_DARKGREY;
    VMargin     = 10;
}

void QRCodeWidget::Display()
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    enum
    {
        kMaxQRCodeStrLength = 120
    };

    string generatedQRCodeData;
    char * qrCodeStr        = NULL;
    uint8_t * qrCodeTempBuf = NULL;
    uint8_t * qrCode        = NULL;
    uint16_t qrCodeDisplaySize, qrCodeX, qrCodeY, qrCodeXOffset, qrCodeYOffset;

    generatedQRCodeData = createSetupPayload();
    qrCodeStr           = (char *) generatedQRCodeData.c_str();

    // Generate the QR code.
    uint16_t qrCodeSize = qrcodegen_BUFFER_LEN_FOR_VERSION(kQRCodeVersion);
    qrCodeTempBuf       = (uint8_t *) malloc(qrCodeSize);
    qrCode              = (uint8_t *) malloc(qrCodeSize);
    VerifyOrExit(qrCodeTempBuf != NULL, err = CHIP_ERROR_NO_MEMORY);
    VerifyOrExit(qrCode != NULL, err = CHIP_ERROR_NO_MEMORY);
    if (!qrcodegen_encodeText(qrCodeStr, qrCodeTempBuf, qrCode, qrcodegen_Ecc_LOW, kQRCodeVersion, kQRCodeVersion,
                              qrcodegen_Mask_AUTO, true))
    {
        ESP_LOGE(TAG, "qrcodegen_encodeText() failed");
        ExitNow(err = CHIP_ERROR_INCORRECT_STATE);
    }

    // Draw the QR code image on the screen.
    qrCodeDisplaySize = (qrcodegen_getSize(qrCode) + kQRCodePadding) * kQRCodeModuleSizePix;
    qrCodeX           = (DisplayWidth - qrCodeDisplaySize) / 2;
    qrCodeY           = (DisplayHeight * VMargin) / 100;
    qrCodeXOffset     = qrCodeX + kQRCodeModuleSizePix;
    qrCodeYOffset     = qrCodeY + kQRCodeModuleSizePix;
    TFT_fillRect(qrCodeX, qrCodeY, (int) qrCodeDisplaySize, (int) qrCodeDisplaySize, QRCodeColor);
    for (uint8_t y = 0; y < qrcodegen_getSize(qrCode); y++)
    {
        for (uint8_t x = 0; x < qrcodegen_getSize(qrCode); x++)
        {
            if (qrcodegen_getModule(qrCode, x, y))
            {
                TFT_fillRect(x * kQRCodeModuleSizePix + qrCodeXOffset, y * kQRCodeModuleSizePix + qrCodeYOffset,
                             (int) kQRCodeModuleSizePix, (int) kQRCodeModuleSizePix, TFT_BLACK);
            }
        }
    }

exit:
    if (qrCode != NULL)
    {
        free(qrCode);
    }
    if (qrCodeTempBuf != NULL)
    {
        free(qrCodeTempBuf);
    }
    if (err != CHIP_NO_ERROR)
    {
        ESP_LOGE(TAG, "QRCodeWidget::Display() failed: %s", ErrorStr(err));
    }
}

#endif // CONFIG_HAVE_DISPLAY
<commit_msg>ESP32 build issue: addVendorOptionalData has been renamed addOptionalVendorData (#1230)<commit_after>/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2018 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 * @file QRCodeWidget.cpp
 *
 * This file implements the QRCodeWidget that displays a QRCode centered on the screen
 * It generates a CHIP SetupPayload containing the device's Soft-AP SSID and then
 * encodes that into a QRCode.
 *
 */

#include "esp_log.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "qrcodegen.h"

#include <platform/CHIPDeviceLayer.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <support/CodeUtils.h>

#include "Display.h"
#include "QRCodeWidget.h"

#define MAX_SSID_LEN 32
// A temporary value assigned for this example's QRCode
// Spells CHIP on a dialer
#define EXAMPLE_VENDOR_ID 3447
// Used to indicate that an SSID has been added to the QRCode
#define EXAMPLE_VENDOR_TAG_SSID 1
// Used to indicate that an IP address has been added to the QRCode
#define EXAMPLE_VENDOR_TAG_IP 2

#if CONFIG_HAVE_DISPLAY

extern const char * TAG;

using namespace ::chip;
using namespace ::chip::DeviceLayer;

// QRCode config
enum
{
    kQRCodeVersion       = 4,
    kQRCodeModuleSizePix = 4,
    kQRCodePadding       = 2
};

// TODO Pull this from the configuration manager
void GetAPName(char * ssid, size_t ssid_len)
{
    uint8_t mac[6];
    CHIP_ERROR err = esp_wifi_get_mac(ESP_IF_WIFI_STA, mac);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "esp_wifi_get_mac(ESP_IF_WIFI_STA) failed: %s", chip::ErrorStr(err));
    }
    snprintf(ssid, ssid_len, "%s%02X%02X", "CHIP_DEMO-", mac[4], mac[5]);
}

void GetGatewayIP(char * ip_buf, size_t ip_len)
{

    tcpip_adapter_ip_info_t ip;
    tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip);
    IPAddress::FromIPv4(ip.ip).ToString(ip_buf, ip_len);
    ESP_LOGE(TAG, "Got gateway ip %s", ip_buf);
}

string createSetupPayload()
{
    char ap_ssid[MAX_SSID_LEN];
    GetAPName(ap_ssid, sizeof(ap_ssid));
    SetupPayload payload;
    payload.version   = 1;
    payload.vendorID  = EXAMPLE_VENDOR_ID;
    payload.productID = 1;
    payload.addOptionalVendorData(EXAMPLE_VENDOR_TAG_SSID, ap_ssid);

    char gw_ip[INET6_ADDRSTRLEN];
    GetGatewayIP(gw_ip, sizeof(gw_ip));
    payload.addOptionalVendorData(EXAMPLE_VENDOR_TAG_IP, gw_ip);

    QRCodeSetupPayloadGenerator generator(payload);
    string result;
    size_t tlvDataLen = sizeof(ap_ssid) + sizeof(gw_ip);
    uint8_t tlvDataStart[tlvDataLen];
    CHIP_ERROR err = generator.payloadBase41Representation(result, tlvDataStart, tlvDataLen);
    if (err != CHIP_NO_ERROR)
    {
        ESP_LOGE(TAG, "Couldn't get payload string %d", generator.payloadBase41Representation(result));
    }
    return result;
};

QRCodeWidget::QRCodeWidget()
{
    QRCodeColor = TFT_DARKGREY;
    VMargin     = 10;
}

void QRCodeWidget::Display()
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    enum
    {
        kMaxQRCodeStrLength = 120
    };

    string generatedQRCodeData;
    char * qrCodeStr        = NULL;
    uint8_t * qrCodeTempBuf = NULL;
    uint8_t * qrCode        = NULL;
    uint16_t qrCodeDisplaySize, qrCodeX, qrCodeY, qrCodeXOffset, qrCodeYOffset;

    generatedQRCodeData = createSetupPayload();
    qrCodeStr           = (char *) generatedQRCodeData.c_str();

    // Generate the QR code.
    uint16_t qrCodeSize = qrcodegen_BUFFER_LEN_FOR_VERSION(kQRCodeVersion);
    qrCodeTempBuf       = (uint8_t *) malloc(qrCodeSize);
    qrCode              = (uint8_t *) malloc(qrCodeSize);
    VerifyOrExit(qrCodeTempBuf != NULL, err = CHIP_ERROR_NO_MEMORY);
    VerifyOrExit(qrCode != NULL, err = CHIP_ERROR_NO_MEMORY);
    if (!qrcodegen_encodeText(qrCodeStr, qrCodeTempBuf, qrCode, qrcodegen_Ecc_LOW, kQRCodeVersion, kQRCodeVersion,
                              qrcodegen_Mask_AUTO, true))
    {
        ESP_LOGE(TAG, "qrcodegen_encodeText() failed");
        ExitNow(err = CHIP_ERROR_INCORRECT_STATE);
    }

    // Draw the QR code image on the screen.
    qrCodeDisplaySize = (qrcodegen_getSize(qrCode) + kQRCodePadding) * kQRCodeModuleSizePix;
    qrCodeX           = (DisplayWidth - qrCodeDisplaySize) / 2;
    qrCodeY           = (DisplayHeight * VMargin) / 100;
    qrCodeXOffset     = qrCodeX + kQRCodeModuleSizePix;
    qrCodeYOffset     = qrCodeY + kQRCodeModuleSizePix;
    TFT_fillRect(qrCodeX, qrCodeY, (int) qrCodeDisplaySize, (int) qrCodeDisplaySize, QRCodeColor);
    for (uint8_t y = 0; y < qrcodegen_getSize(qrCode); y++)
    {
        for (uint8_t x = 0; x < qrcodegen_getSize(qrCode); x++)
        {
            if (qrcodegen_getModule(qrCode, x, y))
            {
                TFT_fillRect(x * kQRCodeModuleSizePix + qrCodeXOffset, y * kQRCodeModuleSizePix + qrCodeYOffset,
                             (int) kQRCodeModuleSizePix, (int) kQRCodeModuleSizePix, TFT_BLACK);
            }
        }
    }

exit:
    if (qrCode != NULL)
    {
        free(qrCode);
    }
    if (qrCodeTempBuf != NULL)
    {
        free(qrCodeTempBuf);
    }
    if (err != CHIP_NO_ERROR)
    {
        ESP_LOGE(TAG, "QRCodeWidget::Display() failed: %s", ErrorStr(err));
    }
}

#endif // CONFIG_HAVE_DISPLAY
<|endoftext|>


<commit_before>/* -*- Mode:C++; c-file-style:"gnu" -*- */
/*
 * Copyright 2014 Waseda University, Sato Laboratory
 *   Author: Jairo Eduardo Lopez <jairo@ruri.waseda.jp>
 *           Zhu Li <philispzhuli1990@ruri.waseda.jp>
 *
 *  nnnsim-den.cc is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  nnnsim-den.cc 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 Affero Public License for more details.
 *
 *  You should have received a copy of the GNU Affero Public License
 *  along with nnnsim-den.cc.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "nnnsim-den.h"

NNN_NAMESPACE_BEGIN

namespace wire{
  namespace nnnSIM{

    NS_OBJECT_ENSURE_REGISTERED (DEN);

    NS_LOG_COMPONENT_DEFINE ("nnn.wire.nnnSIM.DEN");

    DEN::DEN ()
    : CommonHeader<nnn::DEN>()
    {
    }

    DEN::DEN(Ptr<nnn::DEN> den_p)
    : CommonHeader<nnn::DEN>(den_p)
    {
    }

    TypeId
    DEN::GetTypeId(void)
    {
      static TypeId tid = TypeId("ns3::nnn::DEN::nnnSIM")
	  .SetGroupName("Nnn")
	  .SetParent<Header> ()
	  .AddConstructor<DEN> ()
	  ;
      return tid;
    }

    TypeId
    DEN::GetInstanceTypeId (void) const
    {
      return GetTypeId ();
    }

    Ptr<Packet>
    DEN::ToWire(Ptr<const nnn::DEN> den_p)
    {
      Ptr<const Packet> p = den_p->GetWire ();
      if (!p)
	{
	  // Mechanism packets have no payload, make an empty packet
	  Ptr<Packet> packet = Create<Packet> ();
	  DEN wireEncoding (ConstCast<nnn::DEN> (den_p));
	  packet-> AddHeader (wireEncoding);
	  den_p->SetWire (packet);

	  p = packet;
	}
      return p->Copy();
    }

    Ptr<nnn::DEN>
    DEN::FromWire (Ptr<Packet> packet)
    {
      Ptr<nnn::DEN> den_p = Create<nnn::DEN> ();
      Ptr<Packet> wire = packet->Copy();

      DEN wireEncoding (den_p);
      packet->RemoveHeader (wireEncoding);

      // Mechanism packets have no payload, make an empty packet
      den_p->SetWire (wire);

      return den_p;
    }

    uint32_t
    DEN::GetSerializedSize(void) const
    {
      uint16_t poatype = m_ptr->GetPoaType ();
      size_t poatype_size = 0;
      size_t poa_num = 0;

      if (poatype == 0)
	{
	  poa_num = m_ptr->GetNumPoa ();
	  poatype_size = 6; // Hardcoded size of a Mac48Address
	}

      size_t size = CommonGetSerializedSize() +         /* Common header */
	  2 +                                           /* PoA Type*/
	  2 +                                           /* Number of PoAs */
	  poa_num * poatype_size +                      /* Total size of PoAs */
	  NnnSim::SerializedSizeName(m_ptr->GetName()); /* Name size */
      return size;
    }

    void
    DEN::Serialize(Buffer::Iterator start) const
    {
      // Serialize the header
      CommonSerialize(start);

      // Remember that CommonSerialize doesn't write the Packet length
      // Move the iterator forward
      start.Next(CommonGetSerializedSize() -2);

      NS_LOG_INFO ("Serialize -> PktID = " << m_ptr->GetPacketId());
      NS_LOG_INFO ("Serialize -> TTL = " << Seconds(static_cast<uint16_t> (m_ptr->GetLifetime ().ToInteger (Time::S))));
      NS_LOG_INFO ("Serialize -> Version = " << m_ptr->GetVersion ());
      NS_LOG_INFO ("Serialize -> Pkt Len = " << GetSerializedSize());

      start.WriteU16(GetSerializedSize());

      uint16_t poatype = m_ptr->GetPoaType ();

      NS_LOG_INFO ("Serialize -> PoA Type = " << poatype);
      size_t bufsize = 0;

      if (poatype == 0)
	bufsize = 6; // Hardcoded Mac48Address size

      // Create a buffer to be able to serialize PoAs
      uint8_t buffer[bufsize];

      uint32_t totalpoas = m_ptr->GetNumPoa();

      NS_LOG_INFO ("Serialize -> PoA Num = " << totalpoas);

      // Serialize PoA Type
      start.WriteU16(poatype);

      // Serialize Number of PoAs
      start.WriteU16(totalpoas);

      // Serialize PoAs
      for (int i = 0; i < totalpoas; i++)
	{
	  // Use the CopyTo function to get the bit representation
	  m_ptr->GetOnePoa(i).CopyTo(buffer);

	  // Since the bit representation is in 8 bit chunks, serialize it
	  // accordingly
	  for (int j = 0; j < bufsize; j++)
	    start.WriteU8(buffer[j]);
	}

      // Serialize NNN address
      NnnSim::SerializeName(start, m_ptr->GetName());

      NS_LOG_INFO("Finished serialization");
    }

    uint32_t
    DEN::Deserialize (Buffer::Iterator start)
    {
      Buffer::Iterator i = start;

      // Deserialize the header
      uint32_t skip = CommonDeserialize (i);

      NS_LOG_INFO ("Deserialize -> PktID = " << m_ptr->GetPacketId());
      NS_LOG_INFO ("Deserialize -> TTL = " << Seconds(static_cast<uint16_t> (m_ptr->GetLifetime ().ToInteger (Time::S))));
      NS_LOG_INFO ("Deserialize -> Version = " << m_ptr->GetVersion ());
      NS_LOG_INFO ("Deserialize -> Pkt len = " << m_packet_len);

      // Check packet ID
      if (m_ptr->GetPacketId() != nnn::DEN_NNN)
	throw new DENException ();

      // Move the iterator forward
      i.Next(skip);

      uint16_t poatype = i.ReadU16 ();
      size_t bufsize = 0;

      NS_LOG_INFO ("Deserialize -> PoA Type = " << poatype);

      if (poatype == 0)
	bufsize = 6; // Hardcoded Mac48Address size

      uint16_t totalpoas = i.ReadU16 ();

      NS_LOG_INFO ("Deserialize -> PoA Num = " << totalpoas);

      // Create a buffer to be able to deserialize PoAs
      uint8_t buffer[bufsize];

      for (int k = 0; k < totalpoas; k++)
	{
	  for (int j = 0; j < bufsize; j++)
	    {
	      buffer[j] = i.ReadU8 ();
	    }

	  Address tmp = Address ();
	  tmp.CopyFrom(buffer, bufsize);

	  m_ptr->AddPoa(tmp);
	}

      // Deserialize the old name
      m_ptr->SetName(NnnSim::DeserializeName(i));

      NS_ASSERT (GetSerializedSize ()== (i.GetDistanceFrom (start)));

      return i.GetDistanceFrom (start);
    }
  }
}

NNN_NAMESPACE_END
<commit_msg>Small comment on nnnsim-den.cc<commit_after>/* -*- Mode:C++; c-file-style:"gnu" -*- */
/*
 * Copyright 2014 Waseda University, Sato Laboratory
 *   Author: Jairo Eduardo Lopez <jairo@ruri.waseda.jp>
 *           Zhu Li <philispzhuli1990@ruri.waseda.jp>
 *
 *  nnnsim-den.cc is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  nnnsim-den.cc 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 Affero Public License for more details.
 *
 *  You should have received a copy of the GNU Affero Public License
 *  along with nnnsim-den.cc.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "nnnsim-den.h"

NNN_NAMESPACE_BEGIN

namespace wire{
  namespace nnnSIM{

    NS_OBJECT_ENSURE_REGISTERED (DEN);

    NS_LOG_COMPONENT_DEFINE ("nnn.wire.nnnSIM.DEN");

    DEN::DEN ()
    : CommonHeader<nnn::DEN>()
    {
    }

    DEN::DEN(Ptr<nnn::DEN> den_p)
    : CommonHeader<nnn::DEN>(den_p)
    {
    }

    TypeId
    DEN::GetTypeId(void)
    {
      static TypeId tid = TypeId("ns3::nnn::DEN::nnnSIM")
	  .SetGroupName("Nnn")
	  .SetParent<Header> ()
	  .AddConstructor<DEN> ()
	  ;
      return tid;
    }

    TypeId
    DEN::GetInstanceTypeId (void) const
    {
      return GetTypeId ();
    }

    Ptr<Packet>
    DEN::ToWire(Ptr<const nnn::DEN> den_p)
    {
      Ptr<const Packet> p = den_p->GetWire ();
      if (!p)
	{
	  // Mechanism packets have no payload, make an empty packet
	  Ptr<Packet> packet = Create<Packet> ();
	  DEN wireEncoding (ConstCast<nnn::DEN> (den_p));
	  packet-> AddHeader (wireEncoding);
	  den_p->SetWire (packet);

	  p = packet;
	}
      return p->Copy();
    }

    Ptr<nnn::DEN>
    DEN::FromWire (Ptr<Packet> packet)
    {
      Ptr<nnn::DEN> den_p = Create<nnn::DEN> ();
      Ptr<Packet> wire = packet->Copy();

      DEN wireEncoding (den_p);
      packet->RemoveHeader (wireEncoding);

      // Mechanism packets have no payload, make an empty packet
      den_p->SetWire (wire);

      return den_p;
    }

    uint32_t
    DEN::GetSerializedSize(void) const
    {
      uint16_t poatype = m_ptr->GetPoaType ();
      size_t poatype_size = 0;
      size_t poa_num = 0;

      if (poatype == 0)
	{
	  poa_num = m_ptr->GetNumPoa ();
	  poatype_size = 6; // Hardcoded size of a Mac48Address
	}

      size_t size = CommonGetSerializedSize() +         /* Common header */
	  2 +                                           /* PoA Type*/
	  2 +                                           /* Number of PoAs */
	  poa_num * poatype_size +                      /* Total size of PoAs */
	  NnnSim::SerializedSizeName(m_ptr->GetName()); /* Name size */
      return size;
    }

    void
    DEN::Serialize(Buffer::Iterator start) const
    {
      // Serialize the header
      CommonSerialize(start);

      // Remember that CommonSerialize doesn't write the Packet length
      // Move the iterator forward
      start.Next(CommonGetSerializedSize() -2);

      NS_LOG_INFO ("Serialize -> PktID = " << m_ptr->GetPacketId());
      NS_LOG_INFO ("Serialize -> TTL = " << Seconds(static_cast<uint16_t> (m_ptr->GetLifetime ().ToInteger (Time::S))));
      NS_LOG_INFO ("Serialize -> Version = " << m_ptr->GetVersion ());
      NS_LOG_INFO ("Serialize -> Pkt Len = " << GetSerializedSize());

      // Serialize the packet size
      start.WriteU16(GetSerializedSize());

      uint16_t poatype = m_ptr->GetPoaType ();

      NS_LOG_INFO ("Serialize -> PoA Type = " << poatype);
      size_t bufsize = 0;

      if (poatype == 0)
	bufsize = 6; // Hardcoded Mac48Address size

      // Create a buffer to be able to serialize PoAs
      uint8_t buffer[bufsize];

      uint32_t totalpoas = m_ptr->GetNumPoa();

      NS_LOG_INFO ("Serialize -> PoA Num = " << totalpoas);

      // Serialize PoA Type
      start.WriteU16(poatype);

      // Serialize Number of PoAs
      start.WriteU16(totalpoas);

      // Serialize PoAs
      for (int i = 0; i < totalpoas; i++)
	{
	  // Use the CopyTo function to get the bit representation
	  m_ptr->GetOnePoa(i).CopyTo(buffer);

	  // Since the bit representation is in 8 bit chunks, serialize it
	  // accordingly
	  for (int j = 0; j < bufsize; j++)
	    start.WriteU8(buffer[j]);
	}

      // Serialize NNN address
      NnnSim::SerializeName(start, m_ptr->GetName());

      NS_LOG_INFO("Finished serialization");
    }

    uint32_t
    DEN::Deserialize (Buffer::Iterator start)
    {
      Buffer::Iterator i = start;

      // Deserialize the header
      uint32_t skip = CommonDeserialize (i);

      NS_LOG_INFO ("Deserialize -> PktID = " << m_ptr->GetPacketId());
      NS_LOG_INFO ("Deserialize -> TTL = " << Seconds(static_cast<uint16_t> (m_ptr->GetLifetime ().ToInteger (Time::S))));
      NS_LOG_INFO ("Deserialize -> Version = " << m_ptr->GetVersion ());
      NS_LOG_INFO ("Deserialize -> Pkt len = " << m_packet_len);

      // Check packet ID
      if (m_ptr->GetPacketId() != nnn::DEN_NNN)
	throw new DENException ();

      // Move the iterator forward
      i.Next(skip);

      uint16_t poatype = i.ReadU16 ();
      size_t bufsize = 0;

      NS_LOG_INFO ("Deserialize -> PoA Type = " << poatype);

      if (poatype == 0)
	bufsize = 6; // Hardcoded Mac48Address size

      uint16_t totalpoas = i.ReadU16 ();

      NS_LOG_INFO ("Deserialize -> PoA Num = " << totalpoas);

      // Create a buffer to be able to deserialize PoAs
      uint8_t buffer[bufsize];

      for (int k = 0; k < totalpoas; k++)
	{
	  for (int j = 0; j < bufsize; j++)
	    {
	      buffer[j] = i.ReadU8 ();
	    }

	  Address tmp = Address ();
	  tmp.CopyFrom(buffer, bufsize);

	  m_ptr->AddPoa(tmp);
	}

      // Deserialize the old name
      m_ptr->SetName(NnnSim::DeserializeName(i));

      NS_ASSERT (GetSerializedSize ()== (i.GetDistanceFrom (start)));

      return i.GetDistanceFrom (start);
    }
  }
}

NNN_NAMESPACE_END
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ENTRY_HPP_INCLUDED
#define TORRENT_ENTRY_HPP_INCLUDED

/*
 *
 * This file declares the entry class. It is a
 * variant-type that can be an integer, list,
 * dictionary (map) or a string. This type is
 * used to hold bdecoded data (which is the
 * encoding BitTorrent messages uses).
 *
 * it has 4 accessors to access the actual
 * type of the object. They are:
 * integer()
 * string()
 * list()
 * dict()
 * The actual type has to match the type you
 * are asking for, otherwise you will get an
 * assertion failure.
 * When you default construct an entry, it is
 * uninitialized. You can initialize it through the
 * assignment operator, copy-constructor or
 * the constructor that takes a data_type enum.
 *
 *
 */

#include <map>
#include <list>
#include <string>
#include <stdexcept>

#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/max.hpp"

#if TORRENT_USE_IOSTREAM
#include <iosfwd>
#endif

namespace libtorrent
{
	struct lazy_entry;

	struct TORRENT_EXPORT type_error: std::runtime_error
	{
		type_error(const char* error): std::runtime_error(error) {}
	};

	class entry;

	class TORRENT_EXPORT entry
	{
	public:

		// the key is always a string. If a generic entry would be allowed
		// as a key, sorting would become a problem (e.g. to compare a string
		// to a list). The definition doesn't mention such a limit though.
		typedef std::map<std::string, entry> dictionary_type;
		typedef std::string string_type;
		typedef std::list<entry> list_type;
		typedef size_type integer_type;

		enum data_type
		{
			int_t,
			string_t,
			list_t,
			dictionary_t,
			undefined_t
		};

		data_type type() const;

		entry(dictionary_type const&);
		entry(string_type const&);
		entry(list_type const&);
		entry(integer_type const&);

		entry();
		entry(data_type t);
		entry(entry const& e);
		~entry();

		bool operator==(entry const& e) const;

		void operator=(lazy_entry const&);
		void operator=(entry const&);
		void operator=(dictionary_type const&);
		void operator=(string_type const&);
		void operator=(list_type const&);
		void operator=(integer_type const&);

		integer_type& integer();
		const integer_type& integer() const;
		string_type& string();
		const string_type& string() const;
		list_type& list();
		const list_type& list() const;
		dictionary_type& dict();
		const dictionary_type& dict() const;

		void swap(entry& e);

		// these functions requires that the entry
		// is a dictionary, otherwise they will throw
		entry& operator[](char const* key);
		entry& operator[](std::string const& key);
#ifndef BOOST_NO_EXCEPTIONS
		const entry& operator[](char const* key) const;
		const entry& operator[](std::string const& key) const;
#endif
		entry* find_key(char const* key);
		entry const* find_key(char const* key) const;
		entry* find_key(std::string const& key);
		entry const* find_key(std::string const& key) const;

#if (defined TORRENT_VERBOSE_LOGGING || defined TORRENT_DEBUG) && TORRENT_USE_IOSTREAM
		void print(std::ostream& os, int indent = 0) const;
#endif

	protected:

		void construct(data_type t);
		void copy(const entry& e);
		void destruct();

	private:

#ifndef TORRENT_DEBUG
		data_type m_type;
#else
		// the bitfield is used so that the m_type_queried
		// field still fits, so that the ABI is the same for
		// debug builds and release builds. It appears to be
		// very hard to match debug builds with debug versions
		// of libtorrent
		data_type m_type:31;

	public:
		// in debug mode this is set to false by bdecode
		// to indicate that the program has not yet queried
		// the type of this entry, and sould not assume
		// that it has a certain type. This is asserted in
		// the accessor functions. This does not apply if
		// exceptions are used.
		mutable bool m_type_queried:1;
	protected:
#endif // TORRENT_DEBUG

#if (defined(_MSC_VER) && _MSC_VER < 1310) || TORRENT_COMPLETE_TYPES_REQUIRED
		// workaround for msvc-bug.
		// assumes sizeof(map<string, char>) == sizeof(map<string, entry>)
		// and sizeof(list<char>) == sizeof(list<entry>)
		enum { union_size
			= max4<sizeof(std::list<char>)
			, sizeof(std::map<std::string, char>)
			, sizeof(string_type)
			, sizeof(integer_type)>::value
		};
#else
		enum { union_size
			= max4<sizeof(list_type)
			, sizeof(dictionary_type)
			, sizeof(string_type)
			, sizeof(integer_type)>::value
		};
#endif
		integer_type m_data[(union_size + sizeof(integer_type) - 1)
			/ sizeof(integer_type)];
	};

#if defined TORRENT_DEBUG && TORRENT_USE_IOSTREAM
	inline std::ostream& operator<<(std::ostream& os, const entry& e)
	{
		e.print(os, 0);
		return os;
	}
#endif

#ifndef BOOST_NO_EXCEPTIONS
	inline void throw_type_error()
	{
		throw libtorrent_exception(error_code(errors::invalid_entry_type
			, get_libtorrent_category()));
	}
#endif

}

#endif // TORRENT_ENTRY_HPP_INCLUDED

<commit_msg>fixed typo<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ENTRY_HPP_INCLUDED
#define TORRENT_ENTRY_HPP_INCLUDED

/*
 *
 * This file declares the entry class. It is a
 * variant-type that can be an integer, list,
 * dictionary (map) or a string. This type is
 * used to hold bdecoded data (which is the
 * encoding BitTorrent messages uses).
 *
 * it has 4 accessors to access the actual
 * type of the object. They are:
 * integer()
 * string()
 * list()
 * dict()
 * The actual type has to match the type you
 * are asking for, otherwise you will get an
 * assertion failure.
 * When you default construct an entry, it is
 * uninitialized. You can initialize it through the
 * assignment operator, copy-constructor or
 * the constructor that takes a data_type enum.
 *
 *
 */

#include <map>
#include <list>
#include <string>
#include <stdexcept>

#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/max.hpp"

#if TORRENT_USE_IOSTREAM
#include <iosfwd>
#endif

namespace libtorrent
{
	struct lazy_entry;

	struct TORRENT_EXPORT type_error: std::runtime_error
	{
		type_error(const char* error): std::runtime_error(error) {}
	};

	class entry;

	class TORRENT_EXPORT entry
	{
	public:

		// the key is always a string. If a generic entry would be allowed
		// as a key, sorting would become a problem (e.g. to compare a string
		// to a list). The definition doesn't mention such a limit though.
		typedef std::map<std::string, entry> dictionary_type;
		typedef std::string string_type;
		typedef std::list<entry> list_type;
		typedef size_type integer_type;

		enum data_type
		{
			int_t,
			string_t,
			list_t,
			dictionary_t,
			undefined_t
		};

		data_type type() const;

		entry(dictionary_type const&);
		entry(string_type const&);
		entry(list_type const&);
		entry(integer_type const&);

		entry();
		entry(data_type t);
		entry(entry const& e);
		~entry();

		bool operator==(entry const& e) const;

		void operator=(lazy_entry const&);
		void operator=(entry const&);
		void operator=(dictionary_type const&);
		void operator=(string_type const&);
		void operator=(list_type const&);
		void operator=(integer_type const&);

		integer_type& integer();
		const integer_type& integer() const;
		string_type& string();
		const string_type& string() const;
		list_type& list();
		const list_type& list() const;
		dictionary_type& dict();
		const dictionary_type& dict() const;

		void swap(entry& e);

		// these functions requires that the entry
		// is a dictionary, otherwise they will throw
		entry& operator[](char const* key);
		entry& operator[](std::string const& key);
#ifndef BOOST_NO_EXCEPTIONS
		const entry& operator[](char const* key) const;
		const entry& operator[](std::string const& key) const;
#endif
		entry* find_key(char const* key);
		entry const* find_key(char const* key) const;
		entry* find_key(std::string const& key);
		entry const* find_key(std::string const& key) const;

#if (defined TORRENT_VERBOSE_LOGGING || defined TORRENT_DEBUG) && TORRENT_USE_IOSTREAM
		void print(std::ostream& os, int indent = 0) const;
#endif

	protected:

		void construct(data_type t);
		void copy(const entry& e);
		void destruct();

	private:

#ifndef TORRENT_DEBUG
		data_type m_type;
#else
		// the bitfield is used so that the m_type_queried
		// field still fits, so that the ABI is the same for
		// debug builds and release builds. It appears to be
		// very hard to match debug builds with debug versions
		// of libtorrent
		data_type m_type:31;

	public:
		// in debug mode this is set to false by bdecode
		// to indicate that the program has not yet queried
		// the type of this entry, and sould not assume
		// that it has a certain type. This is asserted in
		// the accessor functions. This does not apply if
		// exceptions are used.
		mutable bool m_type_queried:1;
	protected:
#endif // TORRENT_DEBUG

#if (defined(_MSC_VER) && _MSC_VER < 1310) || TORRENT_COMPLETE_TYPES_REQUIRED
		// workaround for msvc-bug.
		// assumes sizeof(map<string, char>) == sizeof(map<string, entry>)
		// and sizeof(list<char>) == sizeof(list<entry>)
		enum { union_size
			= max4<sizeof(std::list<char>)
			, sizeof(std::map<std::string, char>)
			, sizeof(string_type)
			, sizeof(integer_type)>::value
		};
#else
		enum { union_size
			= max4<sizeof(list_type)
			, sizeof(dictionary_type)
			, sizeof(string_type)
			, sizeof(integer_type)>::value
		};
#endif
		integer_type data[(union_size + sizeof(integer_type) - 1)
			/ sizeof(integer_type)];
	};

#if defined TORRENT_DEBUG && TORRENT_USE_IOSTREAM
	inline std::ostream& operator<<(std::ostream& os, const entry& e)
	{
		e.print(os, 0);
		return os;
	}
#endif

#ifndef BOOST_NO_EXCEPTIONS
	inline void throw_type_error()
	{
		throw libtorrent_exception(error_code(errors::invalid_entry_type
			, get_libtorrent_category()));
	}
#endif

}

#endif // TORRENT_ENTRY_HPP_INCLUDED

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_GEOM_UTIL_HPP
#define MAPNIK_GEOM_UTIL_HPP

// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/vertex.hpp>

// boost
#include <boost/tuple/tuple.hpp>

// stl
#include <cmath>
#include <vector>

namespace mapnik
{
template <typename T>
bool clip_test(T p,T q,double& tmin,double& tmax)
{
    double r(0);
    bool result=true;
    if (p<0.0)
    {
        r=q/p;
        if (r>tmax) result=false;
        else if (r>tmin) tmin=r;
    }
    else if (p>0.0)
    {
        r=q/p;
        if (r<tmin) result=false;
        else if (r<tmax) tmax=r;
    } else if (q<0.0) result=false;
    return result;
}

template <typename T,typename Image>
bool clip_line(T& x0,T& y0,T& x1,T& y1,box2d<T> const& box)
{
    double tmin=0.0;
    double tmax=1.0;
    double dx=x1-x0;
    if (clip_test<double>(-dx,x0,tmin,tmax))
    {
        if (clip_test<double>(dx,box.width()-x0,tmin,tmax))
        {
            double dy=y1-y0;
            if (clip_test<double>(-dy,y0,tmin,tmax))
            {
                if (clip_test<double>(dy,box.height()-y0,tmin,tmax))
                {
                    if (tmax<1.0)
                    {
                        x1=static_cast<T>(x0+tmax*dx);
                        y1=static_cast<T>(y0+tmax*dy);
                    }
                    if (tmin>0.0)
                    {
                        x0+=static_cast<T>(tmin*dx);
                        y0+=static_cast<T>(tmin*dy);
                    }
                    return true;
                }
            }
        }
    }
    return false;
}

template <typename Iter>
inline bool point_inside_path(double x,double y,Iter start,Iter end)
{
    bool inside=false;
    double x0=boost::get<0>(*start);
    double y0=boost::get<1>(*start);

    double x1(0);
    double y1(0);
    while (++start!=end)
    {
        if ( boost::get<2>(*start) == SEG_MOVETO)
        {
            x0 = boost::get<0>(*start);
            y0 = boost::get<1>(*start);
            continue;
        }
        x1=boost::get<0>(*start);
        y1=boost::get<1>(*start);

        if ((((y1 <= y) && (y < y0)) ||
             ((y0 <= y) && (y < y1))) &&
            ( x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
            inside=!inside;
        x0=x1;
        y0=y1;
    }
    return inside;
}

inline bool point_in_circle(double x,double y,double cx,double cy,double r)
{
    double dx = x - cx;
    double dy = y - cy;
    double d2 = dx * dx + dy * dy;
    return (d2 <= r * r);
}

template <typename T>
inline T sqr(T x)
{
    return x * x;
}

inline double distance2(double x0,double y0,double x1,double y1)
{
    double dx = x1 - x0;
    double dy = y1 - y0;
    return sqr(dx) + sqr(dy);
}

inline double distance(double x0,double y0, double x1,double y1)
{
    return std::sqrt(distance2(x0,y0,x1,y1));
}

inline double point_to_segment_distance(double x, double y,
                                        double ax, double ay,
                                        double bx, double by)
{
    double len2 = distance2(ax,ay,bx,by);

    if (len2 < 1e-14)
    {
        return distance(x,y,ax,ay);
    }

    double r = ((x - ax)*(bx - ax) + (y - ay)*(by -ay))/len2;
    if ( r < 0 )
    {
        return distance(x,y,ax,ay);
    }
    else if (r > 1)
    {
        return distance(x,y,bx,by);
    }
    double s = ((ay - y)*(bx - ax) - (ax - x)*(by - ay))/len2;
    return std::fabs(s) * std::sqrt(len2);
}

template <typename Iter>
inline bool point_on_path(double x,double y,Iter start,Iter end, double tol)
{
    double x0=boost::get<0>(*start);
    double y0=boost::get<1>(*start);
    double x1(0);
    double y1(0);
    while (++start != end)
    {
        if ( boost::get<2>(*start) == SEG_MOVETO)
        {
            x0 = boost::get<0>(*start);
            y0 = boost::get<1>(*start);
            continue;
        }
        x1=boost::get<0>(*start);
        y1=boost::get<1>(*start);

        double distance = point_to_segment_distance(x,y,x0,y0,x1,y1);
        if (distance < tol)
            return true;
        x0=x1;
        y0=y1;
    }
    return false;
}

// filters
struct filter_in_box
{
    box2d<double> box_;
    explicit filter_in_box(const box2d<double>& box)
        : box_(box) {}

    bool pass(const box2d<double>& extent) const
    {
        return extent.intersects(box_);
    }
};

struct filter_at_point
{
    coord2d pt_;
    explicit filter_at_point(const coord2d& pt)
        : pt_(pt) {}
    bool pass(const box2d<double>& extent) const
    {
        return extent.contains(pt_);
    }
};

////////////////////////////////////////////////////////////////////////////
template <typename PathType>
double path_length(PathType & path)
{
    double x0(0);
    double y0(0);
    double x1(0);
    double y1(0);
    path.rewind(0);
    unsigned command = path.vertex(&x0,&y0);
    if (command == SEG_END) return 0;
    double length = 0;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        length += distance(x0,y0,x1,y1);
        x0 = x1;
        y0 = y1;
    }
    return length;
}

template <typename PathType>
bool middle_point(PathType & path, double & x, double & y)
{
    double x0(0);
    double y0(0);
    double x1(0);
    double y1(0);
    double mid_length = 0.5 * path_length(path);
    path.rewind(0);
    unsigned command = path.vertex(&x0,&y0);
    if (command == SEG_END) return false;
    double dist = 0.0;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        double seg_length = distance(x0, y0, x1, y1);

        if ( dist + seg_length >= mid_length)
        {
            double r = (mid_length - dist)/seg_length;
            x = x0 + (x1 - x0) * r;
            y = y0 + (y1 - y0) * r;
            break;
        }
        dist += seg_length;
        x0 = x1;
        y0 = y1;
    }
    return true;
}

namespace label {

template <typename PathType>
bool centroid(PathType & path, double & x, double & y)
{
    double x0(0);
    double y0(0);
    double x1(0);
    double y1(0);
    double start_x;
    double start_y;

    path.rewind(0);
    unsigned command = path.vertex(&x0, &y0);
    if (command == SEG_END) return false;

    start_x = x0;
    start_y = y0;

    double atmp = 0;
    double xtmp = 0;
    double ytmp = 0;

    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        double dx0 = x0 - start_x;
        double dy0 = y0 - start_y;
        double dx1 = x1 - start_x;
        double dy1 = y1 - start_y;

        double ai = dx0 * dy1 - dx1 * dy0;
        atmp += ai;
        xtmp += (dx1 + dx0) * ai;
        ytmp += (dy1 + dy0) * ai;
        x0 = x1;
        y0 = y1;
    }

    if (atmp != 0)
    {
        x = (xtmp/(3*atmp)) + start_x;
        y = (ytmp/(3*atmp)) + start_y;
    }
    else
    {
        x = x0;
        y = y0;
    }
    return true;
}

template <typename PathType>
bool hit_test(PathType & path, double x, double y, double tol)
{
    bool inside=false;
    double x0(0);
    double y0(0);
    double x1(0);
    double y1(0);
    path.rewind(0);
    unsigned command = path.vertex(&x0, &y0);
    if (command == SEG_END) return false;
    unsigned count = 0;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        ++count;
        if (command == SEG_MOVETO)
        {
            x0 = x1;
            y0 = y1;
            continue;
        }
        if ((((y1 <= y) && (y < y0)) ||
             ((y0 <= y) && (y < y1))) &&
            (x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
            inside=!inside;

        x0 = x1;
        y0 = y1;
    }

    if (count == 0) // one vertex
    {
        return distance(x, y, x0, y0) <= fabs(tol);
    }
    return inside;
}

template <typename PathType>
void interior_position(PathType & path, double & x, double & y)
{
    // start with the centroid
    label::centroid(path, x,y);

    // if we are not a polygon, or the default is within the polygon we are done
    if (hit_test(path,x,y,0.001))
        return;

    // otherwise we find a horizontal line across the polygon and then return the
    // center of the widest intersection between the polygon and the line.

    std::vector<double> intersections; // only need to store the X as we know the y

    double x0 = 0;
    double y0 = 0;
    path.rewind(0);
    unsigned command = path.vertex(&x0, &y0);
    double x1 = 0;
    double y1 = 0;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        if (command != SEG_MOVETO)
        {
            // if the segments overlap
            if (y0==y1)
            {
                if (y0==y)
                {
                    double xi = (x0+x1)/2.0;
                    intersections.push_back(xi);
                }
            }
            // if the path segment crosses the bisector
            else if ((y0 <= y && y1 >= y) ||
                     (y0 >= y && y1 <= y))
            {
                // then calculate the intersection
                double xi = x0;
                if (x0 != x1)
                {
                    double m = (y1-y0)/(x1-x0);
                    double c = y0 - m*x0;
                    xi = (y-c)/m;
                }

                intersections.push_back(xi);
            }
        }
        x0 = x1;
        y0 = y1;
    }
    // no intersections we just return the default
    if (intersections.empty())
        return;
    x0=intersections[0];
    double max_width = 0;
    for (unsigned ii = 1; ii < intersections.size(); ++ii)
    {
        double x1=intersections[ii];
        double xc=(x0+x1)/2.0;
        double width = std::fabs(x1-x0);
        if (width > max_width && hit_test(path,xc,y,0))
        {
            x=xc;
            max_width = width;
            break;
        }
    }
}

}}

#endif // MAPNIK_GEOM_UTIL_HPP
<commit_msg>+ centroid: return first vertex if num_vertices == 1<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_GEOM_UTIL_HPP
#define MAPNIK_GEOM_UTIL_HPP

// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/vertex.hpp>

// boost
#include <boost/tuple/tuple.hpp>

// stl
#include <cmath>
#include <vector>

namespace mapnik
{
template <typename T>
bool clip_test(T p,T q,double& tmin,double& tmax)
{
    double r(0);
    bool result=true;
    if (p<0.0)
    {
        r=q/p;
        if (r>tmax) result=false;
        else if (r>tmin) tmin=r;
    }
    else if (p>0.0)
    {
        r=q/p;
        if (r<tmin) result=false;
        else if (r<tmax) tmax=r;
    } else if (q<0.0) result=false;
    return result;
}

template <typename T,typename Image>
bool clip_line(T& x0,T& y0,T& x1,T& y1,box2d<T> const& box)
{
    double tmin=0.0;
    double tmax=1.0;
    double dx=x1-x0;
    if (clip_test<double>(-dx,x0,tmin,tmax))
    {
        if (clip_test<double>(dx,box.width()-x0,tmin,tmax))
        {
            double dy=y1-y0;
            if (clip_test<double>(-dy,y0,tmin,tmax))
            {
                if (clip_test<double>(dy,box.height()-y0,tmin,tmax))
                {
                    if (tmax<1.0)
                    {
                        x1=static_cast<T>(x0+tmax*dx);
                        y1=static_cast<T>(y0+tmax*dy);
                    }
                    if (tmin>0.0)
                    {
                        x0+=static_cast<T>(tmin*dx);
                        y0+=static_cast<T>(tmin*dy);
                    }
                    return true;
                }
            }
        }
    }
    return false;
}

template <typename Iter>
inline bool point_inside_path(double x,double y,Iter start,Iter end)
{
    bool inside=false;
    double x0=boost::get<0>(*start);
    double y0=boost::get<1>(*start);

    double x1(0);
    double y1(0);
    while (++start!=end)
    {
        if ( boost::get<2>(*start) == SEG_MOVETO)
        {
            x0 = boost::get<0>(*start);
            y0 = boost::get<1>(*start);
            continue;
        }
        x1=boost::get<0>(*start);
        y1=boost::get<1>(*start);

        if ((((y1 <= y) && (y < y0)) ||
             ((y0 <= y) && (y < y1))) &&
            ( x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
            inside=!inside;
        x0=x1;
        y0=y1;
    }
    return inside;
}

inline bool point_in_circle(double x,double y,double cx,double cy,double r)
{
    double dx = x - cx;
    double dy = y - cy;
    double d2 = dx * dx + dy * dy;
    return (d2 <= r * r);
}

template <typename T>
inline T sqr(T x)
{
    return x * x;
}

inline double distance2(double x0,double y0,double x1,double y1)
{
    double dx = x1 - x0;
    double dy = y1 - y0;
    return sqr(dx) + sqr(dy);
}

inline double distance(double x0,double y0, double x1,double y1)
{
    return std::sqrt(distance2(x0,y0,x1,y1));
}

inline double point_to_segment_distance(double x, double y,
                                        double ax, double ay,
                                        double bx, double by)
{
    double len2 = distance2(ax,ay,bx,by);

    if (len2 < 1e-14)
    {
        return distance(x,y,ax,ay);
    }

    double r = ((x - ax)*(bx - ax) + (y - ay)*(by -ay))/len2;
    if ( r < 0 )
    {
        return distance(x,y,ax,ay);
    }
    else if (r > 1)
    {
        return distance(x,y,bx,by);
    }
    double s = ((ay - y)*(bx - ax) - (ax - x)*(by - ay))/len2;
    return std::fabs(s) * std::sqrt(len2);
}

template <typename Iter>
inline bool point_on_path(double x,double y,Iter start,Iter end, double tol)
{
    double x0=boost::get<0>(*start);
    double y0=boost::get<1>(*start);
    double x1(0);
    double y1(0);
    while (++start != end)
    {
        if ( boost::get<2>(*start) == SEG_MOVETO)
        {
            x0 = boost::get<0>(*start);
            y0 = boost::get<1>(*start);
            continue;
        }
        x1=boost::get<0>(*start);
        y1=boost::get<1>(*start);

        double distance = point_to_segment_distance(x,y,x0,y0,x1,y1);
        if (distance < tol)
            return true;
        x0=x1;
        y0=y1;
    }
    return false;
}

// filters
struct filter_in_box
{
    box2d<double> box_;
    explicit filter_in_box(const box2d<double>& box)
        : box_(box) {}

    bool pass(const box2d<double>& extent) const
    {
        return extent.intersects(box_);
    }
};

struct filter_at_point
{
    coord2d pt_;
    explicit filter_at_point(const coord2d& pt)
        : pt_(pt) {}
    bool pass(const box2d<double>& extent) const
    {
        return extent.contains(pt_);
    }
};

////////////////////////////////////////////////////////////////////////////
template <typename PathType>
double path_length(PathType & path)
{
    double x0(0);
    double y0(0);
    double x1(0);
    double y1(0);
    path.rewind(0);
    unsigned command = path.vertex(&x0,&y0);
    if (command == SEG_END) return 0;
    double length = 0;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        length += distance(x0,y0,x1,y1);
        x0 = x1;
        y0 = y1;
    }
    return length;
}

template <typename PathType>
bool middle_point(PathType & path, double & x, double & y)
{
    double x0(0);
    double y0(0);
    double x1(0);
    double y1(0);
    double mid_length = 0.5 * path_length(path);
    path.rewind(0);
    unsigned command = path.vertex(&x0,&y0);
    if (command == SEG_END) return false;
    double dist = 0.0;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        double seg_length = distance(x0, y0, x1, y1);

        if ( dist + seg_length >= mid_length)
        {
            double r = (mid_length - dist)/seg_length;
            x = x0 + (x1 - x0) * r;
            y = y0 + (y1 - y0) * r;
            break;
        }
        dist += seg_length;
        x0 = x1;
        y0 = y1;
    }
    return true;
}

namespace label {

template <typename PathType>
bool centroid(PathType & path, double & x, double & y)
{
    double x0 = 0;
    double y0 = 0;
    double x1 = 0;
    double y1 = 0;
    double start_x;
    double start_y;

    path.rewind(0);
    unsigned command = path.vertex(&x0, &y0);
    if (command == SEG_END) return false;

    start_x = x0;
    start_y = y0;

    double atmp = 0;
    double xtmp = 0;
    double ytmp = 0;
    unsigned count = 1;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        double dx0 = x0 - start_x;
        double dy0 = y0 - start_y;
        double dx1 = x1 - start_x;
        double dy1 = y1 - start_y;

        double ai = dx0 * dy1 - dx1 * dy0;
        atmp += ai;
        xtmp += (dx1 + dx0) * ai;
        ytmp += (dy1 + dy0) * ai;
        x0 = x1;
        y0 = y1;
        ++count;
    }

    if (count == 1)
    {
        x = start_x;
        y = start_y;
        return true;
    }

    if (atmp != 0)
    {
        x = (xtmp/(3*atmp)) + start_x;
        y = (ytmp/(3*atmp)) + start_y;
    }
    else
    {
        x = x0;
        y = y0;
    }
    return true;
}

template <typename PathType>
bool hit_test(PathType & path, double x, double y, double tol)
{
    bool inside=false;
    double x0(0);
    double y0(0);
    double x1(0);
    double y1(0);
    path.rewind(0);
    unsigned command = path.vertex(&x0, &y0);
    if (command == SEG_END) return false;
    unsigned count = 0;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        ++count;
        if (command == SEG_MOVETO)
        {
            x0 = x1;
            y0 = y1;
            continue;
        }
        if ((((y1 <= y) && (y < y0)) ||
             ((y0 <= y) && (y < y1))) &&
            (x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
            inside=!inside;

        x0 = x1;
        y0 = y1;
    }

    if (count == 0) // one vertex
    {
        return distance(x, y, x0, y0) <= fabs(tol);
    }
    return inside;
}

template <typename PathType>
void interior_position(PathType & path, double & x, double & y)
{
    // start with the centroid
    label::centroid(path, x,y);

    // if we are not a polygon, or the default is within the polygon we are done
    if (hit_test(path,x,y,0.001))
        return;

    // otherwise we find a horizontal line across the polygon and then return the
    // center of the widest intersection between the polygon and the line.

    std::vector<double> intersections; // only need to store the X as we know the y

    double x0 = 0;
    double y0 = 0;
    path.rewind(0);
    unsigned command = path.vertex(&x0, &y0);
    double x1 = 0;
    double y1 = 0;
    while (SEG_END != (command = path.vertex(&x1, &y1)))
    {
        if (command != SEG_MOVETO)
        {
            // if the segments overlap
            if (y0==y1)
            {
                if (y0==y)
                {
                    double xi = (x0+x1)/2.0;
                    intersections.push_back(xi);
                }
            }
            // if the path segment crosses the bisector
            else if ((y0 <= y && y1 >= y) ||
                     (y0 >= y && y1 <= y))
            {
                // then calculate the intersection
                double xi = x0;
                if (x0 != x1)
                {
                    double m = (y1-y0)/(x1-x0);
                    double c = y0 - m*x0;
                    xi = (y-c)/m;
                }

                intersections.push_back(xi);
            }
        }
        x0 = x1;
        y0 = y1;
    }
    // no intersections we just return the default
    if (intersections.empty())
        return;
    x0=intersections[0];
    double max_width = 0;
    for (unsigned ii = 1; ii < intersections.size(); ++ii)
    {
        double x1=intersections[ii];
        double xc=(x0+x1)/2.0;
        double width = std::fabs(x1-x0);
        if (width > max_width && hit_test(path,xc,y,0))
        {
            x=xc;
            max_width = width;
            break;
        }
    }
}

}}

#endif // MAPNIK_GEOM_UTIL_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: implsprite.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 21:02:15 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CPPCANVAS_IMPLSPRITE_HXX
#define _CPPCANVAS_IMPLSPRITE_HXX

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XSPRITECANVAS_HPP_
#include <drafts/com/sun/star/rendering/XSpriteCanvas.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XSPRITE_HPP_
#include <drafts/com/sun/star/rendering/XSprites.hpp>
#endif

#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

#ifndef _CPPCANVAS_SPRITE_HXX
#include <cppcanvas/sprite.hxx>
#endif

#include <implspritecanvas.hxx>

namespace cppcanvas
{
    namespace internal
    {
        class ImplSprite : public virtual Sprite
        {
        public:
            ImplSprite( const ::com::sun::star::uno::Reference<
                                  ::drafts::com::sun::star::rendering::XSpriteCanvas >&     rParentCanvas,
                        const ::com::sun::star::uno::Reference<
                                  ::drafts::com::sun::star::rendering::XSprite >&       rSprite,
                        const ImplSpriteCanvas::TransformationArbiterSharedPtr&         rTransformArbiter );
            ImplSprite( const ::com::sun::star::uno::Reference<
                                  ::drafts::com::sun::star::rendering::XSpriteCanvas >&     rParentCanvas,
                        const ::com::sun::star::uno::Reference<
                                  ::drafts::com::sun::star::rendering::XAnimatedSprite >& rSprite,
                        const ImplSpriteCanvas::TransformationArbiterSharedPtr&         rTransformArbiter );
            virtual ~ImplSprite();

            virtual void setAlpha( const double& rAlpha );
            virtual void movePixel( const ::basegfx::B2DPoint& rNewPos );
            virtual void move( const ::basegfx::B2DPoint& rNewPos );
            virtual void transform( const ::basegfx::B2DHomMatrix& rMatrix );
            virtual void setClipPixel( const ::basegfx::B2DPolyPolygon& rClipPoly );
            virtual void setClip( const ::basegfx::B2DPolyPolygon& rClipPoly );

            virtual void show();
            virtual void hide();

            virtual ::com::sun::star::uno::Reference<
                ::drafts::com::sun::star::rendering::XSprite >  getUNOSprite() const;

            ::com::sun::star::uno::Reference<
                ::drafts::com::sun::star::rendering::XGraphicDevice >
                                                                getGraphicDevice() const;

        private:
            // default: disabled copy/assignment
            ImplSprite(const ImplSprite&);
            ImplSprite& operator=( const ImplSprite& );

            ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XGraphicDevice >         mxGraphicDevice;
            const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XSprite >          mxSprite;
            const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::rendering::XAnimatedSprite >  mxAnimatedSprite;
            ImplSpriteCanvas::TransformationArbiterSharedPtr                                                mpTransformArbiter;
        };
    }
}

#endif /* _CPPCANVAS_IMPLSPRITE_HXX */
<commit_msg>INTEGRATION: CWS presfixes01 (1.4.6); FILE MERGED 2005/02/16 11:14:39 fs 1.4.6.1: #i42558# drafts.com.sun.star.drawing/rendering/geometry moved to com.sun.star.*<commit_after>/*************************************************************************
 *
 *  $RCSfile: implsprite.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-10 13:31:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CPPCANVAS_IMPLSPRITE_HXX
#define _CPPCANVAS_IMPLSPRITE_HXX

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_RENDERING_XSPRITECANVAS_HPP_
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
#endif
#ifndef _COM_SUN_STAR_RENDERING_XSPRITE_HPP_
#include <com.sun.star.rendering.XSprites.hpp>
#endif

#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#endif

#ifndef _CPPCANVAS_SPRITE_HXX
#include <cppcanvas/sprite.hxx>
#endif

#include <implspritecanvas.hxx>

namespace cppcanvas
{
    namespace internal
    {
        class ImplSprite : public virtual Sprite
        {
        public:
            ImplSprite( const ::com::sun::star::uno::Reference<
                                  ::com::sun::star::rendering::XSpriteCanvas >&     rParentCanvas,
                        const ::com::sun::star::uno::Reference<
                                  ::com::sun::star::rendering::XSprite >&       rSprite,
                        const ImplSpriteCanvas::TransformationArbiterSharedPtr&         rTransformArbiter );
            ImplSprite( const ::com::sun::star::uno::Reference<
                                  ::com::sun::star::rendering::XSpriteCanvas >&     rParentCanvas,
                        const ::com::sun::star::uno::Reference<
                                  ::com::sun::star::rendering::XAnimatedSprite >& rSprite,
                        const ImplSpriteCanvas::TransformationArbiterSharedPtr&         rTransformArbiter );
            virtual ~ImplSprite();

            virtual void setAlpha( const double& rAlpha );
            virtual void movePixel( const ::basegfx::B2DPoint& rNewPos );
            virtual void move( const ::basegfx::B2DPoint& rNewPos );
            virtual void transform( const ::basegfx::B2DHomMatrix& rMatrix );
            virtual void setClipPixel( const ::basegfx::B2DPolyPolygon& rClipPoly );
            virtual void setClip( const ::basegfx::B2DPolyPolygon& rClipPoly );

            virtual void show();
            virtual void hide();

            virtual ::com::sun::star::uno::Reference<
                ::com::sun::star::rendering::XSprite >  getUNOSprite() const;

            ::com::sun::star::uno::Reference<
                ::com::sun::star::rendering::XGraphicDevice >
                                                                getGraphicDevice() const;

        private:
            // default: disabled copy/assignment
            ImplSprite(const ImplSprite&);
            ImplSprite& operator=( const ImplSprite& );

            ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XGraphicDevice >         mxGraphicDevice;
            const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XSprite >          mxSprite;
            const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XAnimatedSprite >  mxAnimatedSprite;
            ImplSpriteCanvas::TransformationArbiterSharedPtr                                                mpTransformArbiter;
        };
    }
}

#endif /* _CPPCANVAS_IMPLSPRITE_HXX */
<|endoftext|>


<commit_before>///
/// @file   Wheel.hpp
/// @brief  Wheel factorization is used to skip multiles of
///         small primes in the sieve of Eratosthenes.
///
/// Copyright (C) 2020 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef WHEEL_HPP
#define WHEEL_HPP

#include "Bucket.hpp"

#include <stdint.h>
#include <algorithm>
#include <cassert>

namespace primesieve {

/// The WheelInit data structure is used to calculate the
/// first multiple >= start of each sieving prime
///
struct WheelInit
{
  uint8_t nextMultipleFactor;
  uint8_t wheelIndex;
};

extern const WheelInit wheel30Init[30];
extern const WheelInit wheel210Init[210];

/// The WheelElement data structure is used to skip multiples
/// of small primes using wheel factorization
///
struct WheelElement
{
  /// Bitmask used to unset the bit corresponding to the current
  /// multiple of a SievingPrime object
  uint8_t unsetBit;
  /// Factor used to calculate the next multiple of a sieving prime
  /// that is not divisible by any of the wheel factors
  uint8_t nextMultipleFactor;
  /// Overflow needed to correct the next multiple index
  /// (due to sievingPrime = prime / 30)
  uint8_t correct;
  /// Used to calculate the next wheel index:
  /// wheelIndex += next;
  int8_t next;
};

extern const WheelElement wheel30[8*8];
extern const WheelElement wheel210[48*8];

/// The abstract Wheel class is used skip multiples of small
/// primes in the sieve of Eratosthenes. The EratSmall,
/// EratMedium and EratBig classes are derived from Wheel.
///
template <int MODULO, int SIZE, const WheelElement* WHEEL, const WheelInit* INIT>
class Wheel
{
public:
  /// Add a new sieving prime to the sieving algorithm.
  /// Calculate the first multiple > segmentLow of prime and
  /// the position within the sieve array of that multiple
  /// and its wheel index. When done store the sieving prime.
  ///
  void addSievingPrime(uint64_t prime, uint64_t segmentLow)
  {
    assert(segmentLow % 30 == 0);

    // This hack is required because in primesieve the 8
    // bits of each byte (of the sieve array) correspond to
    // the offsets { 7, 11, 13, 17, 19, 23, 29, 31 }.
    // So we are looking for: multiples > segmentLow + 6.
    segmentLow += 6;

    // calculate the first multiple (of prime) > segmentLow
    uint64_t quotient = (segmentLow / prime) + 1;
    quotient = std::max(prime, quotient);
    uint64_t multiple = prime * quotient;
    // prime not needed for sieving
    if (multiple > stop_ ||
        multiple < segmentLow)
      return;

    // calculate the next multiple of prime that is not
    // divisible by any of the wheel's factors
    uint64_t nextMultipleFactor = INIT[quotient % MODULO].nextMultipleFactor;
    uint64_t nextMultiple = prime * nextMultipleFactor;
    if (nextMultiple > stop_ - multiple)
      return;

    nextMultiple += multiple - segmentLow;
    uint64_t multipleIndex = nextMultiple / 30;
    uint64_t wheelIndex = wheelOffsets_[prime % 30] + INIT[quotient % MODULO].wheelIndex;
    storeSievingPrime(prime, multipleIndex, wheelIndex);
  }

protected:
  uint64_t stop_ = 0;
  virtual ~Wheel() = default;
  virtual void storeSievingPrime(uint64_t, uint64_t, uint64_t) = 0;

  static uint64_t getMaxFactor()
  {
    return WHEEL[0].nextMultipleFactor;
  }

  /// Cross-off the current multiple of sievingPrime
  /// and calculate its next multiple
  ///
  static void unsetBit(uint8_t* sieve,
                       uint64_t sievingPrime,
                       uint64_t* multipleIndex,
                       uint64_t* wheelIndex)
  {
    sieve[*multipleIndex] &= WHEEL[*wheelIndex].unsetBit;
    *multipleIndex        += WHEEL[*wheelIndex].nextMultipleFactor * sievingPrime;
    *multipleIndex        += WHEEL[*wheelIndex].correct;
    *wheelIndex           += WHEEL[*wheelIndex].next;
  }

private:
  static const uint64_t wheelOffsets_[30];
};

template <int MODULO, int SIZE, const WheelElement* WHEEL, const WheelInit* INIT>
const uint64_t
Wheel<MODULO, SIZE, WHEEL, INIT>::wheelOffsets_[30] =
{
  0, SIZE * 7, 0, 0, 0, 0,
  0, SIZE * 0, 0, 0, 0, SIZE * 1,
  0, SIZE * 2, 0, 0, 0, SIZE * 3,
  0, SIZE * 4, 0, 0, 0, SIZE * 5,
  0, 0,        0, 0, 0, SIZE * 6
};

/// 3rd wheel, skips multiples of 2, 3 and 5
using Wheel30_t = Wheel<30, 8, wheel30, wheel30Init>;

/// 4th wheel, skips multiples of 2, 3, 5 and 7
using Wheel210_t = Wheel<210, 48, wheel210, wheel210Init>;

} // namespace

#endif
<commit_msg>Remove unused header<commit_after>///
/// @file   Wheel.hpp
/// @brief  Wheel factorization is used to skip multiles of
///         small primes in the sieve of Eratosthenes.
///
/// Copyright (C) 2020 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef WHEEL_HPP
#define WHEEL_HPP

#include <stdint.h>
#include <algorithm>
#include <cassert>

namespace primesieve {

/// The WheelInit data structure is used to calculate the
/// first multiple >= start of each sieving prime
///
struct WheelInit
{
  uint8_t nextMultipleFactor;
  uint8_t wheelIndex;
};

extern const WheelInit wheel30Init[30];
extern const WheelInit wheel210Init[210];

/// The WheelElement data structure is used to skip multiples
/// of small primes using wheel factorization
///
struct WheelElement
{
  /// Bitmask used to unset the bit corresponding to the current
  /// multiple of a SievingPrime object
  uint8_t unsetBit;
  /// Factor used to calculate the next multiple of a sieving prime
  /// that is not divisible by any of the wheel factors
  uint8_t nextMultipleFactor;
  /// Overflow needed to correct the next multiple index
  /// (due to sievingPrime = prime / 30)
  uint8_t correct;
  /// Used to calculate the next wheel index:
  /// wheelIndex += next;
  int8_t next;
};

extern const WheelElement wheel30[8*8];
extern const WheelElement wheel210[48*8];

/// The abstract Wheel class is used skip multiples of small
/// primes in the sieve of Eratosthenes. The EratSmall,
/// EratMedium and EratBig classes are derived from Wheel.
///
template <int MODULO, int SIZE, const WheelElement* WHEEL, const WheelInit* INIT>
class Wheel
{
public:
  /// Add a new sieving prime to the sieving algorithm.
  /// Calculate the first multiple > segmentLow of prime and
  /// the position within the sieve array of that multiple
  /// and its wheel index. When done store the sieving prime.
  ///
  void addSievingPrime(uint64_t prime, uint64_t segmentLow)
  {
    assert(segmentLow % 30 == 0);

    // This hack is required because in primesieve the 8
    // bits of each byte (of the sieve array) correspond to
    // the offsets { 7, 11, 13, 17, 19, 23, 29, 31 }.
    // So we are looking for: multiples > segmentLow + 6.
    segmentLow += 6;

    // calculate the first multiple (of prime) > segmentLow
    uint64_t quotient = (segmentLow / prime) + 1;
    quotient = std::max(prime, quotient);
    uint64_t multiple = prime * quotient;
    // prime not needed for sieving
    if (multiple > stop_ ||
        multiple < segmentLow)
      return;

    // calculate the next multiple of prime that is not
    // divisible by any of the wheel's factors
    uint64_t nextMultipleFactor = INIT[quotient % MODULO].nextMultipleFactor;
    uint64_t nextMultiple = prime * nextMultipleFactor;
    if (nextMultiple > stop_ - multiple)
      return;

    nextMultiple += multiple - segmentLow;
    uint64_t multipleIndex = nextMultiple / 30;
    uint64_t wheelIndex = wheelOffsets_[prime % 30] + INIT[quotient % MODULO].wheelIndex;
    storeSievingPrime(prime, multipleIndex, wheelIndex);
  }

protected:
  uint64_t stop_ = 0;
  virtual ~Wheel() = default;
  virtual void storeSievingPrime(uint64_t, uint64_t, uint64_t) = 0;

  static uint64_t getMaxFactor()
  {
    return WHEEL[0].nextMultipleFactor;
  }

  /// Cross-off the current multiple of sievingPrime
  /// and calculate its next multiple
  ///
  static void unsetBit(uint8_t* sieve,
                       uint64_t sievingPrime,
                       uint64_t* multipleIndex,
                       uint64_t* wheelIndex)
  {
    sieve[*multipleIndex] &= WHEEL[*wheelIndex].unsetBit;
    *multipleIndex        += WHEEL[*wheelIndex].nextMultipleFactor * sievingPrime;
    *multipleIndex        += WHEEL[*wheelIndex].correct;
    *wheelIndex           += WHEEL[*wheelIndex].next;
  }

private:
  static const uint64_t wheelOffsets_[30];
};

template <int MODULO, int SIZE, const WheelElement* WHEEL, const WheelInit* INIT>
const uint64_t
Wheel<MODULO, SIZE, WHEEL, INIT>::wheelOffsets_[30] =
{
  0, SIZE * 7, 0, 0, 0, 0,
  0, SIZE * 0, 0, 0, 0, SIZE * 1,
  0, SIZE * 2, 0, 0, 0, SIZE * 3,
  0, SIZE * 4, 0, 0, 0, SIZE * 5,
  0, 0,        0, 0, 0, SIZE * 6
};

/// 3rd wheel, skips multiples of 2, 3 and 5
using Wheel30_t = Wheel<30, 8, wheel30, wheel30Init>;

/// 4th wheel, skips multiples of 2, 3, 5 and 7
using Wheel210_t = Wheel<210, 48, wheel210, wheel210Init>;

} // namespace

#endif
<|endoftext|>


<commit_before>///
/// @file   pmath.hpp
/// @brief  Auxiliary math functions needed in primesieve.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PMATH_HPP
#define PMATH_HPP

#include <stdint.h>
#include <cmath>
#include <limits>

namespace {

template <typename X, typename Y>
inline X ceilDiv(X x, Y y)
{
  return (X) ((x + y - 1) / y);
}

template <typename T>
inline T numberOfBits(T)
{
  return (T) (sizeof(T) * 8);
}

template <typename T>
inline T isquare(T x)
{
  return x * x;
}

template <typename T>
inline bool isPowerOf2(T x)
{
  return x != 0 && (x & (x - 1)) == 0;
}

template <typename T>
inline T floorPowerOf2(T x)
{
  for (T i = 1; i < numberOfBits(x); i += i)
    x |= (x >> i);
  return x - (x >> 1);
}

template <typename T>
inline T ilog2(T x)
{
  T bits = numberOfBits(x);
  T one = 1;
  T log2 = 0;

  for (T i = bits / 2; i != 0; i /= 2)
  {
    if (x >= (one << i))
    {
      x >>= i;
      log2 += i;
    }
  }

  return log2;
}

/// Integer square root, Newton's method
/// @see book "Hacker's Delight"
///
template <typename T>
inline T isqrt(T x)
{
  if (x <= 1)
    return x;

  T bits = numberOfBits(x);
  T nlz = (bits - 1) - ilog2(x - 1);
  T s = bits / 2 - nlz / 2;
  T one = 1;

  // first guess: least power of 2 >= sqrt(x)
  T g0 = one << s;
  T g1 = (g0 + (x >> s)) >> 1;

  while (g1 < g0)
  {
    g0 = g1;
    g1 = (g0 + (x / g0)) >> 1;
  }

  return g0;
}

/// Returns 2^64-1 if x + y >= 2^64-1
inline uint64_t checkedAdd(uint64_t x, uint64_t y)
{
  if (x >= std::numeric_limits<uint64_t>::max() - y)
    return std::numeric_limits<uint64_t>::max();

  return x + y;
}

/// Returns 0 if x - y <= 0
inline uint64_t checkedSub(uint64_t x, uint64_t y)
{
  return (x > y) ? x - y : 0;
}

template <typename A, typename B, typename C>
inline B inBetween(A min, B x, C max)
{
  if (x < (B) min)
    return (B) min;
  if ((C) x > max)
    return (B) max;

  return x;
}

/// Get an approximation of the maximum prime gap near n
inline uint64_t max_prime_gap(uint64_t n)
{
  double x = (double) n;
  double logx = std::log(x);
  double prime_gap = logx * logx;
  return (uint64_t) prime_gap;
}

} // namespace

#endif
<commit_msg>Fix undefined-behavior<commit_after>///
/// @file   pmath.hpp
/// @brief  Auxiliary math functions needed in primesieve.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PMATH_HPP
#define PMATH_HPP

#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <limits>

namespace {

template <typename X, typename Y>
inline X ceilDiv(X x, Y y)
{
  return (X) ((x + y - 1) / y);
}

template <typename T>
inline T numberOfBits(T)
{
  return (T) (sizeof(T) * 8);
}

template <typename T>
inline T isquare(T x)
{
  return x * x;
}

template <typename T>
inline bool isPowerOf2(T x)
{
  return x != 0 && (x & (x - 1)) == 0;
}

template <typename T>
inline T floorPowerOf2(T x)
{
  for (T i = 1; i < numberOfBits(x); i += i)
    x |= (x >> i);
  return x - (x >> 1);
}

template <typename T>
inline T ilog2(T x)
{
  T bits = numberOfBits(x);
  T one = 1;
  T log2 = 0;

  for (T i = bits / 2; i != 0; i /= 2)
  {
    if (x >= (one << i))
    {
      x >>= i;
      log2 += i;
    }
  }

  return log2;
}

/// Integer square root, Newton's method
/// @see book "Hacker's Delight"
///
template <typename T>
inline T isqrt(T x)
{
  if (x <= 1)
    return x;

  T bits = numberOfBits(x);
  T nlz = (bits - 1) - ilog2(x - 1);
  T s = bits / 2 - nlz / 2;
  T one = 1;

  // first guess: least power of 2 >= sqrt(x)
  T g0 = one << s;
  T g1 = (g0 + (x >> s)) >> 1;

  while (g1 < g0)
  {
    g0 = g1;
    g1 = (g0 + (x / g0)) >> 1;
  }

  return g0;
}

/// Returns 2^64-1 if x + y >= 2^64-1
inline uint64_t checkedAdd(uint64_t x, uint64_t y)
{
  const uint64_t max = std::numeric_limits<uint64_t>::max();

  if (x >= max - y)
    return max;

  return x + y;
}

/// Returns 0 if x - y <= 0
inline uint64_t checkedSub(uint64_t x, uint64_t y)
{
  return (x > y) ? x - y : 0;
}

template <typename A, typename B, typename C>
inline B inBetween(A min, B x, C max)
{
  if (x < (B) min)
    return (B) min;
  if ((C) x > max)
    return (B) max;

  return x;
}

/// Get an approximation of the maximum prime gap near n
inline uint64_t max_prime_gap(uint64_t n)
{
  double x = (double) n;
  x = std::max(1.0, x);
  double logx = std::log(x);
  double prime_gap = logx * logx;
  return (uint64_t) prime_gap;
}

} // namespace

#endif
<|endoftext|>