<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* libmspub
 * Version: MPL 1.1 / GPLv2+ / LGPLv2+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
 *
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
 * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
 * instead of those above.
 */

#include "MSPUBCollector.h"
#include "libmspub_utils.h"
#include "MSPUBConstants.h"
#include "MSPUBTypes.h"

libmspub::MSPUBCollector::MSPUBCollector(libwpg::WPGPaintInterface *painter) :
  m_painter(painter), contentChunkReferences(), m_width(0), m_height(0),
  m_widthSet(false), m_heightSet(false), m_commonPageProperties(),
  m_numPages(0), textStringsById(), pagesBySeqNum(), textShapesBySeqNum(),
  imgShapesBySeqNum(), images(), possibleImageShapes(), colors(), fonts(),
  defaultCharStyles(), defaultParaStyles()
{
}

libmspub::MSPUBCollector::~MSPUBCollector()
{
}

libmspub::ContentChunkReference::ContentChunkReference(libmspub::MSPUBContentChunkType type,
    unsigned long offset, unsigned long end,
    unsigned seqNum, unsigned parentSeqNum) :
  type(type), offset(offset), end(end), seqNum(seqNum), parentSeqNum(parentSeqNum)
{
}

void libmspub::MSPUBCollector::addDefaultCharacterStyle(const CharacterStyle &st)
{
  defaultCharStyles.push_back(st);
}

void libmspub::MSPUBCollector::addDefaultParagraphStyle(const ParagraphStyle &st)
{
  defaultParaStyles.push_back(st);
}

bool libmspub::MSPUBCollector::addPage(unsigned seqNum)
{
  if (! (m_widthSet && m_heightSet) )
  {
    return false;
  }
  MSPUB_DEBUG_MSG(("Adding page of seqnum 0x%x\n", seqNum));
  pagesBySeqNum[seqNum] = PageInfo();
  return true;
}

bool libmspub::MSPUBCollector::addTextShape(unsigned stringId, unsigned seqNum, unsigned pageSeqNum)
{
  std::map<unsigned, PageInfo>::iterator i_page = pagesBySeqNum.find(pageSeqNum);
  if (i_page == pagesBySeqNum.end())
  {
    MSPUB_DEBUG_MSG(("Page of seqnum 0x%x not found in addTextShape!\n", pageSeqNum));
    return false;
  }
  else
  {
    std::map<unsigned, std::vector<TextParagraph> >::iterator i_str = textStringsById.find(stringId);
    if (i_str == textStringsById.end())
    {
      MSPUB_DEBUG_MSG(("Text string of id 0x%x not found in addTextShape!\n", stringId));
      return false;
    }
    else
    {
      std::pair<std::map<unsigned, TextShapeInfo>::iterator, bool> result =
        textShapesBySeqNum.insert(std::pair<const unsigned, TextShapeInfo>(seqNum, TextShapeInfo(i_str->second)));
      if (result.second)
      {
        i_page->second.textShapeReferences.push_back(result.first);
        MSPUB_DEBUG_MSG(("addTextShape succeeded with id 0x%x\n", stringId));
        return true;
      }
      MSPUB_DEBUG_MSG(("already tried to add the text shape of seqnum 0x%x to this page!\n", seqNum));
      return false;
    }
  }
}

bool libmspub::MSPUBCollector::setShapeImgIndex(unsigned seqNum, unsigned index)
{
  MSPUB_DEBUG_MSG(("Setting image index of shape with seqnum 0x%x to 0x%x\n", seqNum, index));
  std::map<unsigned, UnknownShapeInfo>::iterator i = possibleImageShapes.find(seqNum);
  if (i != possibleImageShapes.end())
  {
    i->second.imgIndex = index;
    return true;
  }
  return false;
}

bool libmspub::MSPUBCollector::setShapeCoordinatesInEmu(unsigned seqNum, int xs, int ys, int xe, int ye)
{
  if (! (m_widthSet && m_heightSet))
  {
    return false;
  }
  WPXPropertyList *propsToEdit;
  std::map<unsigned, TextShapeInfo>::iterator elt = textShapesBySeqNum.find(seqNum);
  if (elt != textShapesBySeqNum.end())
  {
    propsToEdit = &(elt->second.props);
  }
  else
  {
    std::map<unsigned, UnknownShapeInfo>::iterator elt = possibleImageShapes.find(seqNum);
    if (elt != possibleImageShapes.end())
    {
      propsToEdit = &(elt->second.props);
    }
    else
    {
      return false;
    }
  }
  double x_center = m_commonPageProperties["svg:width"]->getDouble() / 2;
  double y_center = m_commonPageProperties["svg:height"]->getDouble() / 2;
  propsToEdit->insert("svg:x", x_center + (double)xs / EMUS_IN_INCH);
  propsToEdit->insert("svg:y", y_center + (double)ys / EMUS_IN_INCH);
  propsToEdit->insert("svg:width", (double)(xe - xs) / EMUS_IN_INCH);
  propsToEdit->insert("svg:height", (double)(ye - ys) / EMUS_IN_INCH);
  return true;
}

void libmspub::MSPUBCollector::addFont(std::vector<unsigned char> name)
{
  fonts.push_back(name);
}

void libmspub::MSPUBCollector::assignImages()
{
  for (std::map<unsigned, UnknownShapeInfo>::const_iterator i = possibleImageShapes.begin(); i != possibleImageShapes.end(); ++i)
  {
    if (i->second.imgIndex > 0 && i->second.imgIndex <= images.size())
    {
      std::pair<std::map<unsigned, ImgShapeInfo>::iterator, bool> result =
        imgShapesBySeqNum.insert(std::pair<unsigned, ImgShapeInfo>(i->first, ImgShapeInfo(images[i->second.imgIndex - 1].first, images[i->second.imgIndex - 1].second, i->second.props)));
      if (result.second)
      {
        std::map<unsigned, PageInfo>::iterator i_pg = pagesBySeqNum.find(i->second.pageSeqNum);
        if (i_pg != pagesBySeqNum.end())
        {
          i_pg->second.imgShapeReferences.push_back(result.first);
        }
      }
    }
  }
}

WPXPropertyList libmspub::MSPUBCollector::getParaStyleProps(const ParagraphStyle &style, unsigned defaultParaStyleIndex)
{
  ParagraphStyle _nothing;
  const ParagraphStyle &defaultParaStyle = defaultParaStyleIndex < defaultParaStyles.size() ? defaultParaStyles[defaultParaStyleIndex] : _nothing;
  WPXPropertyList ret;
  Alignment align = style.align >= 0 ? style.align : defaultParaStyle.align;
  switch (align)
  {
  case RIGHT:
    ret.insert("fo:text-align", "right");
    break;
  case CENTER:
    ret.insert("fo:text-align", "center");
    break;
  case JUSTIFY:
    ret.insert("fo:text-align", "justify");
    break;
  case LEFT:
  default:
    ret.insert("fo:text-align", "left");
    break;
  }
  return ret;
}

WPXPropertyList libmspub::MSPUBCollector::getCharStyleProps(const CharacterStyle &style, unsigned defaultCharStyleIndex)
{
  CharacterStyle _nothing = CharacterStyle(false, false, false);
  const CharacterStyle &defaultCharStyle = defaultCharStyleIndex < defaultCharStyles.size() ? defaultCharStyles[defaultCharStyleIndex] : _nothing;
  WPXPropertyList ret;
  if (style.italic)
  {
    ret.insert("fo:font-style", "italic");
  }
  if (style.bold)
  {
    ret.insert("fo:font-weight", "bold");
  }
  if (style.underline)
  {
    ret.insert("style:text-underline-type", "single");
  }
  if (style.textSizeInPt != -1)
  {
    ret.insert("fo:font-size", style.textSizeInPt);
  }
  else if (defaultCharStyle.textSizeInPt != -1)
  {
    ret.insert("fo:font-size", defaultCharStyle.textSizeInPt);
  }
  if (style.colorIndex >= 0 && (size_t)style.colorIndex < colors.size())
  {
    ret.insert("fo:color", getColorString(colors[style.colorIndex]));
  }
  if (style.fontIndex < fonts.size())
  {
    WPXString str;
    appendCharacters(str, fonts[style.fontIndex]);
    ret.insert("style:font-name", str);
  }
  return ret;
}

WPXString libmspub::MSPUBCollector::getColorString(const Color &color)
{
  WPXString ret;
  ret.sprintf("#%.2x%.2x%.2x",(unsigned char)color.r, (unsigned char)color.g, (unsigned char)color.b);
  MSPUB_DEBUG_MSG(("String for r: 0x%x, g: 0x%x, b: 0x%x is %s\n", color.r, color.g, color.b, ret.cstr()));
  return ret;
}

bool libmspub::MSPUBCollector::go()
{
  assignImages();
  for (std::map<unsigned, PageInfo>::const_iterator i = pagesBySeqNum.begin(); i != pagesBySeqNum.end(); ++i)
  {
    m_painter->startGraphics(m_commonPageProperties);
    for (std::vector<std::map<unsigned, TextShapeInfo>::const_iterator>::const_iterator j = i->second.textShapeReferences.begin();
         j != i->second.textShapeReferences.end(); ++j)
    {
      m_painter->startTextObject((*j)->second.props, WPXPropertyListVector());
      for (std::vector<TextParagraph>::const_iterator k = (*j)->second.str.begin(); k != (*j)->second.str.end(); ++k)
      {
        WPXPropertyList paraProps = getParaStyleProps(k->style, k->style.defaultCharStyleIndex);
        m_painter->startTextLine(paraProps);
        for (std::vector<TextSpan>::const_iterator l = k->spans.begin(); l != k->spans.end(); ++l)
        {
          WPXString text;
          appendCharacters(text, l->chars);
          WPXPropertyList charProps = getCharStyleProps(l->style, k->style.defaultCharStyleIndex);
          m_painter->startTextSpan(charProps);
          m_painter->insertText(text);
          m_painter->endTextSpan();
        }
        m_painter->endTextLine();
      }
      m_painter->endTextObject();
    }
    for (std::vector<std::map<unsigned, ImgShapeInfo>::const_iterator>::const_iterator j = i->second.imgShapeReferences.begin();
         j != i->second.imgShapeReferences.end(); ++j)
    {
      m_painter->drawGraphicObject((*j)->second.props, (*j)->second.img);
    }
    m_painter->endGraphics();
  }
  return true;
}

bool libmspub::MSPUBCollector::addTextString(const std::vector<TextParagraph> &str, unsigned id)
{
  MSPUB_DEBUG_MSG(("addTextString, id: 0x%x\n", id));
  textStringsById[id] = str;
  return true; //FIXME: Warn if the string already existed in the map.
}

void libmspub::MSPUBCollector::setWidthInEmu(unsigned long widthInEmu)
{
  //FIXME: Warn if this is called twice
  m_width = widthInEmu;
  m_commonPageProperties.insert("svg:width", ((double)widthInEmu)/EMUS_IN_INCH);
  m_widthSet = true;
}

void libmspub::MSPUBCollector::setHeightInEmu(unsigned long heightInEmu)
{
  //FIXME: Warn if this is called twice
  m_height = heightInEmu;
  m_commonPageProperties.insert("svg:height", ((double)heightInEmu)/EMUS_IN_INCH);
  m_heightSet = true;
}

bool libmspub::MSPUBCollector::addImage(unsigned index, ImgType type, WPXBinaryData img)
{
  MSPUB_DEBUG_MSG(("Image at index %d and of type 0x%x added.\n", index, type));
  while (images.size() < index)
  {
    images.push_back(std::pair<ImgType, WPXBinaryData>(UNKNOWN, WPXBinaryData()));
  }
  images[index - 1] = std::pair<ImgType, WPXBinaryData>(type, img);
  return true;
}

