<commit_before>// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "chrome/browser/simple_xp_frame.h"

#include "chrome/app/theme/theme_resources.h"
#include "base/string_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents.h"
#include "chrome/browser/tab_contents_container_view.h"
#include "chrome/browser/tabs/tab.h"
#include "chrome/browser/views/location_bar_view.h"
#include "chrome/browser/web_app.h"
#include "chrome/browser/web_app_icon_manager.h"
#include "chrome/browser/web_contents.h"
#include "chrome/common/win_util.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/l10n_util.h"
#include "chrome/views/focus_manager.h"
#include "chrome/views/label.h"
#include "chrome/views/text_field.h"
#include "net/base/net_util.h"
#include "SkBitmap.h"

#include "generated_resources.h"

// The title bar text color.
static const SkColor kTitleBarTextColor = SkColorSetRGB(255, 255, 255);

// How thick is the top resize bar.
static const int kTopResizeBarHeight = 3;

// Left margin on the left side of the favicon.
static const int kFavIconMargin = 2;

// Padding between the favicon and the text.
static const int kFavIconPadding = 4;

// Background color for the button hot state.
static const SkColor kHotColor = SkColorSetRGB(49, 106, 197);

// distance between contents and drop arrow.
static const int kHorizMargin = 4;

// Border all around the menu.
static const int kHorizBorderSize = 2;
static const int kVertBorderSize = 1;

// How much wider or shorter the location bar is relative to the client area.
static const int kLocationBarOffset = 2;
// Spacing between the location bar and the content area.
static const int kLocationBarSpacing = 1;

////////////////////////////////////////////////////////////////////////////////
//
// TitleBarMenuButton implementation.
//
////////////////////////////////////////////////////////////////////////////////
TitleBarMenuButton::TitleBarMenuButton(SimpleXPFrameTitleBar* title_bar)
    : ChromeViews::MenuButton(L"", title_bar, false),
      contents_(NULL),
      title_bar_(title_bar) {
  ResourceBundle &rb = ResourceBundle::GetSharedInstance();
  drop_arrow_ = rb.GetBitmapNamed(IDR_APP_DROPARROW);
}

TitleBarMenuButton::~TitleBarMenuButton() {
}

void TitleBarMenuButton::SetContents(ChromeViews::View* contents) {
  contents_ = contents;
}

void TitleBarMenuButton::GetPreferredSize(CSize *out) {
  if (contents_)
    contents_->GetPreferredSize(out);
  else
    out->cx = out->cy = 0;

  out->cx += drop_arrow_->width() + kHorizMargin + (2 * kHorizBorderSize);
  out->cy = std::max(drop_arrow_->height(), static_cast<int>(out->cy));
  out->cy += (2 * kVertBorderSize);
}

void TitleBarMenuButton::Paint(ChromeCanvas* canvas) {
  if (GetState() == TextButton::BS_HOT ||
      GetState() == TextButton::BS_PUSHED || menu_visible_) {
    canvas->FillRectInt(kHotColor, 0, 0, GetWidth(), GetHeight());
  }

  if (contents_) {
    CSize s;
    contents_->GetPreferredSize(&s);
    // Note: we use a floating view in this case because we never want the
    // contents to process any event.
    PaintFloatingView(canvas,
                      contents_,
                      kVertBorderSize,
                      (GetHeight() - s.cy) / 2,
                      GetWidth() - kHorizMargin - drop_arrow_->width() -
                      (2 * kHorizBorderSize),
                      s.cy);
  }

  // We can not use the mirroring infrastructure in ChromeViews in order to
  // mirror the drop down arrow because is is drawn directly on the canvas
  // (instead of using a child View). Thus, we should mirror its position
  // manually.
  gfx::Rect arrow_bounds(GetWidth() - drop_arrow_->width() - kHorizBorderSize,
                         (GetHeight() - drop_arrow_->height()) / 2,
                         drop_arrow_->width(),
                         drop_arrow_->height());
  arrow_bounds.set_x(MirroredLeftPointForRect(arrow_bounds));
  canvas->DrawBitmapInt(*drop_arrow_, arrow_bounds.x(), arrow_bounds.y());
}

bool TitleBarMenuButton::OnMousePressed(const ChromeViews::MouseEvent& e) {
  if (e.GetFlags() & ChromeViews::MouseEvent::EF_IS_DOUBLE_CLICK) {
    if (!HitTest(e.GetLocation()))
      return true;
    title_bar_->CloseWindow();
    return true;
  } else {
    return MenuButton::OnMousePressed(e);
  }
}

////////////////////////////////////////////////////////////////////////////////
//
// SimpleXPFrameTitleBar implementation.
//
////////////////////////////////////////////////////////////////////////////////

SimpleXPFrameTitleBar::SimpleXPFrameTitleBar(SimpleXPFrame* parent)
    : parent_(parent) {
  DCHECK(parent);
  tab_icon_.reset(new TabIconView(this));
  tab_icon_->set_is_light(true);
  menu_button_ = new TitleBarMenuButton(this);
  menu_button_->SetContents(tab_icon_view());
  AddChildView(menu_button_);

  tab_icon_->Update();

  label_ = new ChromeViews::Label();
  label_->SetColor(kTitleBarTextColor);
  label_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
  AddChildView(label_);
}

SimpleXPFrameTitleBar::~SimpleXPFrameTitleBar() {
}

TabContents* SimpleXPFrameTitleBar::GetCurrentTabContents() {
  return parent_->GetCurrentContents();
}

SkBitmap SimpleXPFrameTitleBar::GetFavIcon() {
  // Only use the favicon if we're a web application.
  TabContents* contents = GetCurrentTabContents();
  if (parent_->IsApplication()) {
    TabContents* contents = GetCurrentTabContents();
    WebContents* web_contents = contents->AsWebContents();
    if (web_contents) {
      // If it's a web contents, pull the favicon from the WebApp, and fallback
      // to the icon.
      WebApp* web_app = web_contents->web_app();
      if (web_app && !web_app->GetFavIcon().isNull())
        return web_app->GetFavIcon();
    }
    if (contents) {
      SkBitmap favicon = contents->GetFavIcon();
      if (!favicon.isNull())
        return favicon;
    }
  }

  // Otherwise, use the default icon.
  return SkBitmap();
}

void SimpleXPFrameTitleBar::RunMenu(ChromeViews::View* source,
                                    const CPoint& pt, HWND hwnd) {
  // Make sure we calculate the menu position based on the display bounds of
  // the menu button. The display bounds are different than the actual bounds
  // when the UI layout is RTL and hence we use the mirroring transformation
  // flag. We also adjust the menu position because RTL menus use a different
  // anchor point.
  CPoint p(menu_button_->GetX(APPLY_MIRRORING_TRANSFORMATION),
           menu_button_->GetY() + menu_button_->GetHeight());

  if (UILayoutIsRightToLeft())
    p.x += menu_button_->GetWidth();
  View::ConvertPointToScreen(this, &p);
  parent_->RunMenu(p, hwnd);
}

void SimpleXPFrameTitleBar::Layout() {
  CSize s;
  menu_button_->GetPreferredSize(&s);
  menu_button_->SetBounds(kFavIconMargin, 1 + (GetHeight() - s.cy) / 2,
                          s.cx, s.cy);
  menu_button_->Layout();
  label_->SetBounds(menu_button_->GetX() + menu_button_->GetWidth() +
                    kFavIconPadding, 0,
                    GetWidth() - (menu_button_->GetX() +
                                  menu_button_->GetWidth() + kFavIconPadding),
                    GetHeight());
}

bool SimpleXPFrameTitleBar::WillHandleMouseEvent(int x, int y) {
  // If the locale is RTL, we must query for the bounds of the menu button in
  // a way that returns the mirrored position and not the position set using
  // SetX()/SetBounds().
  CPoint p(x - menu_button_->GetX(APPLY_MIRRORING_TRANSFORMATION),
           y - menu_button_->GetY());
  return menu_button_->HitTest(p);
}

void SimpleXPFrameTitleBar::SetWindowTitle(std::wstring s) {
  if (parent_->IsApplication()) {
    std::wstring t(s);
    Tab::FormatTitleForDisplay(&t);
    label_->SetText(t);
  } else {
    label_->SetText(Browser::ComputePopupTitle(
                        GetCurrentTabContents()->GetURL(), s));
  }
}

void SimpleXPFrameTitleBar::ValidateThrobber() {
  tab_icon_->Update();
  menu_button_->SchedulePaint();
}

void SimpleXPFrameTitleBar::CloseWindow() {
  parent_->Close();
}

void SimpleXPFrameTitleBar::Update() {
  tab_icon_->Update();
}

////////////////////////////////////////////////////////////////////////////////
//
// SimpleXPFrame implementation.
//
////////////////////////////////////////////////////////////////////////////////

// static
SimpleXPFrame* SimpleXPFrame::CreateFrame(const gfx::Rect& bounds,
                                          Browser* browser) {
  SimpleXPFrame* instance = new SimpleXPFrame(browser);
  instance->Create(NULL, bounds.ToRECT(),
                   l10n_util::GetString(IDS_PRODUCT_NAME).c_str());
  instance->InitAfterHWNDCreated();
  instance->SetIsOffTheRecord(browser->profile()->IsOffTheRecord());
  ChromeViews::FocusManager::CreateFocusManager(instance->m_hWnd,
                                                instance->GetRootView());
  return instance;
}

SimpleXPFrame::SimpleXPFrame(Browser* browser)
    : XPFrame(browser),
      title_bar_(NULL),
      location_bar_(NULL) {
}

void SimpleXPFrame::InitAfterHWNDCreated() {
  icon_manager_.reset(new WebAppIconManager(*this));
  XPFrame::InitAfterHWNDCreated();
}

SimpleXPFrame::~SimpleXPFrame() {
}

void SimpleXPFrame::Init() {
  XPFrame::Init();
  if (IsTitleBarVisible()) {
    title_bar_ = new SimpleXPFrameTitleBar(this);
    GetFrameView()->AddChildView(title_bar_);
  }

  location_bar_ = new LocationBarView(browser_->profile(),
                                      browser_->controller(),
                                      browser_->toolbar_model(),
                                      this, true);
  GetFrameView()->AddChildView(location_bar_);
  location_bar_->Init();

  // Constrained popups that were unconstrained will need to set up a
  // throbber.
  UpdateTitleBar();
}

TabContents* SimpleXPFrame::GetCurrentContents() {
  if (browser_)
    return browser_->GetSelectedTabContents();
  else
    return NULL;
}

void SimpleXPFrame::Layout() {
  XPFrame::Layout();
  if (IsTitleBarVisible()) {
    TabContentsContainerView* tccv = GetTabContentsContainer();
    DCHECK(tccv);
    title_bar_->SetBounds(tccv->GetX(), 0,
                          GetButtonXOrigin() - tccv->GetX(),
                          GetContentsYOrigin());
    title_bar_->Layout();
  }

  if (browser_->ShouldDisplayURLField()) {
    TabContentsContainerView* container = GetTabContentsContainer();
    CSize s;
    location_bar_->GetPreferredSize(&s);
    location_bar_->SetBounds(container->GetX() - kLocationBarOffset,
                          container->GetY(),
                          container->GetWidth() + kLocationBarOffset * 2,
                          s.cy);
    container->SetBounds(container->GetX(),
                         location_bar_->GetY() + location_bar_->GetHeight() +
                         kLocationBarSpacing, container->GetWidth(),
                         container->GetHeight() - location_bar_->GetHeight() -
                         1);
    location_bar_->SetVisible(true);
    location_bar_->Layout();
  } else {
    location_bar_->SetVisible(false);
  }
}

LRESULT SimpleXPFrame::OnNCHitTest(const CPoint& pt) {
  if (IsTitleBarVisible()) {
    CPoint p(pt);
    ChromeViews::View::ConvertPointToView(NULL, title_bar_, &p);
    if (!title_bar_->WillHandleMouseEvent(p.x, p.y) &&
        p.x >= 0 && p.y >= kTopResizeBarHeight &&
        p.x < title_bar_->GetWidth() &&
        p.y < title_bar_->GetHeight()) {
      return HTCAPTION;
    }
  }
  return XPFrame::OnNCHitTest(pt);
}

void SimpleXPFrame::SetWindowTitle(const std::wstring& title) {
  if (IsTitleBarVisible())
    title_bar_->SetWindowTitle(title);
  XPFrame::SetWindowTitle(title);
}

void SimpleXPFrame::UpdateTitleBar() {
  if (IsTitleBarVisible()) {
    title_bar_->Update();
    title_bar_->SchedulePaint();
  }
  UpdateLocationBar();
}

void SimpleXPFrame::ValidateThrobber() {
  if (IsTitleBarVisible())
    title_bar_->ValidateThrobber();
}