bool libmspub::MSPUBCollector::addShape(unsigned seqNum, unsigned pageSeqNum)
{
  /*std::map<unsigned, unsigned>::const_iterator i_ind = imgIndicesByShapeSeqNum.find(seqNum);
  if (i_ind == imgIndicesByShapeSeqNum.end())
  {
    MSPUB_DEBUG_MSG(("Didn't find which embedded image index corresponds to shape 0x%x before trying to add the shape in addImageShape!\n", seqNum));
    return false;
  }
  unsigned imgIndex = i_ind->second;
  std::map<unsigned, PageInfo>::iterator i_page = pagesBySeqNum.find(pageSeqNum);
  if (i_page == pagesBySeqNum.end())
  {
    MSPUB_DEBUG_MSG(("Page of seqnum 0x%x not found in addImageShape!\n", pageSeqNum));
    return false;
  }
  if (imgIndex > images.size() || images[imgIndex - 1].first == UNKNOWN)
  {
    MSPUB_DEBUG_MSG(("Valid image of index %d not found in addImageShape!\n", imgIndex));
    return false;
  }
  std::pair<std::map<unsigned, ImgShapeInfo>::const_iterator, bool> result = imgShapesBySeqNum.insert(std::pair<const unsigned, ImgShapeInfo>(seqNum, ImgShapeInfo(images[imgIndex - 1].first, images[imgIndex - 1].second)));
  if (result.second)
  {
    i_page->second.imgShapeReferences.push_back(result.first);
    MSPUB_DEBUG_MSG(("addImageShape succeeded with id 0x%x", imgIndex));
    return true;
  }
  MSPUB_DEBUG_MSG(("already tried to add the image shape of seqnum 0x%x to this page!\n", seqNum));
  return false;*/
  possibleImageShapes.insert(std::pair<unsigned, UnknownShapeInfo>(seqNum, UnknownShapeInfo(pageSeqNum)));
  return true;
}

void libmspub::MSPUBCollector::addColor(unsigned char r, unsigned char g, unsigned char b)
{
  colors.push_back(Color(r, g, b));
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>Fixed a bug causing blank dummy pages to be generated.<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* libmspub
 * Version: MPL 1.1 / GPLv2+ / LGPLv2+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * Copyright (C) 2012 Fridrich Strba <fridrich.strba@bluewin.ch>
 *
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPLv2+"), or
 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
 * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable
 * instead of those above.
 */

#include "MSPUBCollector.h"
#include "libmspub_utils.h"
#include "MSPUBConstants.h"
#include "MSPUBTypes.h"

libmspub::MSPUBCollector::MSPUBCollector(libwpg::WPGPaintInterface *painter) :
  m_painter(painter), contentChunkReferences(), m_width(0), m_height(0),
  m_widthSet(false), m_heightSet(false), m_commonPageProperties(),
  m_numPages(0), textStringsById(), pagesBySeqNum(), textShapesBySeqNum(),
  imgShapesBySeqNum(), images(), possibleImageShapes(), colors(), fonts(),
  defaultCharStyles(), defaultParaStyles()
{
}

libmspub::MSPUBCollector::~MSPUBCollector()
{
}

libmspub::ContentChunkReference::ContentChunkReference(libmspub::MSPUBContentChunkType type,
    unsigned long offset, unsigned long end,
    unsigned seqNum, unsigned parentSeqNum) :
  type(type), offset(offset), end(end), seqNum(seqNum), parentSeqNum(parentSeqNum)
{
}

void libmspub::MSPUBCollector::addDefaultCharacterStyle(const CharacterStyle &st)
{
  defaultCharStyles.push_back(st);
}

void libmspub::MSPUBCollector::addDefaultParagraphStyle(const ParagraphStyle &st)
{
  defaultParaStyles.push_back(st);
}

bool libmspub::MSPUBCollector::addPage(unsigned seqNum)
{
  if (! (m_widthSet && m_heightSet) )
  {
    return false;
  }
  MSPUB_DEBUG_MSG(("Adding page of seqnum 0x%x\n", seqNum));
  pagesBySeqNum[seqNum] = PageInfo();
  return true;
}

bool libmspub::MSPUBCollector::addTextShape(unsigned stringId, unsigned seqNum, unsigned pageSeqNum)
{
  std::map<unsigned, PageInfo>::iterator i_page = pagesBySeqNum.find(pageSeqNum);
  if (i_page == pagesBySeqNum.end())
  {
    MSPUB_DEBUG_MSG(("Page of seqnum 0x%x not found in addTextShape!\n", pageSeqNum));
    return false;
  }
  else
  {
    std::map<unsigned, std::vector<TextParagraph> >::iterator i_str = textStringsById.find(stringId);
    if (i_str == textStringsById.end())
    {
      MSPUB_DEBUG_MSG(("Text string of id 0x%x not found in addTextShape!\n", stringId));
      return false;
    }
    else
    {
      std::pair<std::map<unsigned, TextShapeInfo>::iterator, bool> result =
        textShapesBySeqNum.insert(std::pair<const unsigned, TextShapeInfo>(seqNum, TextShapeInfo(i_str->second)));
      if (result.second)
      {
        i_page->second.textShapeReferences.push_back(result.first);
        MSPUB_DEBUG_MSG(("addTextShape succeeded with id 0x%x\n", stringId));
        return true;
      }
      MSPUB_DEBUG_MSG(("already tried to add the text shape of seqnum 0x%x to this page!\n", seqNum));
      return false;
    }
  }
}

bool libmspub::MSPUBCollector::setShapeImgIndex(unsigned seqNum, unsigned index)
{
  MSPUB_DEBUG_MSG(("Setting image index of shape with seqnum 0x%x to 0x%x\n", seqNum, index));
  std::map<unsigned, UnknownShapeInfo>::iterator i = possibleImageShapes.find(seqNum);
  if (i != possibleImageShapes.end())
  {
    i->second.imgIndex = index;
    return true;
  }
  return false;
}

bool libmspub::MSPUBCollector::setShapeCoordinatesInEmu(unsigned seqNum, int xs, int ys, int xe, int ye)
{
  if (! (m_widthSet && m_heightSet))
  {
    return false;
  }
  WPXPropertyList *propsToEdit;
  std::map<unsigned, TextShapeInfo>::iterator elt = textShapesBySeqNum.find(seqNum);
  if (elt != textShapesBySeqNum.end())
  {
    propsToEdit = &(elt->second.props);
  }
  else
  {
    std::map<unsigned, UnknownShapeInfo>::iterator elt = possibleImageShapes.find(seqNum);
    if (elt != possibleImageShapes.end())
    {
      propsToEdit = &(elt->second.props);
    }
    else
    {
      return false;
    }
  }
  double x_center = m_commonPageProperties["svg:width"]->getDouble() / 2;
  double y_center = m_commonPageProperties["svg:height"]->getDouble() / 2;
  propsToEdit->insert("svg:x", x_center + (double)xs / EMUS_IN_INCH);
  propsToEdit->insert("svg:y", y_center + (double)ys / EMUS_IN_INCH);
  propsToEdit->insert("svg:width", (double)(xe - xs) / EMUS_IN_INCH);
  propsToEdit->insert("svg:height", (double)(ye - ys) / EMUS_IN_INCH);
  return true;
}

void libmspub::MSPUBCollector::addFont(std::vector<unsigned char> name)
{
  fonts.push_back(name);
}

void libmspub::MSPUBCollector::assignImages()
{
  for (std::map<unsigned, UnknownShapeInfo>::const_iterator i = possibleImageShapes.begin(); i != possibleImageShapes.end(); ++i)
  {
    if (i->second.imgIndex > 0 && i->second.imgIndex <= images.size())
    {
      std::pair<std::map<unsigned, ImgShapeInfo>::iterator, bool> result =
        imgShapesBySeqNum.insert(std::pair<unsigned, ImgShapeInfo>(i->first, ImgShapeInfo(images[i->second.imgIndex - 1].first, images[i->second.imgIndex - 1].second, i->second.props)));
      if (result.second)
      {
        std::map<unsigned, PageInfo>::iterator i_pg = pagesBySeqNum.find(i->second.pageSeqNum);
        if (i_pg != pagesBySeqNum.end())
        {
          i_pg->second.imgShapeReferences.push_back(result.first);
        }
      }
    }
  }
}

WPXPropertyList libmspub::MSPUBCollector::getParaStyleProps(const ParagraphStyle &style, unsigned defaultParaStyleIndex)
{
  ParagraphStyle _nothing;
  const ParagraphStyle &defaultParaStyle = defaultParaStyleIndex < defaultParaStyles.size() ? defaultParaStyles[defaultParaStyleIndex] : _nothing;
  WPXPropertyList ret;
  Alignment align = style.align >= 0 ? style.align : defaultParaStyle.align;
  switch (align)
  {
  case RIGHT:
    ret.insert("fo:text-align", "right");
    break;
  case CENTER:
    ret.insert("fo:text-align", "center");
    break;
  case JUSTIFY:
    ret.insert("fo:text-align", "justify");
    break;
  case LEFT:
  default:
    ret.insert("fo:text-align", "left");
    break;
  }
  return ret;
}

WPXPropertyList libmspub::MSPUBCollector::getCharStyleProps(const CharacterStyle &style, unsigned defaultCharStyleIndex)
{
  CharacterStyle _nothing = CharacterStyle(false, false, false);
  const CharacterStyle &defaultCharStyle = defaultCharStyleIndex < defaultCharStyles.size() ? defaultCharStyles[defaultCharStyleIndex] : _nothing;
  WPXPropertyList ret;
  if (style.italic)
  {
    ret.insert("fo:font-style", "italic");
  }
  if (style.bold)
  {
    ret.insert("fo:font-weight", "bold");
  }
  if (style.underline)
  {
    ret.insert("style:text-underline-type", "single");
  }
  if (style.textSizeInPt != -1)
  {
    ret.insert("fo:font-size", style.textSizeInPt);
  }
  else if (defaultCharStyle.textSizeInPt != -1)
  {
    ret.insert("fo:font-size", defaultCharStyle.textSizeInPt);
  }
  if (style.colorIndex >= 0 && (size_t)style.colorIndex < colors.size())
  {
    ret.insert("fo:color", getColorString(colors[style.colorIndex]));
  }
  if (style.fontIndex < fonts.size())
  {
    WPXString str;
    appendCharacters(str, fonts[style.fontIndex]);
    ret.insert("style:font-name", str);
  }
  return ret;
}

WPXString libmspub::MSPUBCollector::getColorString(const Color &color)
{
  WPXString ret;
  ret.sprintf("#%.2x%.2x%.2x",(unsigned char)color.r, (unsigned char)color.g, (unsigned char)color.b);
  MSPUB_DEBUG_MSG(("String for r: 0x%x, g: 0x%x, b: 0x%x is %s\n", color.r, color.g, color.b, ret.cstr()));
  return ret;
}

bool libmspub::MSPUBCollector::go()
{
  assignImages();
  for (std::map<unsigned, PageInfo>::const_iterator i = pagesBySeqNum.begin(); i != pagesBySeqNum.end(); ++i)
  {
    if (i->second.textShapeReferences.size() >  0 || i->second.imgShapeReferences.size() > 0)
    {
      m_painter->startGraphics(m_commonPageProperties);
      for (std::vector<std::map<unsigned, TextShapeInfo>::const_iterator>::const_iterator j = i->second.textShapeReferences.begin();
           j != i->second.textShapeReferences.end(); ++j)
      {
        m_painter->startTextObject((*j)->second.props, WPXPropertyListVector());
        for (std::vector<TextParagraph>::const_iterator k = (*j)->second.str.begin(); k != (*j)->second.str.end(); ++k)
        {
          WPXPropertyList paraProps = getParaStyleProps(k->style, k->style.defaultCharStyleIndex);
          m_painter->startTextLine(paraProps);
          for (std::vector<TextSpan>::const_iterator l = k->spans.begin(); l != k->spans.end(); ++l)
          {
            WPXString text;
            appendCharacters(text, l->chars);
            WPXPropertyList charProps = getCharStyleProps(l->style, k->style.defaultCharStyleIndex);
            m_painter->startTextSpan(charProps);
            m_painter->insertText(text);
            m_painter->endTextSpan();
          }
          m_painter->endTextLine();
        }
        m_painter->endTextObject();
      }
      for (std::vector<std::map<unsigned, ImgShapeInfo>::const_iterator>::const_iterator j = i->second.imgShapeReferences.begin();
           j != i->second.imgShapeReferences.end(); ++j)
      {
        m_painter->drawGraphicObject((*j)->second.props, (*j)->second.img);
      }
      m_painter->endGraphics();
    }
  }
  return true;
}

bool libmspub::MSPUBCollector::addTextString(const std::vector<TextParagraph> &str, unsigned id)
{
  MSPUB_DEBUG_MSG(("addTextString, id: 0x%x\n", id));
  textStringsById[id] = str;
  return true; //FIXME: Warn if the string already existed in the map.
}

void libmspub::MSPUBCollector::setWidthInEmu(unsigned long widthInEmu)
{
  //FIXME: Warn if this is called twice
  m_width = widthInEmu;
  m_commonPageProperties.insert("svg:width", ((double)widthInEmu)/EMUS_IN_INCH);
  m_widthSet = true;
}

void libmspub::MSPUBCollector::setHeightInEmu(unsigned long heightInEmu)
{
  //FIXME: Warn if this is called twice
  m_height = heightInEmu;
  m_commonPageProperties.insert("svg:height", ((double)heightInEmu)/EMUS_IN_INCH);
  m_heightSet = true;
}

bool libmspub::MSPUBCollector::addImage(unsigned index, ImgType type, WPXBinaryData img)
{
  MSPUB_DEBUG_MSG(("Image at index %d and of type 0x%x added.\n", index, type));
  while (images.size() < index)
  {
    images.push_back(std::pair<ImgType, WPXBinaryData>(UNKNOWN, WPXBinaryData()));
  }
  images[index - 1] = std::pair<ImgType, WPXBinaryData>(type, img);
  return true;
}

bool libmspub::MSPUBCollector::addShape(unsigned seqNum, unsigned pageSeqNum)
{
  /*std::map<unsigned, unsigned>::const_iterator i_ind = imgIndicesByShapeSeqNum.find(seqNum);
  if (i_ind == imgIndicesByShapeSeqNum.end())
  {
    MSPUB_DEBUG_MSG(("Didn't find which embedded image index corresponds to shape 0x%x before trying to add the shape in addImageShape!\n", seqNum));
    return false;
  }
  unsigned imgIndex = i_ind->second;
  std::map<unsigned, PageInfo>::iterator i_page = pagesBySeqNum.find(pageSeqNum);
  if (i_page == pagesBySeqNum.end())
  {
    MSPUB_DEBUG_MSG(("Page of seqnum 0x%x not found in addImageShape!\n", pageSeqNum));
    return false;
  }
  if (imgIndex > images.size() || images[imgIndex - 1].first == UNKNOWN)
  {
    MSPUB_DEBUG_MSG(("Valid image of index %d not found in addImageShape!\n", imgIndex));
    return false;
  }
  std::pair<std::map<unsigned, ImgShapeInfo>::const_iterator, bool> result = imgShapesBySeqNum.insert(std::pair<const unsigned, ImgShapeInfo>(seqNum, ImgShapeInfo(images[imgIndex - 1].first, images[imgIndex - 1].second)));
  if (result.second)
  {
    i_page->second.imgShapeReferences.push_back(result.first);
    MSPUB_DEBUG_MSG(("addImageShape succeeded with id 0x%x", imgIndex));
    return true;
  }
  MSPUB_DEBUG_MSG(("already tried to add the image shape of seqnum 0x%x to this page!\n", seqNum));
  return false;*/
  possibleImageShapes.insert(std::pair<unsigned, UnknownShapeInfo>(seqNum, UnknownShapeInfo(pageSeqNum)));
  return true;
}

void libmspub::MSPUBCollector::addColor(unsigned char r, unsigned char g, unsigned char b)
{
  colors.push_back(Color(r, g, b));
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>#include "cudata.h"
#include <cuda_runtime.h>
#include <string.h>
#include <cassert>

typedef std::pair<void*, ssize_t> seq;
using std::make_pair;
using std::auto_ptr;

cuarray::cuarray() {
    l_d = NULL;
    r_d = NULL;
    s = 0;
    e = 0;
    n = 0;
    clean_local = true;
    clean_remote = true;
}

cuarray::~cuarray() {
    if (l_d != NULL) {
        free(l_d);
        l_d = NULL;
    }
    if (r_d != NULL) {
        cudaFree(r_d);
        r_d = NULL;
    }
}

cuarray::cuarray(ssize_t _n, CUTYPE _t, bool host) {
    clean_local = host;
    clean_remote = !host;
    n = _n;
    t = _t;
    if (t == CUBOOL) {
        e = sizeof(bool);
    } else if (t == CUINT32) {
        e = sizeof(int);
    } else if (t == CUINT64) {
        e = sizeof(long);
    } else if (t == CUFLOAT32) {
        e = sizeof(float);
    } else if (t == CUFLOAT64) {
        e = sizeof(double);
    } else {
        e = 0;
    }

    s = e * n;
    if (clean_local) {
        l_d = malloc(s);
        r_d = NULL;
    } else {
        cudaMalloc(&r_d, s);
        l_d = NULL;
    }
}

cuarray::cuarray(ssize_t _n, bool* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(bool);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUBOOL;
}

cuarray::cuarray(ssize_t _n, int* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(int);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUINT32;
}

cuarray::cuarray(ssize_t _n, long* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(long);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUINT64;
}

cuarray::cuarray(ssize_t _n, float* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(float);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUFLOAT32;
}

cuarray::cuarray(ssize_t _n, double* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(float);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUFLOAT64;
}

void cuarray::retrieve() {
    //Lazy data movement
    if (!clean_local) {
        assert(r_d != NULL);
        //Lazy allocation
        if (l_d == NULL) {
            l_d = malloc(s);
        }
        cudaMemcpy(l_d, r_d, s, cudaMemcpyDeviceToHost);
        clean_local = true;
    }
}

void cuarray::exile() {
    //Lazy data movement
    if (!clean_remote) {
        assert(l_d != NULL);
        //Lazy allocation
        if (r_d == NULL) {
            cudaMalloc(&r_d, s);
        }
        cudaMemcpy(r_d, l_d, s, cudaMemcpyHostToDevice);
        clean_remote = true;
    }
}

seq cuarray::get_local_r() {
    retrieve();
    return make_pair(l_d, n);
}

seq cuarray::get_local_w() {
    retrieve();
    clean_remote = false;
    return make_pair(l_d, n);
}

seq cuarray::get_remote_r() {
    exile();
    return make_pair(r_d, n);
}

seq cuarray::get_remote_w() {
    exile();
    clean_local = false;
    return make_pair(r_d, n);
}

template<typename T>
sp_cuarray make_remote(ssize_t in) {
    return sp_cuarray(new cuarray(0, CUVOID, false));
}

template<>
sp_cuarray make_remote<bool>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUBOOL, false));
}

template<>
sp_cuarray make_remote<int>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUINT32, false));
}

template<>
sp_cuarray make_remote<long>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUINT64, false));
}

template<>
sp_cuarray make_remote<float>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUFLOAT32, false));
}

template<>
sp_cuarray make_remote<double>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUFLOAT64, false));
}
<commit_msg>Fixed bug with double arrays. Update tests.<commit_after>#include "cudata.h"
#include <cuda_runtime.h>
#include <string.h>
#include <cassert>

typedef std::pair<void*, ssize_t> seq;
using std::make_pair;
using std::auto_ptr;

cuarray::cuarray() {
    l_d = NULL;
    r_d = NULL;
    s = 0;
    e = 0;
    n = 0;
    clean_local = true;
    clean_remote = true;
}

cuarray::~cuarray() {
    if (l_d != NULL) {
        free(l_d);
        l_d = NULL;
    }
    if (r_d != NULL) {
        cudaFree(r_d);
        r_d = NULL;
    }
}

cuarray::cuarray(ssize_t _n, CUTYPE _t, bool host) {
    clean_local = host;
    clean_remote = !host;
    n = _n;
    t = _t;
    if (t == CUBOOL) {
        e = sizeof(bool);
    } else if (t == CUINT32) {
        e = sizeof(int);
    } else if (t == CUINT64) {
        e = sizeof(long);
    } else if (t == CUFLOAT32) {
        e = sizeof(float);
    } else if (t == CUFLOAT64) {
        e = sizeof(double);
    } else {
        e = 0;
    }

    s = e * n;
    if (clean_local) {
        l_d = malloc(s);
        r_d = NULL;
    } else {
        cudaMalloc(&r_d, s);
        l_d = NULL;
    }
}

cuarray::cuarray(ssize_t _n, bool* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(bool);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUBOOL;
}

cuarray::cuarray(ssize_t _n, int* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(int);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUINT32;
}

cuarray::cuarray(ssize_t _n, long* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(long);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUINT64;
}

cuarray::cuarray(ssize_t _n, float* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(float);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUFLOAT32;
}

cuarray::cuarray(ssize_t _n, double* l) {
    clean_local = true;
    clean_remote = false;
    n = _n;
    e = sizeof(double);
    s = e * n;
    l_d = malloc(s);
    r_d = NULL;
    memcpy(l_d, l, s);
    t = CUFLOAT64;
}

void cuarray::retrieve() {
    //Lazy data movement
    if (!clean_local) {
        assert(r_d != NULL);
        //Lazy allocation
        if (l_d == NULL) {
            l_d = malloc(s);
        }
        cudaMemcpy(l_d, r_d, s, cudaMemcpyDeviceToHost);
        clean_local = true;
    }
}

void cuarray::exile() {
    //Lazy data movement
    if (!clean_remote) {
        assert(l_d != NULL);
        //Lazy allocation
        if (r_d == NULL) {
            cudaMalloc(&r_d, s);
        }
        cudaMemcpy(r_d, l_d, s, cudaMemcpyHostToDevice);
        clean_remote = true;
    }
}

seq cuarray::get_local_r() {
    retrieve();
    return make_pair(l_d, n);
}

seq cuarray::get_local_w() {
    retrieve();
    clean_remote = false;
    return make_pair(l_d, n);
}

seq cuarray::get_remote_r() {
    exile();
    return make_pair(r_d, n);
}

seq cuarray::get_remote_w() {
    exile();
    clean_local = false;
    return make_pair(r_d, n);
}

template<typename T>
sp_cuarray make_remote(ssize_t in) {
    return sp_cuarray(new cuarray(0, CUVOID, false));
}

template<>
sp_cuarray make_remote<bool>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUBOOL, false));
}

template<>
sp_cuarray make_remote<int>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUINT32, false));
}

template<>
sp_cuarray make_remote<long>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUINT64, false));
}

template<>
sp_cuarray make_remote<float>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUFLOAT32, false));
}

template<>
sp_cuarray make_remote<double>(ssize_t in) {
    return sp_cuarray(new cuarray(in, CUFLOAT64, false));
}
<|endoftext|>


<commit_before>#include <QtCore/QScopedPointer>
#include <QtCore/QEventLoop>
#include <QtMultimedia/QCamera>
#include <QtMultimedia/QCameraImageCapture>
#include <QtMultimedia/QCameraInfo>