void SimpleXPFrame::RunMenu(const CPoint& pt, HWND hwnd) {
  browser_->RunSimpleFrameMenu(pt, hwnd);
}

void SimpleXPFrame::ShowTabContents(TabContents* selected_contents) {
  XPFrame::ShowTabContents(selected_contents);

  icon_manager_->SetContents(selected_contents);

  UpdateLocationBar();
}

bool SimpleXPFrame::IsApplication() const {
  return browser_->IsApplication();
}

void SimpleXPFrame::UpdateLocationBar() {
  if (location_bar_ && location_bar_->IsVisible())
    location_bar_->Update(NULL);
}

TabContents* SimpleXPFrame::GetTabContents() {
  return GetCurrentContents();
}

void SimpleXPFrame::OnInputInProgress(bool in_progress) {
}
<commit_msg>Minor alignment tweaks to simple XP frame.<commit_after>// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "chrome/browser/simple_xp_frame.h"

#include "chrome/app/theme/theme_resources.h"
#include "base/string_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents.h"
#include "chrome/browser/tab_contents_container_view.h"
#include "chrome/browser/tabs/tab.h"
#include "chrome/browser/views/location_bar_view.h"
#include "chrome/browser/web_app.h"
#include "chrome/browser/web_app_icon_manager.h"
#include "chrome/browser/web_contents.h"
#include "chrome/common/win_util.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/l10n_util.h"
#include "chrome/views/focus_manager.h"
#include "chrome/views/label.h"
#include "chrome/views/text_field.h"
#include "net/base/net_util.h"
#include "SkBitmap.h"

#include "generated_resources.h"

// The title bar text color.
static const SkColor kTitleBarTextColor = SkColorSetRGB(255, 255, 255);

// How thick is the top resize bar.
static const int kTopResizeBarHeight = 3;

// Left margin on the left side of the favicon.
static const int kFavIconMargin = 1;

// Label offset.
static const int kLabelVerticalOffset = -1;

// Padding between the favicon and the text.
static const int kFavIconPadding = 4;

// Background color for the button hot state.
static const SkColor kHotColor = SkColorSetRGB(49, 106, 197);

// distance between contents and drop arrow.
static const int kHorizMargin = 4;

// Border all around the menu.
static const int kHorizBorderSize = 2;
static const int kVertBorderSize = 1;

// How much wider or shorter the location bar is relative to the client area.
static const int kLocationBarOffset = 2;
// Spacing between the location bar and the content area.
static const int kLocationBarSpacing = 1;

////////////////////////////////////////////////////////////////////////////////
//
// TitleBarMenuButton implementation.
//
////////////////////////////////////////////////////////////////////////////////
TitleBarMenuButton::TitleBarMenuButton(SimpleXPFrameTitleBar* title_bar)
    : ChromeViews::MenuButton(L"", title_bar, false),
      contents_(NULL),
      title_bar_(title_bar) {
  ResourceBundle &rb = ResourceBundle::GetSharedInstance();
  drop_arrow_ = rb.GetBitmapNamed(IDR_APP_DROPARROW);
}

TitleBarMenuButton::~TitleBarMenuButton() {
}

void TitleBarMenuButton::SetContents(ChromeViews::View* contents) {
  contents_ = contents;
}

void TitleBarMenuButton::GetPreferredSize(CSize *out) {
  if (contents_)
    contents_->GetPreferredSize(out);
  else
    out->cx = out->cy = 0;

  out->cx += drop_arrow_->width() + kHorizMargin + (2 * kHorizBorderSize);
  out->cy = std::max(drop_arrow_->height(), static_cast<int>(out->cy));
  out->cy += (2 * kVertBorderSize);
}

void TitleBarMenuButton::Paint(ChromeCanvas* canvas) {
  if (GetState() == TextButton::BS_HOT ||
      GetState() == TextButton::BS_PUSHED || menu_visible_) {
    canvas->FillRectInt(kHotColor, 0, 0, GetWidth(), GetHeight());
  }

  if (contents_) {
    CSize s;
    contents_->GetPreferredSize(&s);
    // Note: we use a floating view in this case because we never want the
    // contents to process any event.
    PaintFloatingView(canvas,
                      contents_,
                      kVertBorderSize,
                      (GetHeight() - s.cy) / 2,
                      GetWidth() - kHorizMargin - drop_arrow_->width() -
                      (2 * kHorizBorderSize),
                      s.cy);
  }

  // We can not use the mirroring infrastructure in ChromeViews in order to
  // mirror the drop down arrow because is is drawn directly on the canvas
  // (instead of using a child View). Thus, we should mirror its position
  // manually.
  gfx::Rect arrow_bounds(GetWidth() - drop_arrow_->width() - kHorizBorderSize,
                         (GetHeight() - drop_arrow_->height()) / 2,
                         drop_arrow_->width(),
                         drop_arrow_->height());
  arrow_bounds.set_x(MirroredLeftPointForRect(arrow_bounds));
  canvas->DrawBitmapInt(*drop_arrow_, arrow_bounds.x(), arrow_bounds.y());
}

bool TitleBarMenuButton::OnMousePressed(const ChromeViews::MouseEvent& e) {
  if (e.GetFlags() & ChromeViews::MouseEvent::EF_IS_DOUBLE_CLICK) {
    if (!HitTest(e.GetLocation()))
      return true;
    title_bar_->CloseWindow();
    return true;
  } else {
    return MenuButton::OnMousePressed(e);
  }
}

////////////////////////////////////////////////////////////////////////////////
//
// SimpleXPFrameTitleBar implementation.
//
////////////////////////////////////////////////////////////////////////////////

SimpleXPFrameTitleBar::SimpleXPFrameTitleBar(SimpleXPFrame* parent)
    : parent_(parent) {
  DCHECK(parent);
  tab_icon_.reset(new TabIconView(this));
  tab_icon_->set_is_light(true);
  menu_button_ = new TitleBarMenuButton(this);
  menu_button_->SetContents(tab_icon_view());
  AddChildView(menu_button_);

  tab_icon_->Update();

  label_ = new ChromeViews::Label();
  label_->SetColor(kTitleBarTextColor);
  label_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
  AddChildView(label_);
}

SimpleXPFrameTitleBar::~SimpleXPFrameTitleBar() {
}

TabContents* SimpleXPFrameTitleBar::GetCurrentTabContents() {
  return parent_->GetCurrentContents();
}

SkBitmap SimpleXPFrameTitleBar::GetFavIcon() {
  // Only use the favicon if we're a web application.
  TabContents* contents = GetCurrentTabContents();
  if (parent_->IsApplication()) {
    TabContents* contents = GetCurrentTabContents();
    WebContents* web_contents = contents->AsWebContents();
    if (web_contents) {
      // If it's a web contents, pull the favicon from the WebApp, and fallback
      // to the icon.
      WebApp* web_app = web_contents->web_app();
      if (web_app && !web_app->GetFavIcon().isNull())
        return web_app->GetFavIcon();
    }
    if (contents) {
      SkBitmap favicon = contents->GetFavIcon();
      if (!favicon.isNull())
        return favicon;
    }
  }

  // Otherwise, use the default icon.
  return SkBitmap();
}

void SimpleXPFrameTitleBar::RunMenu(ChromeViews::View* source,
                                    const CPoint& pt, HWND hwnd) {
  // Make sure we calculate the menu position based on the display bounds of
  // the menu button. The display bounds are different than the actual bounds
  // when the UI layout is RTL and hence we use the mirroring transformation
  // flag. We also adjust the menu position because RTL menus use a different
  // anchor point.
  CPoint p(menu_button_->GetX(APPLY_MIRRORING_TRANSFORMATION),
           menu_button_->GetY() + menu_button_->GetHeight());

  if (UILayoutIsRightToLeft())
    p.x += menu_button_->GetWidth();
  View::ConvertPointToScreen(this, &p);
  parent_->RunMenu(p, hwnd);
}

void SimpleXPFrameTitleBar::Layout() {
  CSize s;
  menu_button_->GetPreferredSize(&s);
  menu_button_->SetBounds(kFavIconMargin, (GetHeight() - s.cy) / 2,
                          s.cx, s.cy);
  menu_button_->Layout();
  label_->SetBounds(menu_button_->GetX() + menu_button_->GetWidth() +
                    kFavIconPadding, kLabelVerticalOffset,
                    GetWidth() - (menu_button_->GetX() +
                                  menu_button_->GetWidth() + kFavIconPadding),
                    GetHeight());
}

bool SimpleXPFrameTitleBar::WillHandleMouseEvent(int x, int y) {
  // If the locale is RTL, we must query for the bounds of the menu button in
  // a way that returns the mirrored position and not the position set using
  // SetX()/SetBounds().
  CPoint p(x - menu_button_->GetX(APPLY_MIRRORING_TRANSFORMATION),
           y - menu_button_->GetY());
  return menu_button_->HitTest(p);
}

void SimpleXPFrameTitleBar::SetWindowTitle(std::wstring s) {
  if (parent_->IsApplication()) {
    std::wstring t(s);
    Tab::FormatTitleForDisplay(&t);
    label_->SetText(t);
  } else {
    label_->SetText(Browser::ComputePopupTitle(
                        GetCurrentTabContents()->GetURL(), s));
  }
}

void SimpleXPFrameTitleBar::ValidateThrobber() {
  tab_icon_->Update();
  menu_button_->SchedulePaint();
}

void SimpleXPFrameTitleBar::CloseWindow() {
  parent_->Close();
}

void SimpleXPFrameTitleBar::Update() {
  tab_icon_->Update();
}

////////////////////////////////////////////////////////////////////////////////
//
// SimpleXPFrame implementation.
//
////////////////////////////////////////////////////////////////////////////////

// static
SimpleXPFrame* SimpleXPFrame::CreateFrame(const gfx::Rect& bounds,
                                          Browser* browser) {
  SimpleXPFrame* instance = new SimpleXPFrame(browser);
  instance->Create(NULL, bounds.ToRECT(),
                   l10n_util::GetString(IDS_PRODUCT_NAME).c_str());
  instance->InitAfterHWNDCreated();
  instance->SetIsOffTheRecord(browser->profile()->IsOffTheRecord());
  ChromeViews::FocusManager::CreateFocusManager(instance->m_hWnd,
                                                instance->GetRootView());
  return instance;
}

SimpleXPFrame::SimpleXPFrame(Browser* browser)
    : XPFrame(browser),
      title_bar_(NULL),
      location_bar_(NULL) {
}

void SimpleXPFrame::InitAfterHWNDCreated() {
  icon_manager_.reset(new WebAppIconManager(*this));
  XPFrame::InitAfterHWNDCreated();
}

SimpleXPFrame::~SimpleXPFrame() {
}

void SimpleXPFrame::Init() {
  XPFrame::Init();
  if (IsTitleBarVisible()) {
    title_bar_ = new SimpleXPFrameTitleBar(this);
    GetFrameView()->AddChildView(title_bar_);
  }

  location_bar_ = new LocationBarView(browser_->profile(),
                                      browser_->controller(),
                                      browser_->toolbar_model(),
                                      this, true);
  GetFrameView()->AddChildView(location_bar_);
  location_bar_->Init();

  // Constrained popups that were unconstrained will need to set up a
  // throbber.
  UpdateTitleBar();
}

TabContents* SimpleXPFrame::GetCurrentContents() {
  if (browser_)
    return browser_->GetSelectedTabContents();
  else
    return NULL;
}

void SimpleXPFrame::Layout() {
  XPFrame::Layout();
  if (IsTitleBarVisible()) {
    TabContentsContainerView* tccv = GetTabContentsContainer();
    DCHECK(tccv);
    title_bar_->SetBounds(tccv->GetX(), 0,
                          GetButtonXOrigin() - tccv->GetX(),
                          GetContentsYOrigin());
    title_bar_->Layout();
  }

  if (browser_->ShouldDisplayURLField()) {
    TabContentsContainerView* container = GetTabContentsContainer();
    CSize s;
    location_bar_->GetPreferredSize(&s);
    location_bar_->SetBounds(container->GetX() - kLocationBarOffset,
                          container->GetY(),
                          container->GetWidth() + kLocationBarOffset * 2,
                          s.cy);
    container->SetBounds(container->GetX(),
                         location_bar_->GetY() + location_bar_->GetHeight() +
                         kLocationBarSpacing, container->GetWidth(),
                         container->GetHeight() - location_bar_->GetHeight() -
                         1);
    location_bar_->SetVisible(true);
    location_bar_->Layout();
  } else {
    location_bar_->SetVisible(false);
  }
}