#include "qtCameraImplementation.h"
#include <QsLog.h>

using namespace trikControl;

QtCameraImplementation::QtCameraImplementation(const QString & port)
{
	QLOG_INFO() << "Available cameras:" << QCameraInfo::availableCameras().count();
	for (auto & cameraInfo : QCameraInfo::availableCameras())
	{
		if (cameraInfo.deviceName() == port)
		{
				decltype(mCamera) tmp(new QCamera(cameraInfo));
				tmp.swap(mCamera);
				break;
		}
	}
	if (!mCamera) {
		QLOG_ERROR() << "Failed to initialize camera for " << port;
	}
}

QVector<uint8_t> QtCameraImplementation::getPhoto()
{
	if(!mCamera)
		return QVector<uint8_t>();

	QScopedPointer<QCameraImageCapture> imageCapture (new QCameraImageCapture(mCamera.data()));

	imageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);

	const auto & formats = imageCapture->supportedBufferFormats();
	QLOG_INFO() << "Supported buffer formats: " << formats;

	QObject::connect(imageCapture.data(), &QCameraImageCapture::readyForCaptureChanged, [this, &imageCapture, camera=mCamera.data()](bool ready)
		{
			if (ready) {
				camera->searchAndLock();
				imageCapture->capture(getTempDir() + "/photo.jpg");
				camera->unlock();
			}
		}
	);

	QVector<uint8_t> imageByteVector;

	QObject::connect(imageCapture.data(), &QCameraImageCapture::imageCaptured, [&imageByteVector] (int, const QImage &imgOrig)
		{
			// Some possible formats:
			// QImage::Format_RGB32
			// QImage::Format_RGB888
			// QImage::Format_RGB16
			// QImage::Format_Grayscale8
			// QImage::Format_Mono
			constexpr auto DESIRED_FORMAT = QImage::Format_RGB888;

			constexpr auto SIZE_X = 320;
			constexpr auto SIZE_Y = 240;

			const QImage &img = imgOrig.format() == DESIRED_FORMAT ? imgOrig : imgOrig.convertToFormat(DESIRED_FORMAT);
			const QImage &scaledImg = img.height() == SIZE_X && img.width() == SIZE_Y ? img : img.scaled(SIZE_X, SIZE_Y); //, Qt::KeepAspectRatioByExpanding
			auto cb = scaledImg.constBits();
			imageByteVector.resize(scaledImg.byteCount());
			std::copy(cb, cb + scaledImg.byteCount(), imageByteVector.begin());
		}
	);

	mCamera->setCaptureMode(QCamera::CaptureStillImage);
	mCamera->start();
	while ( imageByteVector.isEmpty() ) {
		QEventLoop eventLoop;
		QObject::connect(imageCapture.data(), &QCameraImageCapture::imageAvailable, [&eventLoop](int, const QVideoFrame &) {
		eventLoop.quit();
		}
	);
	eventLoop.exec();
    }
	return imageByteVector;
}
<commit_msg>getPhoto:watchdog<commit_after>#include <QtCore/QScopedPointer>
#include <QtCore/QTimer>
#include <QtCore/QEventLoop>
#include <QtMultimedia/QCamera>
#include <QtMultimedia/QCameraImageCapture>
#include <QtMultimedia/QCameraInfo>

#include "qtCameraImplementation.h"
#include <QsLog.h>

using namespace trikControl;

QtCameraImplementation::QtCameraImplementation(const QString & port)
{
	QLOG_INFO() << "Available cameras:" << QCameraInfo::availableCameras().count();
	for (auto & cameraInfo : QCameraInfo::availableCameras()) {
		if (cameraInfo.deviceName() == port) {
				decltype(mCamera) tmp(new QCamera(cameraInfo));
				tmp.swap(mCamera);
				break;
		}
	}

	if (!mCamera) {
		QLOG_ERROR() << "Failed to initialize camera for " << port << " from available cameras" << QCameraInfo::availableCameras();
	}
}

QVector<uint8_t> QtCameraImplementation::getPhoto()
{
	if(!mCamera)
		return QVector<uint8_t>();

	QScopedPointer<QCameraImageCapture> imageCapture (new QCameraImageCapture(mCamera.data()));

	imageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);

	const auto & formats = imageCapture->supportedBufferFormats();
	QLOG_INFO() << "Supported buffer formats: " << formats;

	QObject::connect(imageCapture.data(), &QCameraImageCapture::readyForCaptureChanged, [this, &imageCapture, camera=mCamera.data()](bool ready)
		{
			if (ready) {
				camera->searchAndLock();
				imageCapture->capture(getTempDir() + "/photo.jpg");
				camera->unlock();
			}
		}
	);

	QVector<uint8_t> imageByteVector;

	QObject::connect(imageCapture.data(), &QCameraImageCapture::imageCaptured, [&imageByteVector] (int, const QImage &imgOrig)
		{
			// Some possible formats:
			// QImage::Format_RGB32
			// QImage::Format_RGB888
			// QImage::Format_RGB16
			// QImage::Format_Grayscale8
			// QImage::Format_Mono
			constexpr auto DESIRED_FORMAT = QImage::Format_RGB888;

			constexpr auto SIZE_X = 320;
			constexpr auto SIZE_Y = 240;

			const QImage &img = imgOrig.format() == DESIRED_FORMAT ? imgOrig : imgOrig.convertToFormat(DESIRED_FORMAT);
			const QImage &scaledImg = img.height() == SIZE_X && img.width() == SIZE_Y ? img : img.scaled(SIZE_X, SIZE_Y); //, Qt::KeepAspectRatioByExpanding
			auto cb = scaledImg.constBits();
			imageByteVector.resize(scaledImg.byteCount());
			std::copy(cb, cb + scaledImg.byteCount(), imageByteVector.begin());
		}
	);

	mCamera->setCaptureMode(QCamera::CaptureStillImage);
	mCamera->start();
	QEventLoop eventLoop;
	QTimer watchdog;
	watchdog.setInterval(1000);
	watchdog.setSingleShot(true);
	QObject::connect(&watchdog, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
	QObject::connect(imageCapture.data(), &QCameraImageCapture::imageAvailable, [&eventLoop, &imageByteVector](int, const QVideoFrame &) {
				eventLoop.quit();
			}
		);
	eventLoop.exec();
	watchdog.stop();

	return imageByteVector;
}
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2016 Intel Corporation. All Rights Reserved.

#define _USE_MATH_DEFINES
#include <math.h>
#include <limits>
#include <climits>
#include <algorithm>

#include "image.h"
#include "ivcam-private.h"
#include "ivcam-device.h"

namespace rsimpl
{
    rs_intrinsics MakeDepthIntrinsics(const ivcam::camera_calib_params & c, const int2 & dims)
    {
        return{ dims.x, dims.y, (c.Kc[0][2] * 0.5f + 0.5f) * dims.x, (c.Kc[1][2] * 0.5f + 0.5f) * dims.y, c.Kc[0][0] * 0.5f * dims.x, c.Kc[1][1] * 0.5f * dims.y,
            RS_DISTORTION_INVERSE_BROWN_CONRADY, {c.Invdistc[0], c.Invdistc[1], c.Invdistc[2], c.Invdistc[3], c.Invdistc[4]} };
    }

    rs_intrinsics MakeColorIntrinsics(const ivcam::camera_calib_params & c, const int2 & dims)
    {
        rs_intrinsics intrin = { dims.x, dims.y, c.Kt[0][2] * 0.5f + 0.5f, c.Kt[1][2] * 0.5f + 0.5f, c.Kt[0][0] * 0.5f, c.Kt[1][1] * 0.5f, RS_DISTORTION_NONE };
        if (dims.x * 3 == dims.y * 4) // If using a 4:3 aspect ratio, adjust intrinsics (defaults to 16:9)
        {
            intrin.fx *= 4.0f / 3;
            intrin.ppx *= 4.0f / 3;
            intrin.ppx -= 1.0f / 6;
        }
        intrin.fx *= dims.x;
        intrin.fy *= dims.y;
        intrin.ppx *= dims.x;
        intrin.ppy *= dims.y;
        return intrin;
    }

    void update_supported_options(uvc::device& dev,
        const uvc::extension_unit depth_xu,
        const std::vector <std::pair<rs_option, char>> options,
        std::vector<supported_option>& supported_options)
    {
        for (auto p : options)
        {
            int min, max, step, def;
            get_extension_control_range(dev, depth_xu, p.second, &min, &max, &step, &def);
            supported_option so;
            so.option = p.first;
            so.min = min;
            so.max = max;
            so.step = step;
            so.def = def;
            supported_options.push_back(so);
        }
    }

    iv_camera::iv_camera(std::shared_ptr<uvc::device> device, const static_device_info & info, const ivcam::camera_calib_params & calib) :
        rs_device_base(device, info),
        base_calibration(calib)
    {
    }

    void iv_camera::start_fw_logger(char fw_log_op_code, int grab_rate_in_ms, std::timed_mutex& mutex)
    {
        rs_device_base::start_fw_logger(fw_log_op_code, grab_rate_in_ms, mutex);
    }

    void iv_camera::stop_fw_logger()
    {
        rs_device_base::stop_fw_logger();
    }

    void iv_camera::on_before_start(const std::vector<subdevice_mode_selection> & selected_modes)
    {
    }

    rs_stream iv_camera::select_key_stream(const std::vector<rsimpl::subdevice_mode_selection> & selected_modes)
    {
        int fps[RS_STREAM_NATIVE_COUNT] = {}, max_fps = 0;
        for (const auto & m : selected_modes)
        {
            for (const auto & output : m.get_outputs())
            {
                fps[output.first] = m.mode.fps;
                max_fps = std::max(max_fps, m.mode.fps);
            }
        }

        // Prefer to sync on depth or infrared, but select the stream running at the fastest framerate
        for (auto s : { RS_STREAM_DEPTH, RS_STREAM_INFRARED2, RS_STREAM_INFRARED, RS_STREAM_COLOR })
        {
            if (fps[s] == max_fps) return s;
        }
        return RS_STREAM_DEPTH;
    }

    void iv_camera::set_options(const rs_option options[], size_t count, const double values[])
    {
        std::vector<rs_option>  base_opt;
        std::vector<double>     base_opt_val;

        for (size_t i = 0; i < count; ++i)
        {

            if (uvc::is_pu_control(options[i]))
            {
                // Disabling auto-setting controls, if needed
                switch (options[i])
                {
                case RS_OPTION_COLOR_WHITE_BALANCE:     disable_auto_option( 0, RS_OPTION_COLOR_ENABLE_AUTO_WHITE_BALANCE); break;
                case RS_OPTION_COLOR_EXPOSURE:          disable_auto_option( 0, RS_OPTION_COLOR_ENABLE_AUTO_EXPOSURE); break;
                default:  break;
                }

                uvc::set_pu_control_with_retry(get_device(), 0, options[i], static_cast<int>(values[i]));
                continue;
            }

            switch (options[i])
            {
            case RS_OPTION_F200_LASER_POWER:          ivcam::set_laser_power(get_device(), static_cast<uint8_t>(values[i])); break;
            case RS_OPTION_F200_ACCURACY:             ivcam::set_accuracy(get_device(), static_cast<uint8_t>(values[i])); break;
            case RS_OPTION_F200_MOTION_RANGE:         ivcam::set_motion_range(get_device(), static_cast<uint8_t>(values[i])); break;
            case RS_OPTION_F200_FILTER_OPTION:        ivcam::set_filter_option(get_device(), static_cast<uint8_t>(values[i])); break;
            case RS_OPTION_F200_CONFIDENCE_THRESHOLD: ivcam::set_confidence_threshold(get_device(), static_cast<uint8_t>(values[i])); break;

            default:
                base_opt.push_back(options[i]); base_opt_val.push_back(values[i]); break;
            }
        }

        //Set common options
        if (!base_opt.empty())
            rs_device_base::set_options(base_opt.data(), base_opt.size(), base_opt_val.data());
    }

    void iv_camera::get_options(const rs_option options[], size_t count, double values[])
    {
        std::vector<rs_option>  base_opt;
        std::vector<size_t>     base_opt_index;
        std::vector<double>     base_opt_val;

        for (size_t i = 0; i < count; ++i)
        {
            LOG_INFO("Reading option " << options[i]);

            if (uvc::is_pu_control(options[i]))
                throw std::logic_error(to_string() << __FUNCTION__ << " Option " << options[i] << " must be processed by a concrete class");

            uint8_t val = 0;
            switch (options[i])
            {
            case RS_OPTION_F200_LASER_POWER:          ivcam::get_laser_power(get_device(), val); values[i] = val; break;
            case RS_OPTION_F200_ACCURACY:             ivcam::get_accuracy(get_device(), val); values[i] = val; break;
            case RS_OPTION_F200_MOTION_RANGE:         ivcam::get_motion_range(get_device(), val); values[i] = val; break;
            case RS_OPTION_F200_FILTER_OPTION:        ivcam::get_filter_option(get_device(), val); values[i] = val; break;
            case RS_OPTION_F200_CONFIDENCE_THRESHOLD: ivcam::get_confidence_threshold(get_device(), val); values[i] = val; break;

            default:
                base_opt.push_back(options[i]); base_opt_index.push_back(i);
               /* LOG_WARNING("Cannot get " << options[i] << " on " << get_name());
                throw std::logic_error("Option unsupported");*/
                break;
            }
        }
        //Retrieve the common options
        if (base_opt.size())
        {
            base_opt_val.resize(base_opt.size());
            rs_device_base::get_options(base_opt.data(), base_opt.size(), base_opt_val.data());
        }

        // Merge the local data with values obtained by base class
        for (auto i : base_opt_index)
            values[i] = base_opt_val[i];
    }

    // TODO: This may need to be modified for thread safety
    class rolling_timestamp_reader : public frame_timestamp_reader
    {
        bool started;
        int64_t total;
        int last_timestamp;
    public:
        rolling_timestamp_reader() : started(), total() {}

        bool validate_frame(const subdevice_mode & mode, const void * frame) const override
        {
            // Validate that at least one byte of the image is nonzero
            for (const uint8_t * it = (const uint8_t *)frame, *end = it + mode.pf.get_image_size(mode.native_dims.x, mode.native_dims.y); it != end; ++it)
            {
                if (*it)
                {
                    return true;
                }
            }

            // F200 and SR300 can sometimes produce empty frames shortly after starting, ignore them
            LOG_INFO("Subdevice " << mode.subdevice << " produced empty frame");
            return false;
        }

        double get_frame_timestamp(const subdevice_mode & mode, const void * frame) override
        {
            // Timestamps are encoded within the first 32 bits of the image
            int rolling_timestamp = *reinterpret_cast<const int32_t *>(frame);

            if (!started)
            {
                last_timestamp = rolling_timestamp;
                started = true;
            }

            const int delta = rolling_timestamp - last_timestamp; // NOTE: Relies on undefined behavior: signed int wraparound
            last_timestamp = rolling_timestamp;
            total += delta;
            const int timestamp = static_cast<int>(total / 100000);
            return timestamp;
        }
        unsigned long long get_frame_counter(const subdevice_mode & mode, const void * frame) override
        {
            return 0;
        }
    };

	std::shared_ptr<frame_timestamp_reader> iv_camera::create_frame_timestamp_reader(int subdevice) const
    {
        return std::make_shared<rolling_timestamp_reader>();
    }

} // namespace rsimpl::f200
<commit_msg>adding serial frame number to ivcam-devices<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2016 Intel Corporation. All Rights Reserved.

#define _USE_MATH_DEFINES
#include <math.h>
#include <limits>
#include <climits>
#include <algorithm>

#include "image.h"
#include "ivcam-private.h"
#include "ivcam-device.h"

namespace rsimpl
{
    rs_intrinsics MakeDepthIntrinsics(const ivcam::camera_calib_params & c, const int2 & dims)
    {
        return{ dims.x, dims.y, (c.Kc[0][2] * 0.5f + 0.5f) * dims.x, (c.Kc[1][2] * 0.5f + 0.5f) * dims.y, c.Kc[0][0] * 0.5f * dims.x, c.Kc[1][1] * 0.5f * dims.y,
            RS_DISTORTION_INVERSE_BROWN_CONRADY, {c.Invdistc[0], c.Invdistc[1], c.Invdistc[2], c.Invdistc[3], c.Invdistc[4]} };
    }

    rs_intrinsics MakeColorIntrinsics(const ivcam::camera_calib_params & c, const int2 & dims)
    {
        rs_intrinsics intrin = { dims.x, dims.y, c.Kt[0][2] * 0.5f + 0.5f, c.Kt[1][2] * 0.5f + 0.5f, c.Kt[0][0] * 0.5f, c.Kt[1][1] * 0.5f, RS_DISTORTION_NONE };
        if (dims.x * 3 == dims.y * 4) // If using a 4:3 aspect ratio, adjust intrinsics (defaults to 16:9)
        {
            intrin.fx *= 4.0f / 3;
            intrin.ppx *= 4.0f / 3;
            intrin.ppx -= 1.0f / 6;
        }
        intrin.fx *= dims.x;
        intrin.fy *= dims.y;
        intrin.ppx *= dims.x;
        intrin.ppy *= dims.y;
        return intrin;
    }

    void update_supported_options(uvc::device& dev,
        const uvc::extension_unit depth_xu,
        const std::vector <std::pair<rs_option, char>> options,
        std::vector<supported_option>& supported_options)
    {
        for (auto p : options)
        {
            int min, max, step, def;
            get_extension_control_range(dev, depth_xu, p.second, &min, &max, &step, &def);
            supported_option so;
            so.option = p.first;
            so.min = min;
            so.max = max;
            so.step = step;
            so.def = def;
            supported_options.push_back(so);
        }
    }

    iv_camera::iv_camera(std::shared_ptr<uvc::device> device, const static_device_info & info, const ivcam::camera_calib_params & calib) :
        rs_device_base(device, info),
        base_calibration(calib)
    {
    }

    void iv_camera::start_fw_logger(char fw_log_op_code, int grab_rate_in_ms, std::timed_mutex& mutex)
    {
        rs_device_base::start_fw_logger(fw_log_op_code, grab_rate_in_ms, mutex);
    }

    void iv_camera::stop_fw_logger()
    {
        rs_device_base::stop_fw_logger();
    }

    void iv_camera::on_before_start(const std::vector<subdevice_mode_selection> & selected_modes)
    {
    }

    rs_stream iv_camera::select_key_stream(const std::vector<rsimpl::subdevice_mode_selection> & selected_modes)
    {
        int fps[RS_STREAM_NATIVE_COUNT] = {}, max_fps = 0;
        for (const auto & m : selected_modes)
        {
            for (const auto & output : m.get_outputs())
            {
                fps[output.first] = m.mode.fps;
                max_fps = std::max(max_fps, m.mode.fps);
            }
        }

        // Prefer to sync on depth or infrared, but select the stream running at the fastest framerate
        for (auto s : { RS_STREAM_DEPTH, RS_STREAM_INFRARED2, RS_STREAM_INFRARED, RS_STREAM_COLOR })
        {
            if (fps[s] == max_fps) return s;
        }
        return RS_STREAM_DEPTH;
    }

    void iv_camera::set_options(const rs_option options[], size_t count, const double values[])
    {
        std::vector<rs_option>  base_opt;
        std::vector<double>     base_opt_val;

        for (size_t i = 0; i < count; ++i)
        {

            if (uvc::is_pu_control(options[i]))
            {
                // Disabling auto-setting controls, if needed
                switch (options[i])
                {
                case RS_OPTION_COLOR_WHITE_BALANCE:     disable_auto_option( 0, RS_OPTION_COLOR_ENABLE_AUTO_WHITE_BALANCE); break;
                case RS_OPTION_COLOR_EXPOSURE:          disable_auto_option( 0, RS_OPTION_COLOR_ENABLE_AUTO_EXPOSURE); break;
                default:  break;
                }

                uvc::set_pu_control_with_retry(get_device(), 0, options[i], static_cast<int>(values[i]));
                continue;
            }

            switch (options[i])
            {
            case RS_OPTION_F200_LASER_POWER:          ivcam::set_laser_power(get_device(), static_cast<uint8_t>(values[i])); break;
            case RS_OPTION_F200_ACCURACY:             ivcam::set_accuracy(get_device(), static_cast<uint8_t>(values[i])); break;
            case RS_OPTION_F200_MOTION_RANGE:         ivcam::set_motion_range(get_device(), static_cast<uint8_t>(values[i])); break;
            case RS_OPTION_F200_FILTER_OPTION:        ivcam::set_filter_option(get_device(), static_cast<uint8_t>(values[i])); break;
            case RS_OPTION_F200_CONFIDENCE_THRESHOLD: ivcam::set_confidence_threshold(get_device(), static_cast<uint8_t>(values[i])); break;

            default:
                base_opt.push_back(options[i]); base_opt_val.push_back(values[i]); break;
            }
        }

        //Set common options
        if (!base_opt.empty())
            rs_device_base::set_options(base_opt.data(), base_opt.size(), base_opt_val.data());
    }

    void iv_camera::get_options(const rs_option options[], size_t count, double values[])
    {
        std::vector<rs_option>  base_opt;
        std::vector<size_t>     base_opt_index;
        std::vector<double>     base_opt_val;

        for (size_t i = 0; i < count; ++i)
        {
            LOG_INFO("Reading option " << options[i]);

            if (uvc::is_pu_control(options[i]))
                throw std::logic_error(to_string() << __FUNCTION__ << " Option " << options[i] << " must be processed by a concrete class");

            uint8_t val = 0;
            switch (options[i])
            {
            case RS_OPTION_F200_LASER_POWER:          ivcam::get_laser_power(get_device(), val); values[i] = val; break;
            case RS_OPTION_F200_ACCURACY:             ivcam::get_accuracy(get_device(), val); values[i] = val; break;
            case RS_OPTION_F200_MOTION_RANGE:         ivcam::get_motion_range(get_device(), val); values[i] = val; break;
            case RS_OPTION_F200_FILTER_OPTION:        ivcam::get_filter_option(get_device(), val); values[i] = val; break;
            case RS_OPTION_F200_CONFIDENCE_THRESHOLD: ivcam::get_confidence_threshold(get_device(), val); values[i] = val; break;

            default:
                base_opt.push_back(options[i]); base_opt_index.push_back(i);
               /* LOG_WARNING("Cannot get " << options[i] << " on " << get_name());
                throw std::logic_error("Option unsupported");*/
                break;
            }
        }
        //Retrieve the common options
        if (base_opt.size())
        {
            base_opt_val.resize(base_opt.size());
            rs_device_base::get_options(base_opt.data(), base_opt.size(), base_opt_val.data());
        }

        // Merge the local data with values obtained by base class
        for (auto i : base_opt_index)
            values[i] = base_opt_val[i];
    }

    // TODO: This may need to be modified for thread safety
    class rolling_timestamp_reader : public frame_timestamp_reader
    {
        bool started;
        int64_t total;
        int last_timestamp;
        int64_t counter = 0;
    public:
        rolling_timestamp_reader() : started(), total() {}