LRESULT SimpleXPFrame::OnNCHitTest(const CPoint& pt) {
  if (IsTitleBarVisible()) {
    CPoint p(pt);
    ChromeViews::View::ConvertPointToView(NULL, title_bar_, &p);
    if (!title_bar_->WillHandleMouseEvent(p.x, p.y) &&
        p.x >= 0 && p.y >= kTopResizeBarHeight &&
        p.x < title_bar_->GetWidth() &&
        p.y < title_bar_->GetHeight()) {
      return HTCAPTION;
    }
  }
  return XPFrame::OnNCHitTest(pt);
}

void SimpleXPFrame::SetWindowTitle(const std::wstring& title) {
  if (IsTitleBarVisible())
    title_bar_->SetWindowTitle(title);
  XPFrame::SetWindowTitle(title);
}

void SimpleXPFrame::UpdateTitleBar() {
  if (IsTitleBarVisible()) {
    title_bar_->Update();
    title_bar_->SchedulePaint();
  }
  UpdateLocationBar();
}

void SimpleXPFrame::ValidateThrobber() {
  if (IsTitleBarVisible())
    title_bar_->ValidateThrobber();
}

void SimpleXPFrame::RunMenu(const CPoint& pt, HWND hwnd) {
  browser_->RunSimpleFrameMenu(pt, hwnd);
}

void SimpleXPFrame::ShowTabContents(TabContents* selected_contents) {
  XPFrame::ShowTabContents(selected_contents);

  icon_manager_->SetContents(selected_contents);

  UpdateLocationBar();
}

bool SimpleXPFrame::IsApplication() const {
  return browser_->IsApplication();
}

void SimpleXPFrame::UpdateLocationBar() {
  if (location_bar_ && location_bar_->IsVisible())
    location_bar_->Update(NULL);
}

TabContents* SimpleXPFrame::GetTabContents() {
  return GetCurrentContents();
}

void SimpleXPFrame::OnInputInProgress(bool in_progress) {
}
<|endoftext|>


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

#include "base/file_path.h"
#include "base/values.h"
#include "chrome/common/common_param_traits.h"
#include "chrome/common/indexed_db_key.h"
#include "chrome/common/serialized_script_value.h"

#define IPC_MESSAGE_IMPL
#include "chrome/common/utility_messages.h"<commit_msg>Add missing new line<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/file_path.h"
#include "base/values.h"
#include "chrome/common/common_param_traits.h"
#include "chrome/common/indexed_db_key.h"
#include "chrome/common/serialized_script_value.h"

#define IPC_MESSAGE_IMPL
#include "chrome/common/utility_messages.h"
<|endoftext|>


<commit_before>#include <sstream>
#include "Partitioning.h"
using namespace std;

double RepairDocumentPartition::getScore(ostream& os)
{
	double term;
	double sum(0);
	double totalFragSize(0);
	for (unordered_map<string, FragInfo>::iterator it = uniqueFrags.begin(); it != uniqueFrags.end(); it++)
	{
		term = it->second.count * it->second.fragSize;
		sum += term;
		totalFragSize += it->second.fragSize;
	}
	if (uniqueFrags.size() == 0) return 0.0;

	double avgFragSize = totalFragSize / uniqueFrags.size();
	return sum / (uniqueFrags.size() * avgFragSize);
}

SortedByOffsetNodeSet RepairDocumentPartition::getNodesNthLevelDown(RepairTreeNode* root, unsigned numLevelsDown, SortedByOffsetNodeSet& nodes)
{
	if (!root) return nodes;
	if (numLevelsDown < 1) return nodes;
	if (numLevelsDown == 1)
	{
		if (root->getLeftChild() && root->getRightChild())
		{
			nodes.insert(root->getLeftChild());
			nodes.insert(root->getRightChild());
		}
		return nodes;
	}
	if (root->getLeftChild() && root->getRightChild())
	{
		this->getNodesNthLevelDown(root->getLeftChild(), numLevelsDown - 1, nodes);
		this->getNodesNthLevelDown(root->getRightChild(), numLevelsDown - 1, nodes);
	}
	return nodes;
}

int RepairDocumentPartition::getAssociationLocation(unsigned symbol)
{
	if (memoizedAssociationLocations.count(symbol))
		return memoizedAssociationLocations[symbol];

	// It wasn't saved, so search for it, and save it for next time
	int loc = binarySearch(symbol, associations, 0, associations.size());
	memoizedAssociationLocations[symbol] = loc;

	return loc;
}

double RepairDocumentPartition::getSubsetScore(SortedByOffsetNodeSet subset)
{
	/* AVG */
	// unsigned sum(0);
	// for (SortedByOffsetNodeSet::iterator it = subset.begin(); it != subset.end(); it++)
	// {
	// 	RepairTreeNode* currNode = *it;
	// 	unsigned currScore = 1;
	// 	int loc = getAssociationLocation(currNode->getSymbol());
	// 	if (loc != -1)
	// 	{
	// 		Association a = associations[loc];
	// 		currScore = currNode->getSize() * a.getFreq();
	// 	}
	// 	sum += currScore;
	// }
	// if (subset.size() == 0 || sum == 0) return 0.0;
	// return ((double) sum) / ((double)subset.size());

	/* MAX */
	double currMax(0);
	for (SortedByOffsetNodeSet::iterator it = subset.begin(); it != subset.end(); it++)
	{
		RepairTreeNode* currNode = *it;
		double currScore = 1.0;
		int loc = getAssociationLocation(currNode->getSymbol());
		if (loc != -1)
		{
			Association a = associations[loc];
			currScore = currNode->getSize() * a.getFreq();
		}
		if (currScore > currMax)
		{
			currMax = currScore;
		}
	}
	if (subset.size() == 0 || currMax == 0) return 0.0;
	return currMax;
}

SortedByOffsetNodeSet RepairDocumentPartition::getBestSubset(RepairTreeNode* node)
{
	SortedByOffsetNodeSet nodes = SortedByOffsetNodeSet();
	if (!node)
		return nodes;

	double myScore = 1.0;
	int loc = getAssociationLocation(node->getSymbol());
	if (loc != -1)
	{
		Association a = associations[loc];
		myScore = node->getSize() * a.getFreq();
	}

	// node is a terminal
	if (!node->getLeftChild())
	{
		nodes.insert(node);
		return nodes;
	}

	RepairTreeNode* leftChild = node->getLeftChild();
	RepairTreeNode* rightChild = node->getRightChild();

	SortedByOffsetNodeSet leftSubset = getBestSubset(leftChild);
	SortedByOffsetNodeSet rightSubset = getBestSubset(rightChild);

	double leftScore = getSubsetScore(leftSubset);
	double rightScore = getSubsetScore(rightSubset);

	// TODO try changing to max(leftScore, rightScore)
	double childrenScore = fragmentationCoefficient * (leftScore + rightScore); // Coefficient for fragmenting

	if (myScore >= childrenScore)
	{
		nodes.insert(node);
		return nodes;
	}

	nodes.insert(leftSubset.begin(), leftSubset.end());
	nodes.insert(rightSubset.begin(), rightSubset.end());
	return nodes;
}

unsigned RepairDocumentPartition::getPartitioningOneVersion(RepairTreeNode* root, unsigned numLevelsDown, unsigned* bounds, unsigned minFragSize, unsigned versionSize)
{
	SortedByOffsetNodeSet nodes = SortedByOffsetNodeSet();
	switch (this->method)
	{
		case RepairDocumentPartition::NAIVE: nodes = getNodesNthLevelDown(root, numLevelsDown, nodes);
		    break;
		case RepairDocumentPartition::GREEDY: nodes = getBestSubset(root);
		    break;
		// default is greedy
		default: nodes = getBestSubset(root);
		    break;
	}

	unsigned prevVal(0); // the previous node's index in the file
	unsigned currVal(0); // the current node's index in the file
	unsigned diff(0); // the difference between consecutive indexes (a large value signifies a good fragment)
	unsigned numFrags(0); // the number of fragments (gets incremented in the following loop)
	RepairTreeNode* previous(NULL);

	// We know the first fragment is always at the beginning of the file, and we'll skip the first node in the loop below
	bounds[0] = 0;
	++numFrags;

	// cerr << "Version Start" << endl;
	for (auto it = nodes.begin(); it != nodes.end(); ++it)
	{

		if (numFrags > MAX_NUM_FRAGMENTS_PER_VERSION - 1) {
			break;
		}

		RepairTreeNode* current = *it;

		// cerr << "Symbol: " << current->getSymbol() << endl;
		// cerr << current->getOffset() << ",";

		if (!previous) {
			previous = current;
			continue;
		}

		prevVal = previous->getOffset();
		currVal = current->getOffset();

		diff = currVal - prevVal;
		if (diff >= minFragSize)
		{
			// These offsets are already sorted (see the comparator at the top)
			bounds[numFrags] = current->getOffset();
			numFrags++;
		}

		// Update previous to point to this node now that we're done with it
		previous = current;
	}
	// cerr << endl << endl;
	// system("pause");

	// Calculate the last diff so that the last fragment obeys the minFragSize rule
	if (nodes.size() >= 1)
	{
		unsigned lastDiff = versionSize - bounds[numFrags - 1];
		if (lastDiff >= minFragSize)
		{
			// Our last fragment is ok, just add the position at the end of the file
			bounds[numFrags] = versionSize;
			numFrags++;
		}
		else
		{
			// Our last fragment is too small, replace the last offset we had with the position at the end of the file
			bounds[numFrags - 1] = versionSize;
		}
	}

	// TODO Handle this
	if (numFrags > MAX_NUM_FRAGMENTS_PER_VERSION)
	{
		// Fail or try a partitioning that won't fragment so much
	}

	return numFrags;
}

void RepairDocumentPartition::setPartitioningsAllVersions(unsigned numLevelsDown, unsigned minFragSize)
{
	unsigned versionOffset(0); // after the loop, is set to the total number of fragments (also the size of the starts array)
	unsigned numFragments(0); // will be reused in the loop for the number of fragments in each version

	RepairTreeNode* rootForThisVersion = NULL;

	// Iterate over all versions
	for (unsigned i = 0; i < this->versionData.size(); i++)
	{
		rootForThisVersion = this->versionData[i].getRootNode();

		// Do the partitioning for one version, and store the number of fragments
		numFragments = getPartitioningOneVersion(rootForThisVersion, numLevelsDown,
			&(this->offsets[versionOffset]), minFragSize, versionData[i].getVersionSize());
		versionOffset += numFragments;
		this->versionSizes[i] = numFragments;
	}
}

void RepairDocumentPartition::setFragmentInfo(const vector<vector<unsigned> >& versions, ostream& os, bool print)
{
	os << "*** Fragments ***" << endl;

	unsigned start, end, theID, fragSize;
	string word;
	vector<unsigned> wordIDs;

	MD5 md5;
	char* concatOfWordIDs;

	unsigned totalCountFragments(0);

	// Iterate over versions
	for (unsigned v = 0; v < versions.size(); v++)
	{
		wordIDs = versions[v]; // all the word IDs for version v
		this->fragments.push_back(vector<FragInfo >());
		if (print)
			os << "Version " << v << endl;

		// One version: iterate over the words in that version
		for (unsigned i = 0; i < this->versionSizes[v] - 1; i++)
		{
			start = this->offsets[totalCountFragments + i];
			end = this->offsets[totalCountFragments + i + 1];
			fragSize = end - start;
			if (print)
				os << "Fragment " << i << ": ";
			stringstream ss;
			for (unsigned j = start; j < end; j++)
			{
				theID = wordIDs[j];

				// Need a delimiter to ensure uniqueness (1,2,3 is different from 12,3)
				ss << theID << ",";
			}

			// Store the concatenation of the IDs for this fragment
			concatOfWordIDs = new char[MAX_FRAG_LENGTH];
			strcpy(concatOfWordIDs, ss.str().c_str());

			// Calculate the hash of the fragment
			string hash; // = new char[128]; // md5 produces 128 bit output
			hash = md5.digestString(concatOfWordIDs);
			this->fragments[v].push_back(FragInfo(0, 0, fragSize, hash));
			ss.str("");

			if (print)
				os << "hash (" << hash << ")" << endl;
			delete [] concatOfWordIDs;
			concatOfWordIDs = NULL;
		}
		totalCountFragments += this->versionSizes[v];
		if (print)
			os << endl;
	}
}

void RepairDocumentPartition::updateUniqueFragmentHashMap()
{
	unordered_map<string, FragInfo>::iterator it;
	for (size_t i = 0; i < this->fragments.size(); i++)
	{
		for (size_t j = 0; j < this->fragments[i].size(); j++)
		{
			FragInfo frag = this->fragments[i][j];
			string myHash = frag.hash;

			unsigned theID;
			if (this->uniqueFrags.count(myHash))
			{
				// Found it, so use its ID
				theID = this->uniqueFrags[myHash].id;
				this->uniqueFrags[myHash].count++;
			}
			else
			{
				// Didn't find it, give it an ID
				theID = nextFragID();
				frag.id = theID;
				frag.count = 1;
				this->uniqueFrags[myHash] = frag;
			}
		}
	}
}

void RepairDocumentPartition::writeResults(const vector<vector<unsigned> >& versions, unordered_map<unsigned, string>& IDsToWords,
	const string& outFilename, bool printFragments, bool printAssociations)
{
	ofstream os(outFilename.c_str());

	os << "Results of re-pair partitioning..." << endl << endl;
	os << "*** Fragment boundaries ***" << endl;

	unsigned totalCountFragments(0);
	unsigned diff(0);
	unsigned numVersions = versions.size();
	for (unsigned v = 0; v < numVersions; v++)
	{
		unsigned numFragsInVersion = versionSizes[v];

		if (numFragsInVersion < 1)
		{
			continue;
		}
		os << "Version " << v << endl;
		for (unsigned i = 0; i < numFragsInVersion - 1; i++)
		{
			if (i < numFragsInVersion - 1)
			{
				unsigned currOffset = offsets[totalCountFragments + i];
				unsigned nextOffset = offsets[totalCountFragments + i + 1];
				diff = nextOffset - currOffset;
			}
			else
			{
				diff = 0;
			}

			os << "Fragment " << i << ": " << offsets[totalCountFragments + i] << "-" <<
				offsets[totalCountFragments + i + 1] << " (frag size: " << diff << ")" << endl;
		}
		totalCountFragments += numFragsInVersion;
		os << endl;
	}

	// os << "Number of fragment boundaries: " << starts.size() << endl;
	// os << "Number of fragments: " << (starts.size() - 1) << endl << endl;

	// this->setFragmentInfo(versions, os, printFragments);

	// Assign fragment IDs and stick them in a hashmap
	unordered_map<string, FragInfo> uniqueFrags;
	this->updateUniqueFragmentHashMap();

	// Now decide on the score for this partitioning
	double score = this->getScore(os);
	os << "Score: " << score << endl;
	os.close();
}<commit_msg>debug<commit_after>#include <sstream>
#include "Partitioning.h"
using namespace std;

double RepairDocumentPartition::getScore(ostream& os)
{
	double term;
	double sum(0);
	double totalFragSize(0);
	for (unordered_map<string, FragInfo>::iterator it = uniqueFrags.begin(); it != uniqueFrags.end(); it++)
	{
		term = it->second.count * it->second.fragSize;
		sum += term;
		totalFragSize += it->second.fragSize;
	}
	if (uniqueFrags.size() == 0) return 0.0;

	double avgFragSize = totalFragSize / uniqueFrags.size();
	return sum / (uniqueFrags.size() * avgFragSize);
}

SortedByOffsetNodeSet RepairDocumentPartition::getNodesNthLevelDown(RepairTreeNode* root, unsigned numLevelsDown, SortedByOffsetNodeSet& nodes)
{
	if (!root) return nodes;
	if (numLevelsDown < 1) return nodes;
	if (numLevelsDown == 1)
	{
		if (root->getLeftChild() && root->getRightChild())
		{
			nodes.insert(root->getLeftChild());
			nodes.insert(root->getRightChild());
		}
		return nodes;
	}
	if (root->getLeftChild() && root->getRightChild())
	{
		this->getNodesNthLevelDown(root->getLeftChild(), numLevelsDown - 1, nodes);
		this->getNodesNthLevelDown(root->getRightChild(), numLevelsDown - 1, nodes);
	}
	return nodes;
}

int RepairDocumentPartition::getAssociationLocation(unsigned symbol)
{
	if (memoizedAssociationLocations.count(symbol))
		return memoizedAssociationLocations[symbol];

	// It wasn't saved, so search for it, and save it for next time
	int loc = binarySearch(symbol, associations, 0, associations.size());
	memoizedAssociationLocations[symbol] = loc;

	return loc;
}

double RepairDocumentPartition::getSubsetScore(SortedByOffsetNodeSet subset)
{
	/* AVG */
	// unsigned sum(0);
	// for (SortedByOffsetNodeSet::iterator it = subset.begin(); it != subset.end(); it++)
	// {
	// 	RepairTreeNode* currNode = *it;
	// 	unsigned currScore = 1;
	// 	int loc = getAssociationLocation(currNode->getSymbol());
	// 	if (loc != -1)
	// 	{
	// 		Association a = associations[loc];
	// 		currScore = currNode->getSize() * a.getFreq();
	// 	}
	// 	sum += currScore;
	// }
	// if (subset.size() == 0 || sum == 0) return 0.0;
	// return ((double) sum) / ((double)subset.size());

	/* MAX */
	double currMax(0);
	for (SortedByOffsetNodeSet::iterator it = subset.begin(); it != subset.end(); it++)
	{
		RepairTreeNode* currNode = *it;
		double currScore = 1.0;
		int loc = getAssociationLocation(currNode->getSymbol());
		if (loc != -1)
		{
			Association a = associations[loc];
			currScore = currNode->getSize() * a.getFreq();
		}
		if (currScore > currMax)
		{
			currMax = currScore;
		}
	}
	if (subset.size() == 0 || currMax == 0) return 0.0;
	return currMax;
}

SortedByOffsetNodeSet RepairDocumentPartition::getBestSubset(RepairTreeNode* node)
{
	SortedByOffsetNodeSet nodes = SortedByOffsetNodeSet();
	if (!node)
		return nodes;

	double myScore = 1.0;
	int loc = getAssociationLocation(node->getSymbol());
	if (loc != -1)
	{
		Association a = associations[loc];
		myScore = node->getSize() * a.getFreq();
	}

	// node is a terminal
	if (!node->getLeftChild())
	{
		nodes.insert(node);
		return nodes;
	}

	RepairTreeNode* leftChild = node->getLeftChild();
	RepairTreeNode* rightChild = node->getRightChild();

	SortedByOffsetNodeSet leftSubset = getBestSubset(leftChild);
	SortedByOffsetNodeSet rightSubset = getBestSubset(rightChild);

	double leftScore = getSubsetScore(leftSubset);
	double rightScore = getSubsetScore(rightSubset);

	// TODO try changing to max(leftScore, rightScore)
	double childrenScore = fragmentationCoefficient * (leftScore + rightScore); // Coefficient for fragmenting

	if (myScore >= childrenScore)
	{
		nodes.insert(node);
		return nodes;
	}

	nodes.insert(leftSubset.begin(), leftSubset.end());
	nodes.insert(rightSubset.begin(), rightSubset.end());
	return nodes;
}

unsigned RepairDocumentPartition::getPartitioningOneVersion(RepairTreeNode* root, unsigned numLevelsDown, unsigned* bounds, unsigned minFragSize, unsigned versionSize)
{
	SortedByOffsetNodeSet nodes = SortedByOffsetNodeSet();
	switch (this->method)
	{
		case RepairDocumentPartition::NAIVE: nodes = getNodesNthLevelDown(root, numLevelsDown, nodes);
		    break;
		case RepairDocumentPartition::GREEDY: nodes = getBestSubset(root);
		    break;
		// default is greedy
		default: nodes = getBestSubset(root);
		    break;
	}

	unsigned prevVal(0); // the previous node's index in the file
	unsigned currVal(0); // the current node's index in the file
	unsigned diff(0); // the difference between consecutive indexes (a large value signifies a good fragment)
	unsigned numFrags(0); // the number of fragments (gets incremented in the following loop)
	RepairTreeNode* previous(NULL);

	// We know the first fragment is always at the beginning of the file, and we'll skip the first node in the loop below
	bounds[0] = 0;
	++numFrags;

	// cerr << "Version Start" << endl;
	for (auto it = nodes.begin(); it != nodes.end(); ++it)
	{

		if (numFrags > MAX_NUM_FRAGMENTS_PER_VERSION - 1) {
			break;
		}

		RepairTreeNode* current = *it;

		// cerr << "Symbol: " << current->getSymbol() << endl;
		// cerr << current->getOffset() << ",";

		if (!previous) {
			previous = current;
			continue;
		}

		prevVal = previous->getOffset();
		currVal = current->getOffset();

		diff = currVal - prevVal;
		if (diff >= minFragSize)
		{
			// These offsets are already sorted (see the comparator at the top)
			bounds[numFrags] = current->getOffset();
			numFrags++;
		}

		// Update previous to point to this node now that we're done with it
		previous = current;
	}
	// cerr << endl << endl;
	// system("pause");

	// Calculate the last diff so that the last fragment obeys the minFragSize rule
	if (nodes.size() >= 1)
	{
		unsigned lastDiff = versionSize - bounds[numFrags - 1];
		if (lastDiff >= minFragSize)
		{
			// Our last fragment is ok, just add the position at the end of the file
			bounds[numFrags] = versionSize;
			numFrags++;
		}
		else
		{
			// Our last fragment is too small, replace the last offset we had with the position at the end of the file
			bounds[numFrags - 1] = versionSize;
		}
	}

	// TODO Handle this
	if (numFrags > MAX_NUM_FRAGMENTS_PER_VERSION)
	{
		// Fail or try a partitioning that won't fragment so much
	}

	return numFrags;
}

void RepairDocumentPartition::setPartitioningsAllVersions(unsigned numLevelsDown, unsigned minFragSize)
{
	unsigned versionOffset(0); // after the loop, is set to the total number of fragments (also the size of the starts array)
	unsigned numFragments(0); // will be reused in the loop for the number of fragments in each version

	RepairTreeNode* rootForThisVersion = NULL;

	// Iterate over all versions
	for (unsigned i = 0; i < this->versionData.size(); i++)
	{
		rootForThisVersion = this->versionData[i].getRootNode();

		if (i == 202) {
			cout << "cacaw!" << endl;
		}
		// Do the partitioning for one version, and store the number of fragments
		numFragments = getPartitioningOneVersion(rootForThisVersion, numLevelsDown,
			&(this->offsets[versionOffset]), minFragSize, versionData[i].getVersionSize());
		versionOffset += numFragments;
		this->versionSizes[i] = numFragments;
	}
}

void RepairDocumentPartition::setFragmentInfo(const vector<vector<unsigned> >& versions, ostream& os, bool print)
{
	os << "*** Fragments ***" << endl;

	unsigned start, end, theID, fragSize;
	string word;
	vector<unsigned> wordIDs;

	MD5 md5;
	char* concatOfWordIDs;

	unsigned totalCountFragments(0);

	// Iterate over versions
	for (unsigned v = 0; v < versions.size(); v++)
	{
		wordIDs = versions[v]; // all the word IDs for version v
		this->fragments.push_back(vector<FragInfo >());
		if (print)
			os << "Version " << v << endl;

		// One version: iterate over the words in that version
		for (unsigned i = 0; i < this->versionSizes[v] - 1; i++)
		{
			start = this->offsets[totalCountFragments + i];
			end = this->offsets[totalCountFragments + i + 1];
			fragSize = end - start;
			if (print)
				os << "Fragment " << i << ": ";
			stringstream ss;
			for (unsigned j = start; j < end; j++)
			{
				theID = wordIDs[j];

				// Need a delimiter to ensure uniqueness (1,2,3 is different from 12,3)
				ss << theID << ",";
			}

			// Store the concatenation of the IDs for this fragment
			concatOfWordIDs = new char[MAX_FRAG_LENGTH];
			strcpy(concatOfWordIDs, ss.str().c_str());

			// Calculate the hash of the fragment
			string hash; // = new char[128]; // md5 produces 128 bit output
			hash = md5.digestString(concatOfWordIDs);
			this->fragments[v].push_back(FragInfo(0, 0, fragSize, hash));
			ss.str("");

			if (print)
				os << "hash (" << hash << ")" << endl;
			delete [] concatOfWordIDs;
			concatOfWordIDs = NULL;
		}
		totalCountFragments += this->versionSizes[v];
		if (print)
			os << endl;
	}
}

void RepairDocumentPartition::updateUniqueFragmentHashMap()
{
	unordered_map<string, FragInfo>::iterator it;
	for (size_t i = 0; i < this->fragments.size(); i++)
	{
		for (size_t j = 0; j < this->fragments[i].size(); j++)
		{
			FragInfo frag = this->fragments[i][j];
			string myHash = frag.hash;

			unsigned theID;
			if (this->uniqueFrags.count(myHash))
			{
				// Found it, so use its ID
				theID = this->uniqueFrags[myHash].id;
				this->uniqueFrags[myHash].count++;
			}
			else
			{
				// Didn't find it, give it an ID
				theID = nextFragID();
				frag.id = theID;
				frag.count = 1;
				this->uniqueFrags[myHash] = frag;
			}
		}
	}
}