        bool validate_frame(const subdevice_mode & mode, const void * frame) const override
        {
            // Validate that at least one byte of the image is nonzero
            for (const uint8_t * it = (const uint8_t *)frame, *end = it + mode.pf.get_image_size(mode.native_dims.x, mode.native_dims.y); it != end; ++it)
            {
                if (*it)
                {
                    return true;
                }
            }

            // F200 and SR300 can sometimes produce empty frames shortly after starting, ignore them
            LOG_INFO("Subdevice " << mode.subdevice << " produced empty frame");
            return false;
        }

        double get_frame_timestamp(const subdevice_mode & mode, const void * frame) override
        {
            // Timestamps are encoded within the first 32 bits of the image
            int rolling_timestamp = *reinterpret_cast<const int32_t *>(frame);

            if (!started)
            {
                last_timestamp = rolling_timestamp;
                started = true;
            }

            const int delta = rolling_timestamp - last_timestamp; // NOTE: Relies on undefined behavior: signed int wraparound
            last_timestamp = rolling_timestamp;
            total += delta;
            const int timestamp = static_cast<int>(total / 100000);
            return timestamp;
        }
        unsigned long long get_frame_counter(const subdevice_mode & mode, const void * frame) override
        {
            return ++counter;
        }
    };

	std::shared_ptr<frame_timestamp_reader> iv_camera::create_frame_timestamp_reader(int subdevice) const
    {
        return std::make_shared<rolling_timestamp_reader>();
    }

} // namespace rsimpl::f200
<|endoftext|>


<commit_before>
#pragma once

#include <functional>

#include "geometry/frame.hpp"
#include "geometry/named_quantities.hpp"
#include "quantities/si.hpp"
#include "serialization/geometry.pb.h"

namespace principia {
namespace astronomy {
namespace internal_frames {

using geometry::Frame;
using geometry::Instant;
using geometry::Position;
using quantities::si::ArcMinute;
using quantities::si::ArcSecond;
using quantities::si::Degree;

// The International Celestial Reference System.
// The origin is the barycentre of the solar system.  The axes are fixed with
// respect to the quasars.
// The xy plane is close to the mean equator at J2000.0.
// The x axis is close to the dynamical equinox at J2000.
// The z axis is perpendicular to the xy plane and points to the northern side
// of the xy plane.
// To be honest:
// - There are several realizations of the ICRS, namely ICRF (ICRF1) and its
//   extensions, ICRF2, and the optical Hipparcos Celestial Reference Frame
//   (HCRF); these realizations have different errors, but are consistent. ICRF3
//   is in preparation, as well as an optical realization based on Gaia data.
// - The terms Barycentric Celestial Reference System (BCRS) and ICRS are often
//   used interchangeably; the relativistic framework, including the metric
//   tensor, is defined for the BCRS (IAU 2000 resolution B1.3); the orientation
//   of the BCRS is given by the ICRS axes unless otherwise stated (IAU 2006
//   resolution B2 recommendation 2).
using ICRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::ICRS,
                   /*frame_is_inertial=*/true>;

// The Geocentric Celestial Reference System.
// The origin is the centre of mass of the whole Earth system, including oceans
// and atmosphere; the axes are those of the ICRS.
// To be honest:
// - The BCRS and GCRS are relativistic reference systems.
// - The transformation between BCRS and GCRS spatial coordinates has no
//   rotational component, i.e., the GCRS is kinematically non-rotating with
//   respect to the BCRS; as a result, it rotates dynamically with respect to
//   the BCRS; in particular, the equations of motion in the GCRS include de
//   Sitter and Lense–Thirring precession.
// - The time coordinate of the BCRS is TCB, and the time coordinate of the GCRS
//   is TCG; TT is a linear scaling of TCG, and TDB is a linear scaling of TDB;
//   for practical purposes TT and TDB are within 2 ms of each other;
//   Principia's |Instant| is TT.
using GCRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::GCRS,
                   /*frame_is_inertial=*/false>;

// The International Terrestrial Reference System.
// The origin is the centre of mass of the whole Earth system, including oceans
// and atmosphere; there is no global residual rotation with respect to
// horizontal motions at the earth's surface.
// Practical notes:
// - This is identical to WGS84 at 1 m level, and to recent realizations of WGS
//   84 at 10 cm level; the xz plane is a bit over a hundred metres from the
//   Royal Observatory in Greenwich.
//   Caveat: using |SphericalCoordinates<Length>| on ITRS coordinates is
//   inconsistent with WGS 84 latitudes; the WGS 84 geoid should be used.
// - The ITRS is related to the European Terrestrial Reference System (ETRS89)
//   by a time-dependent rigid transformation.
// To be honest:
// - There are many realizations of the ITRS; as of this writing, ICRFs 89, 90,
//   91, 92, 93, 94, 96, 97, 2000, 2005, 2008, and 2014.  They are related by
//   linearly time-dependent linearized similarity transformations with nonzero
//   scaling, which the current abstractions of Principia cannot support; see
//   Transformation parameters from ITRF2014 to past ITRFs,
//   http://itrf.ensg.ign.fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt.  Identifying
//   recent ITRFs (2005 and later) results in errors of a few millimetres at the
//   geocentre, scale errors on the order of 1 part-per-billion, and angular
//   errors below 1 μas.  Identifying earlier ITRFs results in errors may result
//   in errors of tens of centimetres at the geocentre, scale errors on the
//   order of ten parts per billion, and arcsecond-level angular errors.
// - ETRFyy is always related to the corresponding ITRFyy by a linearized rigid
//   transformation depending linearly on time, however it is related to other
//   ITRFs by time-dependent similarity with time-dependent nonzero scaling; see
//   the tables in EUREF Technical Note 1,
//   http://etrs89.ensg.ign.fr/pub/EUREF-TN-1.pdf
using ITRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::ITRS,
                   /*frame_is_inertial=*/false>;

// The following two reference systems are both geocentric, and they share the
// same z axis, the Celestial Intermediate Pole.  Their common xy plane is the
// intermediate equator.
// The rotation around the z axis relating the Terrestrial and Celestial
// Intermediate Reference Systems, i.e., the angle between the Terrestrial and
// Celestial Intermediate Origins, is the Earth Rotation Angle (ERA); the Earth
// Rotation Angle is an affine function of UT1 defined by equation 5.14 of the
// IERS conventions (2010).  Note that the rate is faster than 2π radians per
// UT1 day, as UT1 is notionally mean solar days, whereas revolutions of the ERA
// are stellar days.

// The glossary of the Nomenclature for Fundamental Astronomy notes for both
// that "since the acronym for this system is close to another acronym (namely
// [ITRS, respectively ICRS]), it is suggested that wherever possible the
// complete name be used".

// The Terrestrial Intermediate Reference System.
// The x axis is the Terrestrial Intermediate Origin.
// The ITRS is related to the Terrestrial Intermediate Reference System by polar
// motion, as described in sections 5.4.1 and 5.5.1 of the IERS conventions
// (2010).
// TODO(egg): identifying this with the ITRS, besides leading to acronym
// confusion, results in arcsecond-level errors.
using TerrestrialIntermediateReferenceSystem = ITRS;

// The origin is geocentric; the basis is right-handed and orthonormal, the xy
// plane is the same as that of the Terrestrial Intermediate Reference System,
// i.e., the intermediate equator.
// The x axis is the Celestial Intermediate Origin.
// The GCRS is related to the Celestial Intermediate Reference System by
// precession-nutation and frame biases, see sections 5.4.4 and 5.5.4 of the
// IERS conventions (2010).
// TODO(egg): identifying this with the GCRS leads to errors on the order of 10
// arcminutes at the time of this writing, and on the order of a degree over a
// century.
using CelestialIntermediateReferenceSystem = GCRS;

// A reference frame for transit exoplanetology.
// The xy plane is the plane of the sky.  The origin is at the barycentre of the
// extrasolar system.  The z axis goes from the extrasolar system to the Earth.
// The xz plane is (approximately) the plane of the extrasolar system.
using Sky =
    Frame<serialization::Frame::SolarSystemTag,
          serialization::Frame::SKY, true>;

}  // namespace internal_frames

using internal_frames::GCRS;
using internal_frames::ICRS;
using internal_frames::ITRS;
using internal_frames::Sky;
using internal_frames::TerrestrialIntermediateReferenceSystem;
using internal_frames::CelestialIntermediateReferenceSystem;

}  // namespace astronomy
}  // namespace principia
<commit_msg>degarble<commit_after>
#pragma once

#include <functional>

#include "geometry/frame.hpp"
#include "geometry/named_quantities.hpp"
#include "quantities/si.hpp"
#include "serialization/geometry.pb.h"