void RepairDocumentPartition::writeResults(const vector<vector<unsigned> >& versions, unordered_map<unsigned, string>& IDsToWords,
	const string& outFilename, bool printFragments, bool printAssociations)
{
	ofstream os(outFilename.c_str());

	os << "Results of re-pair partitioning..." << endl << endl;
	os << "*** Fragment boundaries ***" << endl;

	unsigned totalCountFragments(0);
	unsigned diff(0);
	unsigned numVersions = versions.size();
	for (unsigned v = 0; v < numVersions; v++)
	{
		unsigned numFragsInVersion = versionSizes[v];

		if (numFragsInVersion < 1)
		{
			continue;
		}
		os << "Version " << v << endl;
		for (unsigned i = 0; i < numFragsInVersion - 1; i++)
		{
			if (i < numFragsInVersion - 1)
			{
				unsigned currOffset = offsets[totalCountFragments + i];
				unsigned nextOffset = offsets[totalCountFragments + i + 1];
				diff = nextOffset - currOffset;
			}
			else
			{
				diff = 0;
			}

			os << "Fragment " << i << ": " << offsets[totalCountFragments + i] << "-" <<
				offsets[totalCountFragments + i + 1] << " (frag size: " << diff << ")" << endl;
		}
		totalCountFragments += numFragsInVersion;
		os << endl;
	}

	// os << "Number of fragment boundaries: " << starts.size() << endl;
	// os << "Number of fragments: " << (starts.size() - 1) << endl << endl;

	// this->setFragmentInfo(versions, os, printFragments);

	// Assign fragment IDs and stick them in a hashmap
	unordered_map<string, FragInfo> uniqueFrags;
	this->updateUniqueFragmentHashMap();

	// Now decide on the score for this partitioning
	double score = this->getScore(os);
	os << "Score: " << score << endl;
	os.close();
}<|endoftext|>


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

#include "chrome_frame/npapi_url_request.h"

#include "base/string_number_conversions.h"
#include "chrome_frame/np_browser_functions.h"
#include "chrome_frame/np_utils.h"
#include "net/base/net_errors.h"

class NPAPIUrlRequest : public PluginUrlRequest {
 public:
  explicit NPAPIUrlRequest(NPP instance);
  ~NPAPIUrlRequest();

  virtual bool Start();
  virtual void Stop();
  virtual bool Read(int bytes_to_read);

  // Called from NPAPI
  NPError OnStreamCreated(const char* mime_type, NPStream* stream);
  NPError OnStreamDestroyed(NPReason reason);
  int OnWriteReady();
  int OnWrite(void* buffer, int len);

  // Thread unsafe implementation of ref counting, since
  // this will be called on the plugin UI thread only.
  virtual unsigned long API_CALL AddRef();
  virtual unsigned long API_CALL Release();

 private:
  unsigned long ref_count_;
  NPP instance_;
  NPStream* stream_;
  size_t pending_read_size_;
  URLRequestStatus status_;

  PlatformThreadId thread_;
  static int instance_count_;
  DISALLOW_COPY_AND_ASSIGN(NPAPIUrlRequest);
};

int NPAPIUrlRequest::instance_count_ = 0;

NPAPIUrlRequest::NPAPIUrlRequest(NPP instance)
    : ref_count_(0), instance_(instance), stream_(NULL),
      pending_read_size_(0),
      status_(URLRequestStatus::FAILED, net::ERR_FAILED),
      thread_(PlatformThread::CurrentId()) {
  DLOG(INFO) << "Created request. Count: " << ++instance_count_;
}

NPAPIUrlRequest::~NPAPIUrlRequest() {
  DLOG(INFO) << "Deleted request. Count: " << --instance_count_;
}

// NPAPIUrlRequest member defines.
bool NPAPIUrlRequest::Start() {
  NPError result = NPERR_GENERIC_ERROR;
  DLOG(INFO) << "Starting URL request: " << url();
  if (LowerCaseEqualsASCII(method(), "get")) {
    // TODO(joshia): if we have extra headers for HTTP GET, then implement
    // it using XHR
    result = npapi::GetURLNotify(instance_, url().c_str(), NULL, this);
  } else if (LowerCaseEqualsASCII(method(), "post")) {
    uint32 data_len = static_cast<uint32>(post_data_len());

    std::string buffer;
    if (extra_headers().length() > 0) {
      buffer += extra_headers();
      TrimWhitespace(buffer, TRIM_ALL, &buffer);

      // Firefox looks specifically for "Content-length: \d+\r\n\r\n"
      // to detect if extra headers are added to the message buffer.
      buffer += "\r\nContent-length: ";
      buffer += base::IntToString(data_len);
      buffer += "\r\n\r\n";
    }

    std::string data;
    data.resize(data_len);
    uint32 bytes_read;
    upload_data_->Read(&data[0], data_len,
                       reinterpret_cast<ULONG*>(&bytes_read));
    DCHECK_EQ(data_len, bytes_read);
    buffer += data;

    result = npapi::PostURLNotify(instance_, url().c_str(), NULL,
        buffer.length(), buffer.c_str(), false, this);
  } else {
    NOTREACHED() << "PluginUrlRequest only supports 'GET'/'POST'";
  }

  if (NPERR_NO_ERROR != result) {
    int os_error = net::ERR_FAILED;
    switch (result) {
      case NPERR_INVALID_URL:
        os_error = net::ERR_INVALID_URL;
        break;
      default:
        break;
    }

    delegate_->OnResponseEnd(id(),
        URLRequestStatus(URLRequestStatus::FAILED, os_error));
    return false;
  }

  return true;
}

void NPAPIUrlRequest::Stop() {
  DLOG(INFO) << "Finished request: Url - " << url() << " result: "
      << static_cast<int>(status_.status());
  if (stream_) {
    npapi::DestroyStream(instance_, stream_, NPRES_USER_BREAK);
    stream_ = NULL;
  }
}

bool NPAPIUrlRequest::Read(int bytes_to_read) {
  pending_read_size_ = bytes_to_read;
  return true;
}

NPError NPAPIUrlRequest::OnStreamCreated(const char* mime_type,
                                         NPStream* stream) {
  stream_ = stream;
  status_.set_status(URLRequestStatus::IO_PENDING);
  // TODO(iyengar)
  // Add support for passing persistent cookies and information about any URL
  // redirects to Chrome.
  delegate_->OnResponseStarted(id(), mime_type, stream->headers, stream->end,
      base::Time::FromTimeT(stream->lastmodified), std::string(), 0);
  return NPERR_NO_ERROR;
}

NPError NPAPIUrlRequest::OnStreamDestroyed(NPReason reason) {
  URLRequestStatus::Status status = URLRequestStatus::FAILED;
  switch (reason) {
    case NPRES_DONE:
      status_.set_status(URLRequestStatus::SUCCESS);
      status_.set_os_error(0);
      break;
    case NPRES_USER_BREAK:
      status_.set_status(URLRequestStatus::CANCELED);
      status_.set_os_error(net::ERR_ABORTED);
      break;
    case NPRES_NETWORK_ERR:
    default:
      status_.set_status(URLRequestStatus::FAILED);
      status_.set_os_error(net::ERR_CONNECTION_CLOSED);
      break;
  }

  delegate_->OnResponseEnd(id(), status_);
  return NPERR_NO_ERROR;
}

int NPAPIUrlRequest::OnWriteReady() {
  return pending_read_size_;
}

int NPAPIUrlRequest::OnWrite(void* buffer, int len) {
  pending_read_size_ = 0;
  std::string data(reinterpret_cast<char*>(buffer), len);
  delegate_->OnReadComplete(id(), data);
  return len;
}

STDMETHODIMP_(ULONG) NPAPIUrlRequest::AddRef() {
  DCHECK_EQ(PlatformThread::CurrentId(), thread_);
  ++ref_count_;
  return ref_count_;
}

STDMETHODIMP_(ULONG) NPAPIUrlRequest::Release() {
  DCHECK_EQ(PlatformThread::CurrentId(), thread_);
  unsigned long ret = --ref_count_;
  if (!ret)
    delete this;

  return ret;
}

NPAPIUrlRequestManager::NPAPIUrlRequestManager() : instance_(NULL) {
}

NPAPIUrlRequestManager::~NPAPIUrlRequestManager() {
  StopAll();
}

// PluginUrlRequestManager implementation
PluginUrlRequestManager::ThreadSafeFlags
    NPAPIUrlRequestManager::GetThreadSafeFlags() {
  return PluginUrlRequestManager::NOT_THREADSAFE;
}

void NPAPIUrlRequestManager::StartRequest(int request_id,
    const IPC::AutomationURLRequest& request_info) {
  scoped_refptr<NPAPIUrlRequest> new_request(new NPAPIUrlRequest(instance_));
  DCHECK(new_request);
  if (new_request->Initialize(this, request_id, request_info.url,
        request_info.method, request_info.referrer,
        request_info.extra_request_headers,
        request_info.upload_data,
        static_cast<ResourceType::Type>(request_info.resource_type),
        enable_frame_busting_)) {
    // Add to map.
    DCHECK(request_map_.find(request_id) == request_map_.end());
    request_map_[request_id] = new_request;
    if (new_request->Start()) {
      // Keep additional reference on request for NPSTREAM
      // This will be released in NPP_UrlNotify
      new_request->AddRef();
    }
  }
}

void NPAPIUrlRequestManager::ReadRequest(int request_id, int bytes_to_read) {
  scoped_refptr<NPAPIUrlRequest> request = LookupRequest(request_id);
  if (request)
    request->Read(bytes_to_read);
}

void NPAPIUrlRequestManager::EndRequest(int request_id) {
  scoped_refptr<NPAPIUrlRequest> request = LookupRequest(request_id);
  if (request)
    request->Stop();
}

void NPAPIUrlRequestManager::StopAll() {
  std::vector<scoped_refptr<NPAPIUrlRequest> > request_list;
  // We copy the pending requests into a temporary vector as the Stop
  // function in the request could also try to delete the request from
  // the request map and the iterator could end up being invalid.
  for (RequestMap::iterator it = request_map_.begin();
       it != request_map_.end(); ++it) {
    DCHECK(it->second != NULL);
    request_list.push_back(it->second);
  }

  for (std::vector<scoped_refptr<NPAPIUrlRequest> >::size_type index = 0;
       index < request_list.size(); ++index) {
    request_list[index]->Stop();
  }
}

void NPAPIUrlRequestManager::SetCookiesForUrl(const GURL& url,
                                              const std::string& cookie) {
  // Use the newer NPAPI way if available
  if (npapi::VersionMinor() >= NPVERS_HAS_URL_AND_AUTH_INFO) {
    npapi::SetValueForURL(instance_, NPNURLVCookie, url.spec().c_str(),
                          cookie.c_str(), cookie.length());
  } else {
    DLOG(INFO) << "Host does not support NPVERS_HAS_URL_AND_AUTH_INFO.";
    DLOG(INFO) << "Attempting to set cookie using XPCOM cookie service";
    if (np_utils::SetCookiesUsingXPCOMCookieService(instance_, url.spec(),
                                                    cookie)) {
      DLOG(INFO) << "Successfully set cookies using XPCOM cookie service";
      DLOG(INFO) << cookie.c_str();
    } else {
      NOTREACHED() << "Failed to set cookies for host";
    }
  }
}

void NPAPIUrlRequestManager::GetCookiesForUrl(const GURL& url, int cookie_id) {
  std::string cookie_string;
  bool success = true;

  if (npapi::VersionMinor() >= NPVERS_HAS_URL_AND_AUTH_INFO) {
    char* cookies = NULL;
    unsigned int cookie_length = 0;
    NPError ret = npapi::GetValueForURL(instance_, NPNURLVCookie,
                                        url.spec().c_str(), &cookies,
                                        &cookie_length);
    if (ret == NPERR_NO_ERROR) {
      DLOG(INFO) << "Obtained cookies:" << cookies << " from host";
      cookie_string.append(cookies, cookie_length);
      npapi::MemFree(cookies);
    } else {
      success = false;
    }
  } else {
    DLOG(INFO) << "Host does not support NPVERS_HAS_URL_AND_AUTH_INFO.";
    DLOG(INFO) << "Attempting to read cookie using XPCOM cookie service";
    if (np_utils::GetCookiesUsingXPCOMCookieService(instance_, url.spec(),
                                                    &cookie_string)) {
      DLOG(INFO) << "Successfully read cookies using XPCOM cookie service";
      DLOG(INFO) << cookie_string.c_str();
    } else {
      success = false;
    }
  }

  if (!success)
    DLOG(INFO) << "Failed to return cookies for url:" << url.spec().c_str();

  OnCookiesRetrieved(success, url, cookie_string, cookie_id);
}

// PluginRequestDelegate implementation.
// Callbacks from NPAPIUrlRequest. Simply forward to the delegate.
void NPAPIUrlRequestManager::OnResponseStarted(int request_id,
    const char* mime_type, const char* headers, int size,
    base::Time last_modified, const std::string& redirect_url,
    int redirect_status) {
  delegate_->OnResponseStarted(request_id, mime_type, headers, size,
      last_modified, redirect_url, redirect_status);
}