namespace principia {
namespace astronomy {
namespace internal_frames {

using geometry::Frame;
using geometry::Instant;
using geometry::Position;
using quantities::si::ArcMinute;
using quantities::si::ArcSecond;
using quantities::si::Degree;

// The International Celestial Reference System.
// The origin is the barycentre of the solar system.  The axes are fixed with
// respect to the quasars.
// The xy plane is close to the mean equator at J2000.0.
// The x axis is close to the dynamical equinox at J2000.
// The z axis is perpendicular to the xy plane and points to the northern side
// of the xy plane.
// To be honest:
// - There are several realizations of the ICRS, namely ICRF (ICRF1) and its
//   extensions, ICRF2, and the optical Hipparcos Celestial Reference Frame
//   (HCRF); these realizations have different errors, but are consistent. ICRF3
//   is in preparation, as well as an optical realization based on Gaia data.
// - The terms Barycentric Celestial Reference System (BCRS) and ICRS are often
//   used interchangeably; the relativistic framework, including the metric
//   tensor, is defined for the BCRS (IAU 2000 resolution B1.3); the orientation
//   of the BCRS is given by the ICRS axes unless otherwise stated (IAU 2006
//   resolution B2 recommendation 2).
using ICRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::ICRS,
                   /*frame_is_inertial=*/true>;

// The Geocentric Celestial Reference System.
// The origin is the centre of mass of the whole Earth system, including oceans
// and atmosphere; the axes are those of the ICRS.
// To be honest:
// - The BCRS and GCRS are relativistic reference systems.
// - The transformation between BCRS and GCRS spatial coordinates has no
//   rotational component, i.e., the GCRS is kinematically non-rotating with
//   respect to the BCRS; as a result, it rotates dynamically with respect to
//   the BCRS; in particular, the equations of motion in the GCRS include de
//   Sitter and Lense–Thirring precession.
// - The time coordinate of the BCRS is TCB, and the time coordinate of the GCRS
//   is TCG; TT is a linear scaling of TCG, and TDB is a linear scaling of TDB;
//   for practical purposes TT and TDB are within 2 ms of each other;
//   Principia's |Instant| is TT.
using GCRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::GCRS,
                   /*frame_is_inertial=*/false>;

// The International Terrestrial Reference System.
// The origin is the centre of mass of the whole Earth system, including oceans
// and atmosphere; there is no global residual rotation with respect to
// horizontal motions at the earth's surface.
// Practical notes:
// - This is identical to WGS84 at 1 m level, and to recent realizations of WGS
//   84 at 10 cm level; the xz plane is a bit over a hundred metres from the
//   Royal Observatory in Greenwich.
//   Caveat: using |SphericalCoordinates<Length>| on ITRS coordinates is
//   inconsistent with WGS 84 latitudes; the WGS 84 geoid should be used.
// - The ITRS is related to the European Terrestrial Reference System (ETRS89)
//   by a time-dependent rigid transformation.
// To be honest:
// - There are many realizations of the ITRS; as of this writing, ICRFs 89, 90,
//   91, 92, 93, 94, 96, 97, 2000, 2005, 2008, and 2014.  They are related by
//   linearly time-dependent linearized similarity transformations with nonzero
//   scaling, which the current abstractions of Principia cannot support; see
//   Transformation parameters from ITRF2014 to past ITRFs,
//   http://itrf.ensg.ign.fr/doc_ITRF/Transfo-ITRF2014_ITRFs.txt.  Identifying
//   recent ITRFs (2005 and later) results in errors of a few millimetres at the
//   geocentre, scale errors on the order of 1 part-per-billion, and angular
//   errors below 1 μas.  Identifying earlier ITRFs may result in errors of tens
//   of centimetres at the geocentre, scale errors on the order of ten parts per
//   billion, and arcsecond-level angular errors.
// - ETRFyy is always related to the corresponding ITRFyy by a linearized rigid
//   transformation depending linearly on time, however it is related to other
//   ITRFs by time-dependent similarity with time-dependent nonzero scaling; see
//   the tables in EUREF Technical Note 1,
//   http://etrs89.ensg.ign.fr/pub/EUREF-TN-1.pdf
using ITRS = Frame<serialization::Frame::SolarSystemTag,
                   serialization::Frame::ITRS,
                   /*frame_is_inertial=*/false>;

// The following two reference systems are both geocentric, and they share the
// same z axis, the Celestial Intermediate Pole.  Their common xy plane is the
// intermediate equator.
// The rotation around the z axis relating the Terrestrial and Celestial
// Intermediate Reference Systems, i.e., the angle between the Terrestrial and
// Celestial Intermediate Origins, is the Earth Rotation Angle (ERA); the Earth
// Rotation Angle is an affine function of UT1 defined by equation 5.14 of the
// IERS conventions (2010).  Note that the rate is faster than 2π radians per
// UT1 day, as UT1 is notionally mean solar days, whereas revolutions of the ERA
// are stellar days.

// The glossary of the Nomenclature for Fundamental Astronomy notes for both
// that "since the acronym for this system is close to another acronym (namely
// [ITRS, respectively ICRS]), it is suggested that wherever possible the
// complete name be used".

// The Terrestrial Intermediate Reference System.
// The x axis is the Terrestrial Intermediate Origin.
// The ITRS is related to the Terrestrial Intermediate Reference System by polar
// motion, as described in sections 5.4.1 and 5.5.1 of the IERS conventions
// (2010).
// TODO(egg): identifying this with the ITRS, besides leading to acronym
// confusion, results in arcsecond-level errors.
using TerrestrialIntermediateReferenceSystem = ITRS;

// The origin is geocentric; the basis is right-handed and orthonormal, the xy
// plane is the same as that of the Terrestrial Intermediate Reference System,
// i.e., the intermediate equator.
// The x axis is the Celestial Intermediate Origin.
// The GCRS is related to the Celestial Intermediate Reference System by
// precession-nutation and frame biases, see sections 5.4.4 and 5.5.4 of the
// IERS conventions (2010).
// TODO(egg): identifying this with the GCRS leads to errors on the order of 10
// arcminutes at the time of this writing, and on the order of a degree over a
// century.
using CelestialIntermediateReferenceSystem = GCRS;

// A reference frame for transit exoplanetology.
// The xy plane is the plane of the sky.  The origin is at the barycentre of the
// extrasolar system.  The z axis goes from the extrasolar system to the Earth.
// The xz plane is (approximately) the plane of the extrasolar system.
using Sky =
    Frame<serialization::Frame::SolarSystemTag,
          serialization::Frame::SKY, true>;

}  // namespace internal_frames

using internal_frames::GCRS;
using internal_frames::ICRS;
using internal_frames::ITRS;
using internal_frames::Sky;
using internal_frames::TerrestrialIntermediateReferenceSystem;
using internal_frames::CelestialIntermediateReferenceSystem;

}  // namespace astronomy
}  // namespace principia
<|endoftext|>


<commit_before>/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <unordered_map>
#include <memory>
#include <string>
#include "util/sstream.h"
#include "library/kernel_serializer.h"
#include "library/annotation.h"

namespace lean {
static name * g_annotation = nullptr;
static std::string * g_annotation_opcode = nullptr;

name const & get_annotation_name() { return *g_annotation; }
std::string const & get_annotation_opcode() { return *g_annotation_opcode; }

/** \brief We use a macro to mark expressions that denote "let" and "have"-expressions.
    These marks have no real semantic meaning, but are useful for helping Lean's pretty printer.
*/
class annotation_macro_definition_cell : public macro_definition_cell {
    name m_name;
    void check_macro(expr const & m) const {
        if (!is_macro(m) || macro_num_args(m) != 1)
            throw exception(sstream() << "invalid '" << m_name << "' annotation, incorrect number of arguments");
    }
public:
    annotation_macro_definition_cell(name const & n):m_name(n) {}
    name const & get_annotation_kind() const { return m_name; }
    virtual name get_name() const { return get_annotation_name(); }
    virtual format pp(formatter const &) const { return format(m_name); }
    virtual void display(std::ostream & out) const { out << m_name; }
    virtual pair<expr, constraint_seq> check_type(expr const & m, extension_context & ctx, bool infer_only) const {
        check_macro(m);
        return ctx.check_type(macro_arg(m, 0), infer_only);
    }
    virtual optional<expr> expand(expr const & m, extension_context &) const {
        check_macro(m);
        return some_expr(macro_arg(m, 0));
    }
    virtual void write(serializer & s) const {
        s.write_string(get_annotation_opcode());
        s << m_name;
    }
};

typedef std::unordered_map<name, macro_definition, name_hash, name_eq> annotation_macros;
static annotation_macros * g_annotation_macros = nullptr;

annotation_macros & get_annotation_macros() { return *g_annotation_macros; }

void register_annotation(name const & n) {
    annotation_macros & ms = get_annotation_macros();
    lean_assert(ms.find(n) == ms.end());
    ms.insert(mk_pair(n, macro_definition(new annotation_macro_definition_cell(n))));
}

expr mk_annotation(name const & kind, expr const & e, tag g) {
    annotation_macros & ms = get_annotation_macros();
    auto it = ms.find(kind);
    if (it != ms.end()) {
        return mk_macro(it->second, 1, &e, g);
    } else {
        throw exception(sstream() << "unknown annotation kind '" << kind << "'");
    }
}

expr mk_annotation(name const & kind, expr const & e) {
    return mk_annotation(kind, e, e.get_tag());
}

bool is_annotation(expr const & e) {
    return is_macro(e) && macro_def(e).get_name() == get_annotation_name();
}

name const & get_annotation_kind(expr const & e) {
    lean_assert(is_annotation(e));
    return static_cast<annotation_macro_definition_cell const*>(macro_def(e).raw())->get_annotation_kind();
}

bool is_annotation(expr const & e, name const & kind) {
    return is_annotation(e) && get_annotation_kind(e) == kind;
}

expr const & get_annotation_arg(expr const & e) {
    lean_assert(is_annotation(e));
    return macro_arg(e, 0);
}

bool is_nested_annotation(expr const & e, name const & kind) {
    expr const * it = &e;
    while (is_annotation(*it)) {
        if (get_annotation_kind(*it) == kind)
            return true;
        it = &get_annotation_arg(*it);
    }
    return false;
}

expr const & get_nested_annotation_arg(expr const & e) {
    expr const * it = &e;
    while (is_annotation(*it))
        it = &get_annotation_arg(*it);
    return *it;
}

expr copy_annotations(expr const & from, expr const & to) {
    buffer<expr> trace;
    expr const * it = &from;
    while (is_annotation(*it)) {
        trace.push_back(*it);
        it = &get_annotation_arg(*it);
    }
    expr r     = to;
    unsigned i = trace.size();
    while (i > 0) {
        --i;
        r = copy_tag(trace[i], mk_annotation(get_annotation_kind(trace[i]), r));
    }
    return r;
}

static name * g_have = nullptr;
static name * g_show = nullptr;

expr mk_have_annotation(expr const & e) { return mk_annotation(*g_have, e); }
expr mk_show_annotation(expr const & e) { return mk_annotation(*g_show, e); }
bool is_have_annotation(expr const & e) { return is_annotation(e, *g_have); }
bool is_show_annotation(expr const & e) { return is_annotation(e, *g_show); }

void initialize_annotation() {
    g_annotation = new name("annotation");
    g_annotation_opcode = new std::string("Annot");
    g_annotation_macros = new annotation_macros();
    g_have = new name("have");
    g_show = new name("show");

    register_annotation(*g_have);
    register_annotation(*g_show);

    register_macro_deserializer(get_annotation_opcode(),
                                [](deserializer & d, unsigned num, expr const * args) {
                                    if (num != 1)
                                        throw corrupted_stream_exception();
                                    name k;
                                    d >> k;
                                    return mk_annotation(k, args[0]);
                                });
}

void finalize_annotation() {
    delete g_show;
    delete g_have;
    delete g_annotation_macros;
    delete g_annotation_opcode;
    delete g_annotation;
}
}
<commit_msg>fix(library/annotation): add missing == and hash methods for annotation class<commit_after>/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <unordered_map>
#include <memory>
#include <string>
#include "util/sstream.h"
#include "library/kernel_serializer.h"
#include "library/annotation.h"

namespace lean {
static name * g_annotation = nullptr;
static std::string * g_annotation_opcode = nullptr;

name const & get_annotation_name() { return *g_annotation; }
std::string const & get_annotation_opcode() { return *g_annotation_opcode; }

/** \brief We use a macro to mark expressions that denote "let" and "have"-expressions.
    These marks have no real semantic meaning, but are useful for helping Lean's pretty printer.
*/
class annotation_macro_definition_cell : public macro_definition_cell {
    name m_name;
    void check_macro(expr const & m) const {
        if (!is_macro(m) || macro_num_args(m) != 1)
            throw exception(sstream() << "invalid '" << m_name << "' annotation, incorrect number of arguments");
    }
public:
    annotation_macro_definition_cell(name const & n):m_name(n) {}
    name const & get_annotation_kind() const { return m_name; }
    virtual name get_name() const { return get_annotation_name(); }
    virtual format pp(formatter const &) const { return format(m_name); }
    virtual void display(std::ostream & out) const { out << m_name; }
    virtual pair<expr, constraint_seq> check_type(expr const & m, extension_context & ctx, bool infer_only) const {
        check_macro(m);
        return ctx.check_type(macro_arg(m, 0), infer_only);
    }
    virtual optional<expr> expand(expr const & m, extension_context &) const {
        check_macro(m);
        return some_expr(macro_arg(m, 0));
    }
    virtual void write(serializer & s) const {
        s.write_string(get_annotation_opcode());
        s << m_name;
    }
    virtual bool operator==(macro_definition_cell const & other) const {
        if (auto other_ptr = dynamic_cast<annotation_macro_definition_cell const *>(&other)) {
            return m_name == other_ptr->m_name;
        } else {
            return false;
        }
    }
    virtual unsigned hash() const {
        return ::lean::hash(m_name.hash(), g_annotation->hash());
    }
};

typedef std::unordered_map<name, macro_definition, name_hash, name_eq> annotation_macros;
static annotation_macros * g_annotation_macros = nullptr;

annotation_macros & get_annotation_macros() { return *g_annotation_macros; }

void register_annotation(name const & n) {
    annotation_macros & ms = get_annotation_macros();
    lean_assert(ms.find(n) == ms.end());
    ms.insert(mk_pair(n, macro_definition(new annotation_macro_definition_cell(n))));
}

expr mk_annotation(name const & kind, expr const & e, tag g) {
    annotation_macros & ms = get_annotation_macros();
    auto it = ms.find(kind);
    if (it != ms.end()) {
        return mk_macro(it->second, 1, &e, g);
    } else {
        throw exception(sstream() << "unknown annotation kind '" << kind << "'");
    }
}

expr mk_annotation(name const & kind, expr const & e) {
    return mk_annotation(kind, e, e.get_tag());
}

bool is_annotation(expr const & e) {
    return is_macro(e) && macro_def(e).get_name() == get_annotation_name();
}

name const & get_annotation_kind(expr const & e) {
    lean_assert(is_annotation(e));
    return static_cast<annotation_macro_definition_cell const*>(macro_def(e).raw())->get_annotation_kind();
}

bool is_annotation(expr const & e, name const & kind) {
    return is_annotation(e) && get_annotation_kind(e) == kind;
}

expr const & get_annotation_arg(expr const & e) {
    lean_assert(is_annotation(e));
    return macro_arg(e, 0);
}

bool is_nested_annotation(expr const & e, name const & kind) {
    expr const * it = &e;
    while (is_annotation(*it)) {
        if (get_annotation_kind(*it) == kind)
            return true;
        it = &get_annotation_arg(*it);
    }
    return false;
}

expr const & get_nested_annotation_arg(expr const & e) {
    expr const * it = &e;
    while (is_annotation(*it))
        it = &get_annotation_arg(*it);
    return *it;
}

expr copy_annotations(expr const & from, expr const & to) {
    buffer<expr> trace;
    expr const * it = &from;
    while (is_annotation(*it)) {
        trace.push_back(*it);
        it = &get_annotation_arg(*it);
    }
    expr r     = to;
    unsigned i = trace.size();
    while (i > 0) {
        --i;
        r = copy_tag(trace[i], mk_annotation(get_annotation_kind(trace[i]), r));
    }
    return r;
}

static name * g_have = nullptr;
static name * g_show = nullptr;

expr mk_have_annotation(expr const & e) { return mk_annotation(*g_have, e); }
expr mk_show_annotation(expr const & e) { return mk_annotation(*g_show, e); }
bool is_have_annotation(expr const & e) { return is_annotation(e, *g_have); }
bool is_show_annotation(expr const & e) { return is_annotation(e, *g_show); }

void initialize_annotation() {
    g_annotation = new name("annotation");
    g_annotation_opcode = new std::string("Annot");
    g_annotation_macros = new annotation_macros();
    g_have = new name("have");
    g_show = new name("show");

    register_annotation(*g_have);
    register_annotation(*g_show);

    register_macro_deserializer(get_annotation_opcode(),
                                [](deserializer & d, unsigned num, expr const * args) {
                                    if (num != 1)
                                        throw corrupted_stream_exception();
                                    name k;
                                    d >> k;
                                    return mk_annotation(k, args[0]);
                                });
}

void finalize_annotation() {
    delete g_show;
    delete g_have;
    delete g_annotation_macros;
    delete g_annotation_opcode;
    delete g_annotation;
}
}
<|endoftext|>