void NPAPIUrlRequestManager::OnReadComplete(int request_id,
                                            const std::string& data) {
  delegate_->OnReadComplete(request_id, data);
}

void NPAPIUrlRequestManager::OnResponseEnd(int request_id,
                                           const URLRequestStatus& status) {
  // Delete from map.
  RequestMap::iterator it = request_map_.find(request_id);
  DCHECK(request_map_.end() != it);
  scoped_refptr<NPAPIUrlRequest> request = (*it).second;
  request_map_.erase(it);

  // Inform delegate unless canceled.
  if (status.status() != URLRequestStatus::CANCELED)
    delegate_->OnResponseEnd(request_id, status);
}

void NPAPIUrlRequestManager::OnCookiesRetrieved(bool success, const GURL& url,
    const std::string& cookie_string, int cookie_id) {
  delegate_->OnCookiesRetrieved(success, url, cookie_string, cookie_id);
}

// Notifications from browser. Find the NPAPIUrlRequest and forward to it.
NPError NPAPIUrlRequestManager::NewStream(NPMIMEType type,
                                          NPStream* stream,
                                          NPBool seekable,
                                          uint16* stream_type) {
  NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData);
  if (!request)
    return NPERR_NO_ERROR;

  DCHECK(request_map_.find(request->id()) != request_map_.end());
  // We need to return the requested stream mode if we are returning a success
  // code. If we don't do this it causes Opera to blow up.
  *stream_type = NP_NORMAL;
  return request->OnStreamCreated(type, stream);
}

int32 NPAPIUrlRequestManager::WriteReady(NPStream* stream) {
  NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData);
  if (!request)
    return 0x7FFFFFFF;
  DCHECK(request_map_.find(request->id()) != request_map_.end());
  return request->OnWriteReady();
}

int32 NPAPIUrlRequestManager::Write(NPStream* stream, int32 offset,
                                    int32 len, void* buffer) {
  NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData);
  if (!request)
    return len;
  DCHECK(request_map_.find(request->id()) != request_map_.end());
  return request->OnWrite(buffer, len);
}

NPError NPAPIUrlRequestManager::DestroyStream(NPStream* stream,
                                              NPReason reason) {
  NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData);
  if (!request)
    return NPERR_NO_ERROR;
  DCHECK(request_map_.find(request->id()) != request_map_.end());
  return request->OnStreamDestroyed(reason);
}

void NPAPIUrlRequestManager::UrlNotify(const char* url, NPReason reason,
                                       void* notify_data) {
  NPAPIUrlRequest* request = RequestFromNotifyData(notify_data);
  DCHECK(request != NULL);
  if (request) {
    request->Stop();
    request->Release();
  }
}

scoped_refptr<NPAPIUrlRequest> NPAPIUrlRequestManager::LookupRequest(
    int request_id) {
  RequestMap::iterator index = request_map_.find(request_id);
  if (index != request_map_.end())
    return index->second;
  return NULL;
}
<commit_msg>Simple fix correcting the lifetime scope of automated url request jobs during chrome-initiated xmlhttprequest aborts.  Two similar problems are fixed by this CL.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome_frame/npapi_url_request.h"

#include "base/string_number_conversions.h"
#include "chrome_frame/np_browser_functions.h"
#include "chrome_frame/np_utils.h"
#include "net/base/net_errors.h"

class NPAPIUrlRequest : public PluginUrlRequest {
 public:
  explicit NPAPIUrlRequest(NPP instance);
  ~NPAPIUrlRequest();

  virtual bool Start();
  virtual void Stop();
  virtual bool Read(int bytes_to_read);

  // Called from NPAPI
  NPError OnStreamCreated(const char* mime_type, NPStream* stream);
  NPError OnStreamDestroyed(NPReason reason);
  int OnWriteReady();
  int OnWrite(void* buffer, int len);

  // Thread unsafe implementation of ref counting, since
  // this will be called on the plugin UI thread only.
  virtual unsigned long API_CALL AddRef();
  virtual unsigned long API_CALL Release();

  const URLRequestStatus& status() const {
    return status_;
  }

  NPP instance() const {
    return instance_;
  }

 private:
  unsigned long ref_count_;
  NPP instance_;
  NPStream* stream_;
  size_t pending_read_size_;
  URLRequestStatus status_;

  PlatformThreadId thread_;
  static int instance_count_;
  DISALLOW_COPY_AND_ASSIGN(NPAPIUrlRequest);
};

int NPAPIUrlRequest::instance_count_ = 0;

NPAPIUrlRequest::NPAPIUrlRequest(NPP instance)
    : ref_count_(0), instance_(instance), stream_(NULL),
      pending_read_size_(0),
      status_(URLRequestStatus::FAILED, net::ERR_FAILED),
      thread_(PlatformThread::CurrentId()) {
  DLOG(INFO) << "Created request. Count: " << ++instance_count_;
}

NPAPIUrlRequest::~NPAPIUrlRequest() {
  DLOG(INFO) << "Deleted request. Count: " << --instance_count_;
}

// NPAPIUrlRequest member defines.
bool NPAPIUrlRequest::Start() {
  NPError result = NPERR_GENERIC_ERROR;
  DLOG(INFO) << "Starting URL request: " << url();
  if (LowerCaseEqualsASCII(method(), "get")) {
    // TODO(joshia): if we have extra headers for HTTP GET, then implement
    // it using XHR
    result = npapi::GetURLNotify(instance_, url().c_str(), NULL, this);
  } else if (LowerCaseEqualsASCII(method(), "post")) {
    uint32 data_len = static_cast<uint32>(post_data_len());

    std::string buffer;
    if (extra_headers().length() > 0) {
      buffer += extra_headers();
      TrimWhitespace(buffer, TRIM_ALL, &buffer);

      // Firefox looks specifically for "Content-length: \d+\r\n\r\n"
      // to detect if extra headers are added to the message buffer.
      buffer += "\r\nContent-length: ";
      buffer += base::IntToString(data_len);
      buffer += "\r\n\r\n";
    }

    std::string data;
    data.resize(data_len);
    uint32 bytes_read;
    upload_data_->Read(&data[0], data_len,
                       reinterpret_cast<ULONG*>(&bytes_read));
    DCHECK_EQ(data_len, bytes_read);
    buffer += data;

    result = npapi::PostURLNotify(instance_, url().c_str(), NULL,
        buffer.length(), buffer.c_str(), false, this);
  } else {
    NOTREACHED() << "PluginUrlRequest only supports 'GET'/'POST'";
  }

  if (NPERR_NO_ERROR != result) {
    int os_error = net::ERR_FAILED;
    switch (result) {
      case NPERR_INVALID_URL:
        os_error = net::ERR_INVALID_URL;
        break;
      default:
        break;
    }

    delegate_->OnResponseEnd(id(),
        URLRequestStatus(URLRequestStatus::FAILED, os_error));
    return false;
  }

  return true;
}

void NPAPIUrlRequest::Stop() {
  DLOG(INFO) << "Finished request: Url - " << url() << " result: "
      << static_cast<int>(status_.status());

  status_.set_status(URLRequestStatus::CANCELED);
  if (stream_) {
    npapi::DestroyStream(instance_, stream_, NPRES_USER_BREAK);
    stream_ = NULL;
  }
}

bool NPAPIUrlRequest::Read(int bytes_to_read) {
  pending_read_size_ = bytes_to_read;
  return true;
}

NPError NPAPIUrlRequest::OnStreamCreated(const char* mime_type,
                                         NPStream* stream) {
  stream_ = stream;
  status_.set_status(URLRequestStatus::IO_PENDING);
  // TODO(iyengar)
  // Add support for passing persistent cookies and information about any URL
  // redirects to Chrome.
  delegate_->OnResponseStarted(id(), mime_type, stream->headers, stream->end,
      base::Time::FromTimeT(stream->lastmodified), std::string(), 0);
  return NPERR_NO_ERROR;
}

NPError NPAPIUrlRequest::OnStreamDestroyed(NPReason reason) {
  // If the request has been aborted, then ignore the |reason| argument.
  // Normally the execution flow is such than NPRES_USER_BREAK will be passed
  // when the stream is aborted, but sometimes NPRES_NETWORK_ERROR is passed
  // instead.  To prevent Chrome from receiving a notification of a failed
  // network connection, when Chrome actually canceled the request, we ignore
  // the status here.
  if (URLRequestStatus::CANCELED != status_.status()) {
    switch (reason) {
      case NPRES_DONE:
        status_.set_status(URLRequestStatus::SUCCESS);
        status_.set_os_error(0);
        break;
      case NPRES_USER_BREAK:
        status_.set_status(URLRequestStatus::CANCELED);
        status_.set_os_error(net::ERR_ABORTED);
        break;
      case NPRES_NETWORK_ERR:
      default:
        status_.set_status(URLRequestStatus::FAILED);
        status_.set_os_error(net::ERR_CONNECTION_CLOSED);
        break;
    }
  }

  delegate_->OnResponseEnd(id(), status_);
  return NPERR_NO_ERROR;
}

int NPAPIUrlRequest::OnWriteReady() {
  return pending_read_size_;
}

int NPAPIUrlRequest::OnWrite(void* buffer, int len) {
  pending_read_size_ = 0;
  std::string data(reinterpret_cast<char*>(buffer), len);
  delegate_->OnReadComplete(id(), data);
  return len;
}

STDMETHODIMP_(ULONG) NPAPIUrlRequest::AddRef() {
  DCHECK_EQ(PlatformThread::CurrentId(), thread_);
  ++ref_count_;
  return ref_count_;
}

STDMETHODIMP_(ULONG) NPAPIUrlRequest::Release() {
  DCHECK_EQ(PlatformThread::CurrentId(), thread_);
  unsigned long ret = --ref_count_;
  if (!ret)
    delete this;

  return ret;
}

NPAPIUrlRequestManager::NPAPIUrlRequestManager() : instance_(NULL) {
}

NPAPIUrlRequestManager::~NPAPIUrlRequestManager() {
  StopAll();
}

// PluginUrlRequestManager implementation
PluginUrlRequestManager::ThreadSafeFlags
    NPAPIUrlRequestManager::GetThreadSafeFlags() {
  return PluginUrlRequestManager::NOT_THREADSAFE;
}

void NPAPIUrlRequestManager::StartRequest(int request_id,
    const IPC::AutomationURLRequest& request_info) {
  scoped_refptr<NPAPIUrlRequest> new_request(new NPAPIUrlRequest(instance_));
  DCHECK(new_request);
  if (new_request->Initialize(this, request_id, request_info.url,
        request_info.method, request_info.referrer,
        request_info.extra_request_headers,
        request_info.upload_data,
        static_cast<ResourceType::Type>(request_info.resource_type),
        enable_frame_busting_)) {
    DCHECK(request_map_.find(request_id) == request_map_.end());
    if (new_request->Start()) {
      request_map_[request_id] = new_request;
      // Keep additional reference on request for NPSTREAM
      // This will be released in NPP_UrlNotify
      new_request->AddRef();
    }
  }
}

void NPAPIUrlRequestManager::ReadRequest(int request_id, int bytes_to_read) {
  scoped_refptr<NPAPIUrlRequest> request = LookupRequest(request_id);
  if (request)
    request->Read(bytes_to_read);
}

void NPAPIUrlRequestManager::EndRequest(int request_id) {
  scoped_refptr<NPAPIUrlRequest> request = LookupRequest(request_id);
  if (request)
    request->Stop();
}

void NPAPIUrlRequestManager::StopAll() {
  std::vector<scoped_refptr<NPAPIUrlRequest> > request_list;
  // We copy the pending requests into a temporary vector as the Stop
  // function in the request could also try to delete the request from
  // the request map and the iterator could end up being invalid.
  for (RequestMap::iterator it = request_map_.begin();
       it != request_map_.end(); ++it) {
    DCHECK(it->second != NULL);
    request_list.push_back(it->second);
  }

  for (std::vector<scoped_refptr<NPAPIUrlRequest> >::size_type index = 0;
       index < request_list.size(); ++index) {
    request_list[index]->Stop();
  }
}

void NPAPIUrlRequestManager::SetCookiesForUrl(const GURL& url,
                                              const std::string& cookie) {
  // Use the newer NPAPI way if available
  if (npapi::VersionMinor() >= NPVERS_HAS_URL_AND_AUTH_INFO) {
    npapi::SetValueForURL(instance_, NPNURLVCookie, url.spec().c_str(),
                          cookie.c_str(), cookie.length());
  } else {
    DLOG(INFO) << "Host does not support NPVERS_HAS_URL_AND_AUTH_INFO.";
    DLOG(INFO) << "Attempting to set cookie using XPCOM cookie service";
    if (np_utils::SetCookiesUsingXPCOMCookieService(instance_, url.spec(),
                                                    cookie)) {
      DLOG(INFO) << "Successfully set cookies using XPCOM cookie service";
      DLOG(INFO) << cookie.c_str();
    } else {
      NOTREACHED() << "Failed to set cookies for host";
    }
  }
}