<commit_before>#include "jsproc/worker.hpp"

#include <cstring>              // strerror
#include <sys/types.h>
#include <sys/socket.h>

namespace jsproc {

// Accepts and runs a job.
static void accept_job(
    job_result_t *result,
    read_stream_t *job_source,
    read_stream_t *job_input,
    write_stream_t *job_output)
{
    // Try to receive the job.
    job_func_t jobfunc;
    int64_t res = force_read(job_source, &jobfunc, sizeof jobfunc);
    if (res < (int64_t) sizeof jobfunc) {
        result->type = JOB_INITIAL_READ_FAILURE;
        result->data.archive_result = res == -1 ? ARCHIVE_SOCK_ERROR : ARCHIVE_SOCK_EOF;
        return;
    }

    // The job should explicitly set result->type. Otherwise, something weird
    // happened.
    result->type = JOB_UNKNOWN_ERROR;
    (*jobfunc)(result, job_input, job_output);
}

void exec_worker(int sockfd) {
    unix_socket_stream_t sock(sockfd, new blocking_fd_watcher_t());

    // Receive and run jobs until we get an error, or a job tells us to shut down.
    job_result_t result;
    do {
        fprintf(stderr, "WORKER accepting\n");
        accept_job(&result, &sock, &sock, &sock);
        fprintf(stderr, "WORKER result: %s\n",
                result.type == JOB_SUCCESS ? "success" :
                result.type == JOB_INITIAL_READ_FAILURE ? "initial read failure" :
                "other");
        // TODO (rntz): logging, error-detection etc.
    } while (result.type != JOB_SHUTDOWN && sock.is_read_open() && sock.is_write_open());

    // TODO (rntz): useful return codes.
    fprintf(stderr, "WORKER dying!\n");
    exit(0);
}

} // namespace jsproc
<commit_msg>add FIXME to worker.cc<commit_after>#include "jsproc/worker.hpp"

#include <cstring>              // strerror
#include <sys/types.h>
#include <sys/socket.h>

namespace jsproc {

// Accepts and runs a job.
static void accept_job(
    job_result_t *result,
    read_stream_t *job_source,
    read_stream_t *job_input,
    write_stream_t *job_output)
{
    // Try to receive the job.
    job_func_t jobfunc;
    int64_t res = force_read(job_source, &jobfunc, sizeof jobfunc);
    if (res < (int64_t) sizeof jobfunc) {
        result->type = JOB_INITIAL_READ_FAILURE;
        result->data.archive_result = res == -1 ? ARCHIVE_SOCK_ERROR : ARCHIVE_SOCK_EOF;
        return;
    }

    // The job should explicitly set result->type. Otherwise, something weird
    // happened.
    result->type = JOB_UNKNOWN_ERROR;
    (*jobfunc)(result, job_input, job_output);
}

// FIXME: currently assumes it gets a stream of jobs, when actually it gets a
// stream of fds which carry jobs.
void exec_worker(int sockfd) {
    unix_socket_stream_t sock(sockfd, new blocking_fd_watcher_t());

    // Receive and run jobs until we get an error, or a job tells us to shut down.
    job_result_t result;
    do {
        fprintf(stderr, "WORKER accepting\n");
        accept_job(&result, &sock, &sock, &sock);
        fprintf(stderr, "WORKER result: %s\n",
                result.type == JOB_SUCCESS ? "success" :
                result.type == JOB_INITIAL_READ_FAILURE ? "initial read failure" :
                "other");
        // TODO (rntz): logging, error-detection etc.
    } while (result.type != JOB_SHUTDOWN && sock.is_read_open() && sock.is_write_open());

    // TODO (rntz): useful return codes.
    fprintf(stderr, "WORKER dying!\n");
    exit(0);
}

} // namespace jsproc
<|endoftext|>


<commit_before>/*
 * Image.hpp
 *
 *  Created on: Sep 8, 2009
 *      Author: rasmussn
 */

#ifndef IMAGE_HPP_
#define IMAGE_HPP_

#include "HyPerLayer.hpp"
#include "../columns/HyPerCol.hpp"

namespace PV {

class Image : public HyPerLayer {

protected:
   Image(const char * name, HyPerCol * hc);

public:
   Image(const char * name, HyPerCol * hc, const char * filename);
   virtual ~Image();

#ifdef OBSOLETE
   virtual int initialize_base(const char * name, HyPerCol * hc);
#endif
   virtual int initializeImage(const char * filename);

   // primary layer interface
   //
   virtual int recvSynapticInput(HyPerConn * conn, PVLayerCube * cube, int neighbor);
   virtual int updateState(float time, float dt);
//   virtual int publish(InterColComm * comm, float time);
   virtual int outputState(float time, bool last=false);

   // partially override implementation of LayerDataInterface interface
   //
   const pvdata_t * getLayerData()   { return data; }

#ifdef OBSOLETE
   const PVLayerLoc * getLayerLoc()  { return & clayer->loc; /*return &loc;*/ }
   bool isExtended()                 { return true; }

   virtual bool updateImage(float time, float dt);
#endif
   virtual int  clearImage();

   float lastUpdate()  { return lastUpdateTime; }

   virtual pvdata_t * getImageBuffer();
   virtual PVLayerLoc getImageLoc();

   virtual int tag();

   int read(const char * filename);
   int read(const char * filename, int offsetX, int offsetY);
   int write(const char * filename);

   int exchange();

   int toGrayScale();
   static int convertToGrayScale(PVLayerLoc * loc, unsigned char * buf);

   int  convolve(int width);
   void setTau(float t)                { tau = t; }

   int copyFromInteriorBuffer(const unsigned char * buf);
   int copyToInteriorBuffer(unsigned char * buf, float fac);
   int gatherToInteriorBuffer(unsigned char * buf);

protected:

   //int initializeImage(const char * filename);

#ifdef OBSOLETE
   Communicator * comm;           // the communicator object for reading/writing files
#endif
   MPI_Datatype * mpi_datatypes;  // MPI datatypes for boundary exchange

#ifdef OBSOLETE
   PVLayerLoc loc;        // size/location of layer
#endif
   pvdata_t * data;       // buffer containing reduced image
   char * filename;       // path to file if a file exists

   PVLayerLoc imageLoc;   // size/location of actual image
   pvdata_t * imageData;  // buffer containing image

   int writeImages;      // controls writing of image file during outputState

   float lastPhase;
   float lastUpdateTime; // time of last image update

   float tau;
};

}

#endif /* IMAGE_HPP_ */
<commit_msg>Added multiplicative factor to copyFromInteriorBuffer.<commit_after>/*
 * Image.hpp
 *
 *  Created on: Sep 8, 2009
 *      Author: rasmussn
 */

#ifndef IMAGE_HPP_
#define IMAGE_HPP_

#include "HyPerLayer.hpp"
#include "../columns/HyPerCol.hpp"

namespace PV {

class Image : public HyPerLayer {

protected:
   Image(const char * name, HyPerCol * hc);

public:
   Image(const char * name, HyPerCol * hc, const char * filename);
   virtual ~Image();

#ifdef OBSOLETE
   virtual int initialize_base(const char * name, HyPerCol * hc);
#endif
   virtual int initializeImage(const char * filename);

   // primary layer interface
   //
   virtual int recvSynapticInput(HyPerConn * conn, PVLayerCube * cube, int neighbor);
   virtual int updateState(float time, float dt);
//   virtual int publish(InterColComm * comm, float time);
   virtual int outputState(float time, bool last=false);

   // partially override implementation of LayerDataInterface interface
   //
   const pvdata_t * getLayerData()   { return data; }

#ifdef OBSOLETE
   const PVLayerLoc * getLayerLoc()  { return & clayer->loc; /*return &loc;*/ }
   bool isExtended()                 { return true; }

   virtual bool updateImage(float time, float dt);
#endif
   virtual int  clearImage();

   float lastUpdate()  { return lastUpdateTime; }

   virtual pvdata_t * getImageBuffer();
   virtual PVLayerLoc getImageLoc();

   virtual int tag();

   int read(const char * filename);
   int read(const char * filename, int offsetX, int offsetY);
   int write(const char * filename);

   int exchange();

   int toGrayScale();
   static int convertToGrayScale(PVLayerLoc * loc, unsigned char * buf);

   int  convolve(int width);
   void setTau(float t)                { tau = t; }

   int copyFromInteriorBuffer(const unsigned char * buf, float fac);
   int copyToInteriorBuffer(unsigned char * buf, float fac);
   int gatherToInteriorBuffer(unsigned char * buf);

protected:

#ifdef OPENCL_THREADS
   int virtual initializeThreadData();
   int         initializeThreadKernels();
#endif

   //int initializeImage(const char * filename);

#ifdef OBSOLETE
   Communicator * comm;           // the communicator object for reading/writing files
#endif
   MPI_Datatype * mpi_datatypes;  // MPI datatypes for boundary exchange

#ifdef OBSOLETE
   PVLayerLoc loc;        // size/location of layer
#endif
   pvdata_t * data;       // buffer containing reduced image
   char * filename;       // path to file if a file exists

   PVLayerLoc imageLoc;   // size/location of actual image
   pvdata_t * imageData;  // buffer containing image

   int writeImages;      // controls writing of image file during outputState

   float lastPhase;
   float lastUpdateTime; // time of last image update

   float tau;
};

}

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