void NPAPIUrlRequestManager::GetCookiesForUrl(const GURL& url, int cookie_id) {
  std::string cookie_string;
  bool success = true;

  if (npapi::VersionMinor() >= NPVERS_HAS_URL_AND_AUTH_INFO) {
    char* cookies = NULL;
    unsigned int cookie_length = 0;
    NPError ret = npapi::GetValueForURL(instance_, NPNURLVCookie,
                                        url.spec().c_str(), &cookies,
                                        &cookie_length);
    if (ret == NPERR_NO_ERROR) {
      DLOG(INFO) << "Obtained cookies:" << cookies << " from host";
      cookie_string.append(cookies, cookie_length);
      npapi::MemFree(cookies);
    } else {
      success = false;
    }
  } else {
    DLOG(INFO) << "Host does not support NPVERS_HAS_URL_AND_AUTH_INFO.";
    DLOG(INFO) << "Attempting to read cookie using XPCOM cookie service";
    if (np_utils::GetCookiesUsingXPCOMCookieService(instance_, url.spec(),
                                                    &cookie_string)) {
      DLOG(INFO) << "Successfully read cookies using XPCOM cookie service";
      DLOG(INFO) << cookie_string.c_str();
    } else {
      success = false;
    }
  }

  if (!success)
    DLOG(INFO) << "Failed to return cookies for url:" << url.spec().c_str();

  OnCookiesRetrieved(success, url, cookie_string, cookie_id);
}

// PluginRequestDelegate implementation.
// Callbacks from NPAPIUrlRequest. Simply forward to the delegate.
void NPAPIUrlRequestManager::OnResponseStarted(int request_id,
    const char* mime_type, const char* headers, int size,
    base::Time last_modified, const std::string& redirect_url,
    int redirect_status) {
  delegate_->OnResponseStarted(request_id, mime_type, headers, size,
      last_modified, redirect_url, redirect_status);
}

void NPAPIUrlRequestManager::OnReadComplete(int request_id,
                                            const std::string& data) {
  delegate_->OnReadComplete(request_id, data);
}

void NPAPIUrlRequestManager::OnResponseEnd(int request_id,
                                           const URLRequestStatus& status) {
  // Delete from map.
  RequestMap::iterator it = request_map_.find(request_id);
  DCHECK(request_map_.end() != it);
  scoped_refptr<NPAPIUrlRequest> request = (*it).second;
  request_map_.erase(it);

  // Inform delegate unless canceled.
  if (status.status() != URLRequestStatus::CANCELED)
    delegate_->OnResponseEnd(request_id, status);
}

void NPAPIUrlRequestManager::OnCookiesRetrieved(bool success, const GURL& url,
    const std::string& cookie_string, int cookie_id) {
  delegate_->OnCookiesRetrieved(success, url, cookie_string, cookie_id);
}

// Notifications from browser. Find the NPAPIUrlRequest and forward to it.
NPError NPAPIUrlRequestManager::NewStream(NPMIMEType type,
                                          NPStream* stream,
                                          NPBool seekable,
                                          uint16* stream_type) {
  NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData);
  if (!request)
    return NPERR_NO_ERROR;

  // This stream is being constructed for a request that has already been
  // canceled.  Signal its immediate termination.
  if (URLRequestStatus::CANCELED == request->status().status()) {
    return npapi::DestroyStream(request->instance(),
                                stream, NPRES_USER_BREAK);
  }

  DCHECK(request_map_.find(request->id()) != request_map_.end());
  // We need to return the requested stream mode if we are returning a success
  // code. If we don't do this it causes Opera to blow up.
  *stream_type = NP_NORMAL;
  return request->OnStreamCreated(type, stream);
}

int32 NPAPIUrlRequestManager::WriteReady(NPStream* stream) {
  NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData);
  if (!request)
    return 0x7FFFFFFF;
  DCHECK(request_map_.find(request->id()) != request_map_.end());
  return request->OnWriteReady();
}

int32 NPAPIUrlRequestManager::Write(NPStream* stream, int32 offset,
                                    int32 len, void* buffer) {
  NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData);
  if (!request)
    return len;
  DCHECK(request_map_.find(request->id()) != request_map_.end());
  return request->OnWrite(buffer, len);
}

NPError NPAPIUrlRequestManager::DestroyStream(NPStream* stream,
                                              NPReason reason) {
  NPAPIUrlRequest* request = RequestFromNotifyData(stream->notifyData);
  if (!request)
    return NPERR_NO_ERROR;

  // It is possible to receive notification of a destroyed stream for a
  // unregistered request:  EndRequest will unregister a request in response
  // to an AutomationMsg_RequestEnd message.  EndRequest will also invoke
  // npapi::DestroyStream, which will call back to this function.
  if (request_map_.find(request->id()) != request_map_.end())
    return request->OnStreamDestroyed(reason);

  return NPERR_NO_ERROR;
}

void NPAPIUrlRequestManager::UrlNotify(const char* url, NPReason reason,
                                       void* notify_data) {
  NPAPIUrlRequest* request = RequestFromNotifyData(notify_data);
  DCHECK(request != NULL);
  if (request) {
    request->Stop();
    request->Release();
  }
}

scoped_refptr<NPAPIUrlRequest> NPAPIUrlRequestManager::LookupRequest(
    int request_id) {
  RequestMap::iterator index = request_map_.find(request_id);
  if (index != request_map_.end())
    return index->second;
  return NULL;
}
<|endoftext|>


<commit_before>#include "ovpCAlgorithmSphericalSplineInterpolation.h"

//INSERM lib
#include "spline_sph.h"

#include <float.h> //DBL_MAX
#include <math.h>

using namespace OpenViBE;
using namespace OpenViBE::Kernel;
using namespace OpenViBE::Plugins;

using namespace OpenViBEPlugins;
using namespace OpenViBEPlugins::Test;

boolean CAlgorithmSphericalSplineInterpolation::initialize(void)
{
	m_bFirstProcess = true;
	m_pDoubleCoords = NULL;
	m_pInsermCoords = NULL;
	m_pSplineCoefs = NULL;
	m_pLaplacianSplineCoefs = NULL;

	ip_i64SplineOrder.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_SplineOrder));
	ip_i64ControlPointsCount.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_ControlPointsCount));
	ip_pControlPointsCoords.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_ControlPointsCoordinates));
	ip_pControlPointsValues.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_ControlPointsValues));
	ip_pSamplePointsCoords.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_SamplePointsCoordinates));

	op_pSamplePointsValues.initialize(getOutputParameter(OVP_Algorithm_SphericalSplineInterpolation_OutputParameterId_SamplePointsValues));
	op_pSamplePointsValues->setDimensionCount(1);
	op_f64MinSamplePointValue.initialize(getOutputParameter(OVP_Algorithm_SphericalSplineInterpolation_OutputParameterId_MinSamplePointValue));
	op_f64MaxSamplePointValue.initialize(getOutputParameter(OVP_Algorithm_SphericalSplineInterpolation_OutputParameterId_MaxSamplePointValue));

	return true;
}

boolean CAlgorithmSphericalSplineInterpolation::uninitialize(void)
{
	ip_i64SplineOrder.uninitialize();
	ip_i64ControlPointsCount.uninitialize();
	ip_pControlPointsCoords.uninitialize();
	ip_pControlPointsValues.uninitialize();
	ip_pSamplePointsCoords.uninitialize();

	op_pSamplePointsValues.uninitialize();
	op_f64MinSamplePointValue.uninitialize();
	op_f64MaxSamplePointValue.uninitialize();

	if(m_pDoubleCoords != NULL)
	{
		delete[] m_pDoubleCoords;
	}

	if(m_pInsermCoords != NULL)
	{
		delete[] m_pInsermCoords;
	}

	if(m_pSplineCoefs != NULL)
	{
		delete[] m_pSplineCoefs;
	}

	if(m_pLaplacianSplineCoefs != NULL)
	{
		delete[] m_pLaplacianSplineCoefs;
	}

	return true;
}

boolean CAlgorithmSphericalSplineInterpolation::process(void)
{
	if(m_bFirstProcess == true)
	{
		//store coords as doubles
		m_pDoubleCoords = new double[3*ip_i64ControlPointsCount];
		//set up matrix of pointers to double coords matrix
		m_pInsermCoords = new double* [ip_i64ControlPointsCount];
		//fill both matrices
		for(int i=0; i<ip_i64ControlPointsCount; i++)
		{
			m_pDoubleCoords[i*3] = (double)(*ip_pControlPointsCoords)[i*3];
			m_pDoubleCoords[i*3+1] = (double)(*ip_pControlPointsCoords)[i*3+1];
			m_pDoubleCoords[i*3+2] = (double)(*ip_pControlPointsCoords)[i*3+2];
			m_pInsermCoords[i] = m_pDoubleCoords + 3*i;
		}
		m_bFirstProcess == false;
	}

	//do we want to precompute tables?
	if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_PrecomputeTables))
	{
		//compute cos/sin values used in spline polynomias
		spline_tables((int)ip_i64SplineOrder, m_PotTable, m_ScdTable);
	}

	if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_ComputeSplineCoefs))
	{
		if(m_pSplineCoefs == NULL && (int)ip_i64ControlPointsCount != 0)
		{
			m_pSplineCoefs = new double[(int)ip_i64ControlPointsCount+1];
		}

		//compute spline ponderation coefficients using spline values
		//FIXME : have a working copy of control points values stored as doubles?
		spline_coef((int)ip_i64ControlPointsCount, m_pInsermCoords, (double*)ip_pControlPointsValues->getBuffer(), m_PotTable, m_pSplineCoefs);
	}

	if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_ComputeLaplacianCoefs))
	{
		if(m_pLaplacianSplineCoefs == NULL && (int)ip_i64ControlPointsCount != 0)
		{
			m_pLaplacianSplineCoefs = new double[(int)ip_i64ControlPointsCount+1];
		}

		//compute spline ponderation coefficients using spline values
		//FIXME : have a working copy of control points values stored as doubles?
		spline_coef((int)ip_i64ControlPointsCount, m_pInsermCoords, (double*)ip_pControlPointsValues->getBuffer(), m_PotTable, m_pLaplacianSplineCoefs);
		m_pLaplacianSplineCoefs[(int)ip_i64ControlPointsCount] = 0;
	}

	if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_InterpolateSpline))
	{
		//ensure we got enough storage space for interpolated values
		if(op_pSamplePointsValues->getDimensionSize(0) != ip_pSamplePointsCoords->getDimensionSize(0))
		{
			op_pSamplePointsValues->setDimensionSize(0, ip_pSamplePointsCoords->getDimensionSize(0));
		}

		//compute interpolated values using spline
		double* l_pSampleValue = (double*)op_pSamplePointsValues->getBuffer();

		op_f64MinSamplePointValue = +DBL_MAX;
		op_f64MaxSamplePointValue = -DBL_MAX;

		for(uint32 i=0; i<ip_pSamplePointsCoords->getDimensionSize(0); i++, l_pSampleValue++)
		{
#if defined OVP_OS_Windows
#ifndef NDEBUG
			if(_finite(*(ip_pSamplePointsCoords->getBuffer()+3*i)) == 0 ||
				_finite(*(ip_pSamplePointsCoords->getBuffer()+3*i+1)) == 0 ||
				_finite(*(ip_pSamplePointsCoords->getBuffer()+3*i+2)) == 0) //tests whether a double is infinite or a NaN
			{
				getLogManager() << LogLevel_ImportantWarning << "Bad interpolation point coordinates !\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i) << "\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i+1) << "\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i+2) << "\n";
			}
#endif
#endif

			*l_pSampleValue = spline_interp(
				(int)ip_i64ControlPointsCount, //number of fixed values
				m_pInsermCoords, //coordinates of fixed values
				m_PotTable, //sin/cos table for spline
				m_pSplineCoefs, //spline coefficients
				*(ip_pSamplePointsCoords->getBuffer()+3*i),
				*(ip_pSamplePointsCoords->getBuffer()+3*i+1),
				*(ip_pSamplePointsCoords->getBuffer()+3*i+2) //coordinate where to interpolate
				);

#if defined OVP_OS_Windows
#ifndef NDEBUG
			if(_finite(*l_pSampleValue) == 0) //tests whether a double is infinite or a NaN
			{
				getLogManager() << LogLevel_ImportantWarning << "Interpolation fails !\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i) << "\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i+1) << "\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i+2) << "\n";
			}
#endif
#endif

			if(*l_pSampleValue < op_f64MinSamplePointValue)
			{
				op_f64MinSamplePointValue = *l_pSampleValue;
			}
			if(*l_pSampleValue > op_f64MaxSamplePointValue)
			{
				op_f64MaxSamplePointValue = *l_pSampleValue;
			}
		}
	}
	else if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_InterpolateLaplacian))
	{
		//ensure we got enough storage space for interpolated values
		if(op_pSamplePointsValues->getDimensionSize(0) != ip_pSamplePointsCoords->getDimensionSize(0))
		{
			op_pSamplePointsValues->setDimensionSize(0, ip_pSamplePointsCoords->getDimensionSize(0));
		}

		//compute interpolated values using spline
		double* l_pSampleValue = (double*)op_pSamplePointsValues->getBuffer();

		op_f64MinSamplePointValue = +DBL_MAX;
		op_f64MaxSamplePointValue = -DBL_MAX;

		for(uint32 i=0; i<ip_pSamplePointsCoords->getDimensionSize(0); i++, l_pSampleValue++)
		{
			*l_pSampleValue = spline_interp(
				(int)ip_i64ControlPointsCount, //number of fixed values
				m_pInsermCoords, //coordinates of fixed values
				m_ScdTable, //sin/cos table for laplacian
				m_pLaplacianSplineCoefs, //laplacian coefficients
				*(ip_pSamplePointsCoords->getBuffer()+3*i),
				*(ip_pSamplePointsCoords->getBuffer()+3*i+1),
				*(ip_pSamplePointsCoords->getBuffer()+3*i+2) //coordinate where to interpolate
				);

			/***************************************************************************/
			/*** Units : potential values being very often expressed as micro-Volts  ***/
			/***         SCD values should be multiplied by a scaling factor         ***/
			/***         to get nano-Amperes/m3                                      ***/
			/***         Since the output of spline_interp corresponds to the        ***/
			/***         Laplacian operator only, SCD are obtained with a scaling    ***/
			/***         factor equal to 10-3 * sigma / (R*R)                        ***/
			/***         with sigma = conductivity of the scalp    = 0.45 Siemens/m  ***/
			/***         and  R     = radius of the spherical head = 0.09 m          ***/
			/***************************************************************************/
			*l_pSampleValue = *l_pSampleValue * (0.001 * 0.45 / 0.09 / 0.09);

			if(*l_pSampleValue < op_f64MinSamplePointValue)
			{
				op_f64MinSamplePointValue = *l_pSampleValue;
			}
			if(*l_pSampleValue > op_f64MaxSamplePointValue)
			{
				op_f64MaxSamplePointValue = *l_pSampleValue;
			}
		}
	}

	return true;
}
<commit_msg>openvibe-plugins-simple-visualisation :  * corrected bug on operator with no effect<commit_after>#include "ovpCAlgorithmSphericalSplineInterpolation.h"

//INSERM lib
#include "spline_sph.h"

#include <float.h> //DBL_MAX
#include <math.h>

using namespace OpenViBE;
using namespace OpenViBE::Kernel;
using namespace OpenViBE::Plugins;

using namespace OpenViBEPlugins;
using namespace OpenViBEPlugins::Test;

boolean CAlgorithmSphericalSplineInterpolation::initialize(void)
{
	m_bFirstProcess = true;
	m_pDoubleCoords = NULL;
	m_pInsermCoords = NULL;
	m_pSplineCoefs = NULL;
	m_pLaplacianSplineCoefs = NULL;

	ip_i64SplineOrder.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_SplineOrder));
	ip_i64ControlPointsCount.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_ControlPointsCount));
	ip_pControlPointsCoords.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_ControlPointsCoordinates));
	ip_pControlPointsValues.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_ControlPointsValues));
	ip_pSamplePointsCoords.initialize(getInputParameter(OVP_Algorithm_SphericalSplineInterpolation_InputParameterId_SamplePointsCoordinates));

	op_pSamplePointsValues.initialize(getOutputParameter(OVP_Algorithm_SphericalSplineInterpolation_OutputParameterId_SamplePointsValues));
	op_pSamplePointsValues->setDimensionCount(1);
	op_f64MinSamplePointValue.initialize(getOutputParameter(OVP_Algorithm_SphericalSplineInterpolation_OutputParameterId_MinSamplePointValue));
	op_f64MaxSamplePointValue.initialize(getOutputParameter(OVP_Algorithm_SphericalSplineInterpolation_OutputParameterId_MaxSamplePointValue));

	return true;
}

boolean CAlgorithmSphericalSplineInterpolation::uninitialize(void)
{
	ip_i64SplineOrder.uninitialize();
	ip_i64ControlPointsCount.uninitialize();
	ip_pControlPointsCoords.uninitialize();
	ip_pControlPointsValues.uninitialize();
	ip_pSamplePointsCoords.uninitialize();

	op_pSamplePointsValues.uninitialize();
	op_f64MinSamplePointValue.uninitialize();
	op_f64MaxSamplePointValue.uninitialize();

	if(m_pDoubleCoords != NULL)
	{
		delete[] m_pDoubleCoords;
	}

	if(m_pInsermCoords != NULL)
	{
		delete[] m_pInsermCoords;
	}

	if(m_pSplineCoefs != NULL)
	{
		delete[] m_pSplineCoefs;
	}

	if(m_pLaplacianSplineCoefs != NULL)
	{
		delete[] m_pLaplacianSplineCoefs;
	}

	return true;
}

boolean CAlgorithmSphericalSplineInterpolation::process(void)
{
	if(m_bFirstProcess == true)
	{
		//store coords as doubles
		m_pDoubleCoords = new double[3*ip_i64ControlPointsCount];
		//set up matrix of pointers to double coords matrix
		m_pInsermCoords = new double* [ip_i64ControlPointsCount];
		//fill both matrices
		for(int i=0; i<ip_i64ControlPointsCount; i++)
		{
			m_pDoubleCoords[i*3] = (double)(*ip_pControlPointsCoords)[i*3];
			m_pDoubleCoords[i*3+1] = (double)(*ip_pControlPointsCoords)[i*3+1];
			m_pDoubleCoords[i*3+2] = (double)(*ip_pControlPointsCoords)[i*3+2];
			m_pInsermCoords[i] = m_pDoubleCoords + 3*i;
		}
		m_bFirstProcess = false;
	}

	//do we want to precompute tables?
	if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_PrecomputeTables))
	{
		//compute cos/sin values used in spline polynomias
		spline_tables((int)ip_i64SplineOrder, m_PotTable, m_ScdTable);
	}

	if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_ComputeSplineCoefs))
	{
		if(m_pSplineCoefs == NULL && (int)ip_i64ControlPointsCount != 0)
		{
			m_pSplineCoefs = new double[(int)ip_i64ControlPointsCount+1];
		}

		//compute spline ponderation coefficients using spline values
		//FIXME : have a working copy of control points values stored as doubles?
		spline_coef((int)ip_i64ControlPointsCount, m_pInsermCoords, (double*)ip_pControlPointsValues->getBuffer(), m_PotTable, m_pSplineCoefs);
	}

	if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_ComputeLaplacianCoefs))
	{
		if(m_pLaplacianSplineCoefs == NULL && (int)ip_i64ControlPointsCount != 0)
		{
			m_pLaplacianSplineCoefs = new double[(int)ip_i64ControlPointsCount+1];
		}

		//compute spline ponderation coefficients using spline values
		//FIXME : have a working copy of control points values stored as doubles?
		spline_coef((int)ip_i64ControlPointsCount, m_pInsermCoords, (double*)ip_pControlPointsValues->getBuffer(), m_PotTable, m_pLaplacianSplineCoefs);
		m_pLaplacianSplineCoefs[(int)ip_i64ControlPointsCount] = 0;
	}

	if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_InterpolateSpline))
	{
		//ensure we got enough storage space for interpolated values
		if(op_pSamplePointsValues->getDimensionSize(0) != ip_pSamplePointsCoords->getDimensionSize(0))
		{
			op_pSamplePointsValues->setDimensionSize(0, ip_pSamplePointsCoords->getDimensionSize(0));
		}

		//compute interpolated values using spline
		double* l_pSampleValue = (double*)op_pSamplePointsValues->getBuffer();

		op_f64MinSamplePointValue = +DBL_MAX;
		op_f64MaxSamplePointValue = -DBL_MAX;

		for(uint32 i=0; i<ip_pSamplePointsCoords->getDimensionSize(0); i++, l_pSampleValue++)
		{
#if defined OVP_OS_Windows
#ifndef NDEBUG
			if(_finite(*(ip_pSamplePointsCoords->getBuffer()+3*i)) == 0 ||
				_finite(*(ip_pSamplePointsCoords->getBuffer()+3*i+1)) == 0 ||
				_finite(*(ip_pSamplePointsCoords->getBuffer()+3*i+2)) == 0) //tests whether a double is infinite or a NaN
			{
				getLogManager() << LogLevel_ImportantWarning << "Bad interpolation point coordinates !\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i) << "\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i+1) << "\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i+2) << "\n";
			}
#endif
#endif

			*l_pSampleValue = spline_interp(
				(int)ip_i64ControlPointsCount, //number of fixed values
				m_pInsermCoords, //coordinates of fixed values
				m_PotTable, //sin/cos table for spline
				m_pSplineCoefs, //spline coefficients
				*(ip_pSamplePointsCoords->getBuffer()+3*i),
				*(ip_pSamplePointsCoords->getBuffer()+3*i+1),
				*(ip_pSamplePointsCoords->getBuffer()+3*i+2) //coordinate where to interpolate
				);

#if defined OVP_OS_Windows
#ifndef NDEBUG
			if(_finite(*l_pSampleValue) == 0) //tests whether a double is infinite or a NaN
			{
				getLogManager() << LogLevel_ImportantWarning << "Interpolation fails !\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i) << "\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i+1) << "\n";
				getLogManager() << LogLevel_ImportantWarning << *(ip_pSamplePointsCoords->getBuffer()+3*i+2) << "\n";
			}
#endif
#endif

			if(*l_pSampleValue < op_f64MinSamplePointValue)
			{
				op_f64MinSamplePointValue = *l_pSampleValue;
			}
			if(*l_pSampleValue > op_f64MaxSamplePointValue)
			{
				op_f64MaxSamplePointValue = *l_pSampleValue;
			}
		}
	}
	else if(isInputTriggerActive(OVP_Algorithm_SphericalSplineInterpolation_InputTriggerId_InterpolateLaplacian))
	{
		//ensure we got enough storage space for interpolated values
		if(op_pSamplePointsValues->getDimensionSize(0) != ip_pSamplePointsCoords->getDimensionSize(0))
		{
			op_pSamplePointsValues->setDimensionSize(0, ip_pSamplePointsCoords->getDimensionSize(0));
		}

		//compute interpolated values using spline
		double* l_pSampleValue = (double*)op_pSamplePointsValues->getBuffer();

		op_f64MinSamplePointValue = +DBL_MAX;
		op_f64MaxSamplePointValue = -DBL_MAX;

		for(uint32 i=0; i<ip_pSamplePointsCoords->getDimensionSize(0); i++, l_pSampleValue++)
		{
			*l_pSampleValue = spline_interp(
				(int)ip_i64ControlPointsCount, //number of fixed values
				m_pInsermCoords, //coordinates of fixed values
				m_ScdTable, //sin/cos table for laplacian
				m_pLaplacianSplineCoefs, //laplacian coefficients
				*(ip_pSamplePointsCoords->getBuffer()+3*i),
				*(ip_pSamplePointsCoords->getBuffer()+3*i+1),
				*(ip_pSamplePointsCoords->getBuffer()+3*i+2) //coordinate where to interpolate
				);

			/***************************************************************************/
			/*** Units : potential values being very often expressed as micro-Volts  ***/
			/***         SCD values should be multiplied by a scaling factor         ***/
			/***         to get nano-Amperes/m3                                      ***/
			/***         Since the output of spline_interp corresponds to the        ***/
			/***         Laplacian operator only, SCD are obtained with a scaling    ***/
			/***         factor equal to 10-3 * sigma / (R*R)                        ***/
			/***         with sigma = conductivity of the scalp    = 0.45 Siemens/m  ***/
			/***         and  R     = radius of the spherical head = 0.09 m          ***/
			/***************************************************************************/
			*l_pSampleValue = *l_pSampleValue * (0.001 * 0.45 / 0.09 / 0.09);

			if(*l_pSampleValue < op_f64MinSamplePointValue)
			{
				op_f64MinSamplePointValue = *l_pSampleValue;
			}
			if(*l_pSampleValue > op_f64MaxSamplePointValue)
			{
				op_f64MaxSamplePointValue = *l_pSampleValue;
			}
		}
	}

	return true;
}
<|endoftext|>


<commit_before><commit_msg>Modified the destructor in LnLSTM<commit_after><|endoftext|>