<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <sfx2/sidebar/ResourceDefinitions.hrc>
#include <sfx2/sidebar/Theme.hxx>
#include <sfx2/sidebar/ControlFactory.hxx>
#include "ChartElementsPanel.hxx"
#include "ChartController.hxx"
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/imagemgr.hxx>
#include <vcl/fixed.hxx>
#include <vcl/lstbox.hxx>
#include <vcl/field.hxx>
#include <vcl/toolbox.hxx>
#include <svl/intitem.hxx>
#include <svl/stritem.hxx>
#include <comphelper/processfactory.hxx>

#include "LegendHelper.hxx"
#include "TitleHelper.hxx"
#include "ChartModelHelper.hxx"
#include "AxisHelper.hxx"
#include "DiagramHelper.hxx"

#include "ChartModel.hxx"

using namespace css;
using namespace css::uno;
using ::sfx2::sidebar::Theme;

namespace chart { namespace sidebar {

namespace {

enum class GridType
{
    VERT_MAJOR,
    VERT_MINOR,
    HOR_MAJOR,
    HOR_MINOR
};

enum class AxisType
{
    X_MAIN,
    Y_MAIN,
    Z_MAIN,
    X_SECOND,
    Y_SECOND
};

class ChartSidebarModifyListener : public cppu::WeakImplHelper1<css::util::XModifyListener>
{
public:

    ChartSidebarModifyListener(ChartElementsPanel* pParent);
    virtual ~ChartSidebarModifyListener();

    virtual void SAL_CALL modified(const css::lang::EventObject& rEvent)
        throw (::css::uno::RuntimeException, ::std::exception) SAL_OVERRIDE;

    virtual void SAL_CALL disposing(const css::lang::EventObject& rEvent)
        throw (::css::uno::RuntimeException, ::std::exception) SAL_OVERRIDE;

private:
    ChartElementsPanel* mpParent;
};

ChartSidebarModifyListener::ChartSidebarModifyListener(ChartElementsPanel* pParent):
    mpParent(pParent)
{
}

ChartSidebarModifyListener::~ChartSidebarModifyListener()
{
}

void ChartSidebarModifyListener::modified(const css::lang::EventObject& /*rEvent*/)
        throw (::css::uno::RuntimeException, ::std::exception)
{
    mpParent->updateData();
}

void ChartSidebarModifyListener::disposing(const css::lang::EventObject& /*rEvent*/)
        throw (::css::uno::RuntimeException, ::std::exception)
{
    mpParent->modelInvalid();
}

ChartModel* getChartModel(css::uno::Reference<css::frame::XModel> xModel)
{
    ChartModel* pModel = dynamic_cast<ChartModel*>(xModel.get());

    return pModel;
}

bool isLegendVisible(css::uno::Reference<css::frame::XModel> xModel)
{
    ChartModel* pModel = getChartModel(xModel);
    if (!pModel)
        return false;

    Reference< beans::XPropertySet > xLegendProp( LegendHelper::getLegend(*pModel), uno::UNO_QUERY );
    if( xLegendProp.is())
    {
        try
        {
            bool bShow = false;
            if( xLegendProp->getPropertyValue( "Show") >>= bShow )
            {
                return bShow;
            }
        }
        catch(const uno::Exception &)
        {
        }
    }

    return false;
}

bool isTitleVisisble(css::uno::Reference<css::frame::XModel> xModel, TitleHelper::eTitleType eTitle)
{
    return TitleHelper::getTitle(eTitle, xModel).is();
}

bool isGridVisible(css::uno::Reference<css::frame::XModel> xModel, GridType eType)
{
    Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel));
    if(xDiagram.is())
    {
        sal_Int32 nDimensionIndex = 0;
        if (eType == GridType::HOR_MAJOR || eType == GridType::HOR_MINOR)
            nDimensionIndex = 1;
        sal_Int32 nCooSysIndex = 0;

        bool bMajor = (eType == GridType::HOR_MAJOR || eType == GridType::VERT_MAJOR);

        bool bHasGrid = AxisHelper::isGridShown(nDimensionIndex, nCooSysIndex, bMajor, xDiagram);
        return bHasGrid;
    }
    return false;
}

bool isAxisVisible(css::uno::Reference<css::frame::XModel> xModel, AxisType eType)
{
    Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel));
    if(xDiagram.is())
    {
        sal_Int32 nDimensionIndex = 0;
        if (eType == AxisType::Y_MAIN || eType == AxisType::Y_SECOND)
            nDimensionIndex = 1;
        else if (eType == AxisType::Z_MAIN)
            nDimensionIndex = 2;

        bool bMajor = !(eType == AxisType::X_SECOND || eType == AxisType::Y_SECOND);

        bool bHasAxis = AxisHelper::isAxisShown(nDimensionIndex, bMajor, xDiagram);
        return bHasAxis;
    }
    return false;
}

void setAxisVisible(css::uno::Reference<css::frame::XModel> xModel, AxisType eType, bool bVisible)
{
    Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel));
    if(xDiagram.is())
    {
        sal_Int32 nDimensionIndex = 0;
        if (eType == AxisType::Y_MAIN || eType == AxisType::Y_SECOND)
            nDimensionIndex = 1;
        else if (eType == AxisType::Z_MAIN)
            nDimensionIndex = 2;

        bool bMajor = !(eType == AxisType::X_SECOND || eType == AxisType::Y_SECOND);

        if (bVisible)
            AxisHelper::showAxis(nDimensionIndex, bMajor, xDiagram, comphelper::getProcessComponentContext());
        else
            AxisHelper::hideAxis(nDimensionIndex, bMajor, xDiagram);
    }
}

}

ChartElementsPanel::ChartElementsPanel(
    vcl::Window* pParent,
    const css::uno::Reference<css::frame::XFrame>& rxFrame,
    SfxBindings* pBindings,
    ChartController* pController)
  : PanelLayout(pParent, "ChartElementsPanel", "modules/schart/ui/sidebarelements.ui", rxFrame),
    mxFrame(rxFrame),
    maContext(),
    mpBindings(pBindings),
    mxModel(pController->getModel()),
    mxListener(new ChartSidebarModifyListener(this))
{
    get(mpCBTitle,  "checkbutton_title");
    get(mpCBSubtitle,  "checkbutton_subtitle");
    get(mpCBXAxis,  "checkbutton_x_axis");
    get(mpCBXAxisTitle,  "checkbutton_x_axis_title");
    get(mpCBYAxis,  "checkbutton_y_axis");
    get(mpCBYAxisTitle,  "checkbutton_y_axis_title");
    get(mpCBZAxis,  "checkbutton_z_axis");
    get(mpCBZAxisTitle,  "checkbutton_z_axis_title");
    get(mpCB2ndXAxis,  "checkbutton_2nd_x_axis");
    get(mpCB2ndXAxisTitle,  "checkbutton_2nd_x_axis_title");
    get(mpCB2ndYAxis,  "checkbutton_2nd_y_axis");
    get(mpCB2ndYAxisTitle,  "checkbutton_2nd_y_axis_title");
    get(mpCBLegend,  "checkbutton_legend");
    get(mpCBGridVertical,  "checkbutton_gridline_vertical");
    get(mpCBGridHorizontal,  "checkbutton_gridline_horizontal");
    get(mpCBShowLabel,  "checkbutton_label");
    get(mpCBTrendline,  "checkbutton_trendline");
}

ChartElementsPanel::~ChartElementsPanel()
{
    disposeOnce();
}

void ChartElementsPanel::dispose()
{

    css::uno::Reference<css::util::XModifyBroadcaster> xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW);
    xBroadcaster->removeModifyListener(mxListener);
    mpCBTitle.clear();
    mpCBSubtitle.clear();
    mpCBXAxis.clear();
    mpCBXAxisTitle.clear();
    mpCBYAxis.clear();
    mpCBYAxisTitle.clear();
    mpCBZAxis.clear();
    mpCBZAxisTitle.clear();
    mpCB2ndXAxis.clear();
    mpCB2ndXAxisTitle.clear();
    mpCB2ndYAxis.clear();
    mpCB2ndYAxisTitle.clear();
    mpCBLegend.clear();
    mpCBGridVertical.clear();
    mpCBGridHorizontal.clear();
    mpCBShowLabel.clear();
    mpCBTrendline.clear();

    PanelLayout::dispose();
}

void ChartElementsPanel::Initialize()
{
    css::uno::Reference<css::util::XModifyBroadcaster> xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW);
    xBroadcaster->addModifyListener(mxListener);
    updateData();

    Link<> aLink = LINK(this, ChartElementsPanel, CheckBoxHdl);
    mpCBTitle->SetClickHdl(aLink);
    mpCBSubtitle->SetClickHdl(aLink);
    mpCBXAxis->SetClickHdl(aLink);
    mpCBXAxisTitle->SetClickHdl(aLink);
    mpCBYAxis->SetClickHdl(aLink);
    mpCBYAxisTitle->SetClickHdl(aLink);
    mpCBZAxis->SetClickHdl(aLink);
    mpCBZAxisTitle->SetClickHdl(aLink);
    mpCB2ndXAxis->SetClickHdl(aLink);
    mpCB2ndXAxisTitle->SetClickHdl(aLink);
    mpCB2ndYAxis->SetClickHdl(aLink);
    mpCB2ndYAxisTitle->SetClickHdl(aLink);
    mpCBLegend->SetClickHdl(aLink);
    mpCBGridVertical->SetClickHdl(aLink);
    mpCBGridHorizontal->SetClickHdl(aLink);
}

void ChartElementsPanel::updateData()
{
    Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(mxModel));
    sal_Int32 nDimension = DiagramHelper::getDimension(xDiagram);
    SolarMutexGuard aGuard;

    mpCBLegend->Check(isLegendVisible(mxModel));
    mpCBTitle->Check(isTitleVisisble(mxModel, TitleHelper::MAIN_TITLE));
    mpCBSubtitle->Check(isTitleVisisble(mxModel, TitleHelper::SUB_TITLE));
    mpCBXAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::X_AXIS_TITLE));
    mpCBYAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::Y_AXIS_TITLE));
    mpCBZAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::Z_AXIS_TITLE));
    mpCB2ndXAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::SECONDARY_X_AXIS_TITLE));
    mpCB2ndYAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::SECONDARY_Y_AXIS_TITLE));
    mpCBGridVertical->Check(isGridVisible(mxModel, GridType::VERT_MAJOR));
    mpCBGridHorizontal->Check(isGridVisible(mxModel, GridType::HOR_MAJOR));
    mpCBXAxis->Check(isAxisVisible(mxModel, AxisType::X_MAIN));
    mpCBYAxis->Check(isAxisVisible(mxModel, AxisType::Y_MAIN));
    mpCBZAxis->Check(isAxisVisible(mxModel, AxisType::Z_MAIN));
    mpCB2ndXAxis->Check(isAxisVisible(mxModel, AxisType::X_SECOND));
    mpCB2ndYAxis->Check(isAxisVisible(mxModel, AxisType::Y_SECOND));

    if (nDimension != 3)
    {
        mpCBZAxis->Disable();
        mpCBZAxisTitle->Disable();
    }
}

VclPtr<vcl::Window> ChartElementsPanel::Create (
    vcl::Window* pParent,
    const css::uno::Reference<css::frame::XFrame>& rxFrame,
    SfxBindings* pBindings, ChartController* pController)
{
    if (pParent == NULL)
        throw lang::IllegalArgumentException("no parent Window given to ChartElementsPanel::Create", NULL, 0);
    if ( ! rxFrame.is())
        throw lang::IllegalArgumentException("no XFrame given to ChartElementsPanel::Create", NULL, 1);
    if (pBindings == NULL)
        throw lang::IllegalArgumentException("no SfxBindings given to ChartElementsPanel::Create", NULL, 2);

    return  VclPtr<ChartElementsPanel>::Create(
                        pParent, rxFrame, pBindings, pController);
}

void ChartElementsPanel::DataChanged(
    const DataChangedEvent& )
{
    updateData();
}

void ChartElementsPanel::HandleContextChange(
    const ::sfx2::sidebar::EnumContext& rContext)
{
    if(maContext == rContext)
    {
        // Nothing to do.
        return;
    }

    maContext = rContext;
    updateData();
}

void ChartElementsPanel::NotifyItemUpdate(
    sal_uInt16 /*nSID*/,
    SfxItemState /*eState*/,
    const SfxPoolItem* /*pState*/,
    const bool )
{
}

void ChartElementsPanel::modelInvalid()
{

}

IMPL_LINK(ChartElementsPanel, CheckBoxHdl, CheckBox*, pCheckBox)
{
    bool bChecked = pCheckBox->IsChecked();
    if (pCheckBox == mpCBTitle.get())
    {
    }
    else if (pCheckBox == mpCBXAxis.get())
        setAxisVisible(mxModel, AxisType::X_MAIN, bChecked);
    else if (pCheckBox == mpCBYAxis.get())
        setAxisVisible(mxModel, AxisType::Y_MAIN, bChecked);
    else if (pCheckBox == mpCB2ndXAxis.get())
        setAxisVisible(mxModel, AxisType::X_SECOND, bChecked);
    else if (pCheckBox == mpCB2ndYAxis.get())
        setAxisVisible(mxModel, AxisType::Y_SECOND, bChecked);

    return 0;
}

}} // end of namespace ::chart::sidebar

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>also react to title checkboxes<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <sfx2/sidebar/ResourceDefinitions.hrc>
#include <sfx2/sidebar/Theme.hxx>
#include <sfx2/sidebar/ControlFactory.hxx>
#include "ChartElementsPanel.hxx"
#include "ChartController.hxx"
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/imagemgr.hxx>
#include <vcl/fixed.hxx>
#include <vcl/lstbox.hxx>
#include <vcl/field.hxx>
#include <vcl/toolbox.hxx>
#include <svl/intitem.hxx>
#include <svl/stritem.hxx>
#include <comphelper/processfactory.hxx>

#include "LegendHelper.hxx"
#include "TitleHelper.hxx"
#include "ChartModelHelper.hxx"
#include "AxisHelper.hxx"
#include "DiagramHelper.hxx"

#include "ChartModel.hxx"

using namespace css;
using namespace css::uno;
using ::sfx2::sidebar::Theme;

namespace chart { namespace sidebar {

namespace {

enum class GridType
{
    VERT_MAJOR,
    VERT_MINOR,
    HOR_MAJOR,
    HOR_MINOR
};

enum class AxisType
{
    X_MAIN,
    Y_MAIN,
    Z_MAIN,
    X_SECOND,
    Y_SECOND
};

class ChartSidebarModifyListener : public cppu::WeakImplHelper1<css::util::XModifyListener>
{
public:

    ChartSidebarModifyListener(ChartElementsPanel* pParent);
    virtual ~ChartSidebarModifyListener();

    virtual void SAL_CALL modified(const css::lang::EventObject& rEvent)
        throw (::css::uno::RuntimeException, ::std::exception) SAL_OVERRIDE;

    virtual void SAL_CALL disposing(const css::lang::EventObject& rEvent)
        throw (::css::uno::RuntimeException, ::std::exception) SAL_OVERRIDE;

private:
    ChartElementsPanel* mpParent;
};

ChartSidebarModifyListener::ChartSidebarModifyListener(ChartElementsPanel* pParent):
    mpParent(pParent)
{
}

ChartSidebarModifyListener::~ChartSidebarModifyListener()
{
}

void ChartSidebarModifyListener::modified(const css::lang::EventObject& /*rEvent*/)
        throw (::css::uno::RuntimeException, ::std::exception)
{
    mpParent->updateData();
}

void ChartSidebarModifyListener::disposing(const css::lang::EventObject& /*rEvent*/)
        throw (::css::uno::RuntimeException, ::std::exception)
{
    mpParent->modelInvalid();
}

ChartModel* getChartModel(css::uno::Reference<css::frame::XModel> xModel)
{
    ChartModel* pModel = dynamic_cast<ChartModel*>(xModel.get());

    return pModel;
}

bool isLegendVisible(css::uno::Reference<css::frame::XModel> xModel)
{
    ChartModel* pModel = getChartModel(xModel);
    if (!pModel)
        return false;

    Reference< beans::XPropertySet > xLegendProp( LegendHelper::getLegend(*pModel), uno::UNO_QUERY );
    if( xLegendProp.is())
    {
        try
        {
            bool bShow = false;
            if( xLegendProp->getPropertyValue( "Show") >>= bShow )
            {
                return bShow;
            }
        }
        catch(const uno::Exception &)
        {
        }
    }

    return false;
}

bool isTitleVisisble(css::uno::Reference<css::frame::XModel> xModel, TitleHelper::eTitleType eTitle)
{
    return TitleHelper::getTitle(eTitle, xModel).is();
}

void setTitleVisible(css::uno::Reference<css::frame::XModel> xModel, TitleHelper::eTitleType eTitle, bool bVisible)
{
    if (bVisible)
    {
        TitleHelper::createTitle(eTitle, "Title", xModel, comphelper::getProcessComponentContext());
    }
    else
    {
        TitleHelper::removeTitle(eTitle, xModel);
    }
}

bool isGridVisible(css::uno::Reference<css::frame::XModel> xModel, GridType eType)
{
    Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel));
    if(xDiagram.is())
    {
        sal_Int32 nDimensionIndex = 0;
        if (eType == GridType::HOR_MAJOR || eType == GridType::HOR_MINOR)
            nDimensionIndex = 1;
        sal_Int32 nCooSysIndex = 0;

        bool bMajor = (eType == GridType::HOR_MAJOR || eType == GridType::VERT_MAJOR);

        bool bHasGrid = AxisHelper::isGridShown(nDimensionIndex, nCooSysIndex, bMajor, xDiagram);
        return bHasGrid;
    }
    return false;
}

bool isAxisVisible(css::uno::Reference<css::frame::XModel> xModel, AxisType eType)
{
    Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel));
    if(xDiagram.is())
    {
        sal_Int32 nDimensionIndex = 0;
        if (eType == AxisType::Y_MAIN || eType == AxisType::Y_SECOND)
            nDimensionIndex = 1;
        else if (eType == AxisType::Z_MAIN)
            nDimensionIndex = 2;

        bool bMajor = !(eType == AxisType::X_SECOND || eType == AxisType::Y_SECOND);

        bool bHasAxis = AxisHelper::isAxisShown(nDimensionIndex, bMajor, xDiagram);
        return bHasAxis;
    }
    return false;
}

void setAxisVisible(css::uno::Reference<css::frame::XModel> xModel, AxisType eType, bool bVisible)
{
    Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(xModel));
    if(xDiagram.is())
    {
        sal_Int32 nDimensionIndex = 0;
        if (eType == AxisType::Y_MAIN || eType == AxisType::Y_SECOND)
            nDimensionIndex = 1;
        else if (eType == AxisType::Z_MAIN)
            nDimensionIndex = 2;

        bool bMajor = !(eType == AxisType::X_SECOND || eType == AxisType::Y_SECOND);

        if (bVisible)
            AxisHelper::showAxis(nDimensionIndex, bMajor, xDiagram, comphelper::getProcessComponentContext());
        else
            AxisHelper::hideAxis(nDimensionIndex, bMajor, xDiagram);
    }
}

}

ChartElementsPanel::ChartElementsPanel(
    vcl::Window* pParent,
    const css::uno::Reference<css::frame::XFrame>& rxFrame,
    SfxBindings* pBindings,
    ChartController* pController)
  : PanelLayout(pParent, "ChartElementsPanel", "modules/schart/ui/sidebarelements.ui", rxFrame),
    mxFrame(rxFrame),
    maContext(),
    mpBindings(pBindings),
    mxModel(pController->getModel()),
    mxListener(new ChartSidebarModifyListener(this))
{
    get(mpCBTitle,  "checkbutton_title");
    get(mpCBSubtitle,  "checkbutton_subtitle");
    get(mpCBXAxis,  "checkbutton_x_axis");
    get(mpCBXAxisTitle,  "checkbutton_x_axis_title");
    get(mpCBYAxis,  "checkbutton_y_axis");
    get(mpCBYAxisTitle,  "checkbutton_y_axis_title");
    get(mpCBZAxis,  "checkbutton_z_axis");
    get(mpCBZAxisTitle,  "checkbutton_z_axis_title");
    get(mpCB2ndXAxis,  "checkbutton_2nd_x_axis");
    get(mpCB2ndXAxisTitle,  "checkbutton_2nd_x_axis_title");
    get(mpCB2ndYAxis,  "checkbutton_2nd_y_axis");
    get(mpCB2ndYAxisTitle,  "checkbutton_2nd_y_axis_title");
    get(mpCBLegend,  "checkbutton_legend");
    get(mpCBGridVertical,  "checkbutton_gridline_vertical");
    get(mpCBGridHorizontal,  "checkbutton_gridline_horizontal");
    get(mpCBShowLabel,  "checkbutton_label");
    get(mpCBTrendline,  "checkbutton_trendline");
}

ChartElementsPanel::~ChartElementsPanel()
{
    disposeOnce();
}

void ChartElementsPanel::dispose()
{

    css::uno::Reference<css::util::XModifyBroadcaster> xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW);
    xBroadcaster->removeModifyListener(mxListener);
    mpCBTitle.clear();
    mpCBSubtitle.clear();
    mpCBXAxis.clear();
    mpCBXAxisTitle.clear();
    mpCBYAxis.clear();
    mpCBYAxisTitle.clear();
    mpCBZAxis.clear();
    mpCBZAxisTitle.clear();
    mpCB2ndXAxis.clear();
    mpCB2ndXAxisTitle.clear();
    mpCB2ndYAxis.clear();
    mpCB2ndYAxisTitle.clear();
    mpCBLegend.clear();
    mpCBGridVertical.clear();
    mpCBGridHorizontal.clear();
    mpCBShowLabel.clear();
    mpCBTrendline.clear();

    PanelLayout::dispose();
}

void ChartElementsPanel::Initialize()
{
    css::uno::Reference<css::util::XModifyBroadcaster> xBroadcaster(mxModel, css::uno::UNO_QUERY_THROW);
    xBroadcaster->addModifyListener(mxListener);
    updateData();

    Link<> aLink = LINK(this, ChartElementsPanel, CheckBoxHdl);
    mpCBTitle->SetClickHdl(aLink);
    mpCBSubtitle->SetClickHdl(aLink);
    mpCBXAxis->SetClickHdl(aLink);
    mpCBXAxisTitle->SetClickHdl(aLink);
    mpCBYAxis->SetClickHdl(aLink);
    mpCBYAxisTitle->SetClickHdl(aLink);
    mpCBZAxis->SetClickHdl(aLink);
    mpCBZAxisTitle->SetClickHdl(aLink);
    mpCB2ndXAxis->SetClickHdl(aLink);
    mpCB2ndXAxisTitle->SetClickHdl(aLink);
    mpCB2ndYAxis->SetClickHdl(aLink);
    mpCB2ndYAxisTitle->SetClickHdl(aLink);
    mpCBLegend->SetClickHdl(aLink);
    mpCBGridVertical->SetClickHdl(aLink);
    mpCBGridHorizontal->SetClickHdl(aLink);
}

void ChartElementsPanel::updateData()
{
    Reference< chart2::XDiagram > xDiagram(ChartModelHelper::findDiagram(mxModel));
    sal_Int32 nDimension = DiagramHelper::getDimension(xDiagram);
    SolarMutexGuard aGuard;

    mpCBLegend->Check(isLegendVisible(mxModel));
    mpCBTitle->Check(isTitleVisisble(mxModel, TitleHelper::MAIN_TITLE));
    mpCBSubtitle->Check(isTitleVisisble(mxModel, TitleHelper::SUB_TITLE));
    mpCBXAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::X_AXIS_TITLE));
    mpCBYAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::Y_AXIS_TITLE));
    mpCBZAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::Z_AXIS_TITLE));
    mpCB2ndXAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::SECONDARY_X_AXIS_TITLE));
    mpCB2ndYAxisTitle->Check(isTitleVisisble(mxModel, TitleHelper::SECONDARY_Y_AXIS_TITLE));
    mpCBGridVertical->Check(isGridVisible(mxModel, GridType::VERT_MAJOR));
    mpCBGridHorizontal->Check(isGridVisible(mxModel, GridType::HOR_MAJOR));
    mpCBXAxis->Check(isAxisVisible(mxModel, AxisType::X_MAIN));
    mpCBYAxis->Check(isAxisVisible(mxModel, AxisType::Y_MAIN));
    mpCBZAxis->Check(isAxisVisible(mxModel, AxisType::Z_MAIN));
    mpCB2ndXAxis->Check(isAxisVisible(mxModel, AxisType::X_SECOND));
    mpCB2ndYAxis->Check(isAxisVisible(mxModel, AxisType::Y_SECOND));

    if (nDimension != 3)
    {
        mpCBZAxis->Disable();
        mpCBZAxisTitle->Disable();
    }
}

VclPtr<vcl::Window> ChartElementsPanel::Create (
    vcl::Window* pParent,
    const css::uno::Reference<css::frame::XFrame>& rxFrame,
    SfxBindings* pBindings, ChartController* pController)
{
    if (pParent == NULL)
        throw lang::IllegalArgumentException("no parent Window given to ChartElementsPanel::Create", NULL, 0);
    if ( ! rxFrame.is())
        throw lang::IllegalArgumentException("no XFrame given to ChartElementsPanel::Create", NULL, 1);
    if (pBindings == NULL)
        throw lang::IllegalArgumentException("no SfxBindings given to ChartElementsPanel::Create", NULL, 2);

    return  VclPtr<ChartElementsPanel>::Create(
                        pParent, rxFrame, pBindings, pController);
}

void ChartElementsPanel::DataChanged(
    const DataChangedEvent& )
{
    updateData();
}

void ChartElementsPanel::HandleContextChange(
    const ::sfx2::sidebar::EnumContext& rContext)
{
    if(maContext == rContext)
    {
        // Nothing to do.
        return;
    }

    maContext = rContext;
    updateData();
}

void ChartElementsPanel::NotifyItemUpdate(
    sal_uInt16 /*nSID*/,
    SfxItemState /*eState*/,
    const SfxPoolItem* /*pState*/,
    const bool )
{
}

void ChartElementsPanel::modelInvalid()
{

}

IMPL_LINK(ChartElementsPanel, CheckBoxHdl, CheckBox*, pCheckBox)
{
    bool bChecked = pCheckBox->IsChecked();
    if (pCheckBox == mpCBTitle.get())
        setTitleVisible(mxModel, TitleHelper::MAIN_TITLE, bChecked);
    else if (pCheckBox == mpCBSubtitle.get())
        setTitleVisible(mxModel, TitleHelper::SUB_TITLE, bChecked);
    else if (pCheckBox == mpCBXAxis.get())
        setAxisVisible(mxModel, AxisType::X_MAIN, bChecked);
    else if (pCheckBox == mpCBXAxisTitle.get())
        setTitleVisible(mxModel, TitleHelper::X_AXIS_TITLE, bChecked);
    else if (pCheckBox == mpCBYAxis.get())
        setAxisVisible(mxModel, AxisType::Y_MAIN, bChecked);
    else if (pCheckBox == mpCBYAxisTitle.get())
        setTitleVisible(mxModel, TitleHelper::Y_AXIS_TITLE, bChecked);
    else if (pCheckBox == mpCBZAxis.get())
        setAxisVisible(mxModel, AxisType::Z_MAIN, bChecked);
    else if (pCheckBox == mpCBZAxisTitle.get())
        setTitleVisible(mxModel, TitleHelper::Z_AXIS_TITLE, bChecked);
    else if (pCheckBox == mpCB2ndXAxis.get())
        setAxisVisible(mxModel, AxisType::X_SECOND, bChecked);
    else if (pCheckBox == mpCB2ndXAxisTitle.get())
        setTitleVisible(mxModel, TitleHelper::SECONDARY_X_AXIS_TITLE, bChecked);
    else if (pCheckBox == mpCB2ndYAxis.get())
        setAxisVisible(mxModel, AxisType::Y_SECOND, bChecked);
    else if (pCheckBox == mpCB2ndYAxisTitle.get())
        setTitleVisible(mxModel, TitleHelper::SECONDARY_Y_AXIS_TITLE, bChecked);

    return 0;
}

}} // end of namespace ::chart::sidebar

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


<commit_before>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkImageDecoder.h"
#include "SkColor.h"
#include "SkColorPriv.h"
#include "SkStream.h"
#include "SkTemplates.h"
#include "SkPackBits.h"

#include "gif_lib.h"

class SkGIFImageDecoder : public SkImageDecoder {
public:
    virtual Format getFormat() const {
        return kGIF_Format;
    }

protected:
    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
};

static const uint8_t gStartingIterlaceYValue[] = {
    0, 4, 2, 1
};
static const uint8_t gDeltaIterlaceYValue[] = {
    8, 8, 4, 2
};

/*  Implement the GIF interlace algorithm in an iterator.
    1) grab every 8th line beginning at 0
    2) grab every 8th line beginning at 4
    3) grab every 4th line beginning at 2
    4) grab every 2nd line beginning at 1
*/
class GifInterlaceIter {
public:
    GifInterlaceIter(int height) : fHeight(height) {
        fStartYPtr = gStartingIterlaceYValue;
        fDeltaYPtr = gDeltaIterlaceYValue;

        fCurrY = *fStartYPtr++;
        fDeltaY = *fDeltaYPtr++;
    }

    int currY() const {
        SkASSERT(fStartYPtr);
        SkASSERT(fDeltaYPtr);
        return fCurrY;
    }

    void next() {
        SkASSERT(fStartYPtr);
        SkASSERT(fDeltaYPtr);

        int y = fCurrY + fDeltaY;
        // We went from an if statement to a while loop so that we iterate
        // through fStartYPtr until a valid row is found. This is so that images
        // that are smaller than 5x5 will not trash memory.
        while (y >= fHeight) {
            if (gStartingIterlaceYValue +
                    SK_ARRAY_COUNT(gStartingIterlaceYValue) == fStartYPtr) {
                // we done
                SkDEBUGCODE(fStartYPtr = NULL;)
                SkDEBUGCODE(fDeltaYPtr = NULL;)
                y = 0;
            } else {
                y = *fStartYPtr++;
                fDeltaY = *fDeltaYPtr++;
            }
        }
        fCurrY = y;
    }

private:
    const int fHeight;
    int fCurrY;
    int fDeltaY;
    const uint8_t* fStartYPtr;
    const uint8_t* fDeltaYPtr;
};

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

//#define GIF_STAMP       "GIF"    /* First chars in file - GIF stamp. */
//#define GIF_STAMP_LEN   (sizeof(GIF_STAMP) - 1)

static int DecodeCallBackProc(GifFileType* fileType, GifByteType* out,
                              int size) {
    SkStream* stream = (SkStream*) fileType->UserData;
    return (int) stream->read(out, size);
}

void CheckFreeExtension(SavedImage* Image) {
    if (Image->ExtensionBlocks) {
#if GIFLIB_MAJOR < 5
        FreeExtension(Image);
#else
        GifFreeExtensions(&Image->ExtensionBlockCount, &Image->ExtensionBlocks);
#endif
    }
}

// return NULL on failure
static const ColorMapObject* find_colormap(const GifFileType* gif) {
    const ColorMapObject* cmap = gif->Image.ColorMap;
    if (NULL == cmap) {
        cmap = gif->SColorMap;
    }

    if (NULL == cmap) {
        // no colormap found
        return NULL;
    }
    // some sanity checks
    if (cmap && ((unsigned)cmap->ColorCount > 256 ||
                 cmap->ColorCount != (1 << cmap->BitsPerPixel))) {
        cmap = NULL;
    }
    return cmap;
}

// return -1 if not found (i.e. we're completely opaque)
static int find_transpIndex(const SavedImage& image, int colorCount) {
    int transpIndex = -1;
    for (int i = 0; i < image.ExtensionBlockCount; ++i) {
        const ExtensionBlock* eb = image.ExtensionBlocks + i;
        if (eb->Function == 0xF9 && eb->ByteCount == 4) {
            if (eb->Bytes[0] & 1) {
                transpIndex = (unsigned char)eb->Bytes[3];
                // check for valid transpIndex
                if (transpIndex >= colorCount) {
                    transpIndex = -1;
                }
                break;
            }
        }
    }
    return transpIndex;
}

static bool error_return(GifFileType* gif, const SkBitmap& bm,
                         const char msg[]) {
#if 0
    SkDebugf("libgif error <%s> bitmap [%d %d] pixels %p colortable %p\n",
             msg, bm.width(), bm.height(), bm.getPixels(), bm.getColorTable());
#endif
    return false;
}

bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
#if GIFLIB_MAJOR < 5
    GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
#else
    GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL);
#endif
    if (NULL == gif) {
        return error_return(gif, *bm, "DGifOpen");
    }

    SkAutoTCallIProc<GifFileType, DGifCloseFile> acp(gif);

    SavedImage temp_save;
    temp_save.ExtensionBlocks=NULL;
    temp_save.ExtensionBlockCount=0;
    SkAutoTCallVProc<SavedImage, CheckFreeExtension> acp2(&temp_save);

    int width, height;
    GifRecordType recType;
    GifByteType *extData;
#if GIFLIB_MAJOR >= 5
    int extFunction;
#endif
    int transpIndex = -1;   // -1 means we don't have it (yet)

    do {
        if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
            return error_return(gif, *bm, "DGifGetRecordType");
        }

        switch (recType) {
        case IMAGE_DESC_RECORD_TYPE: {
            if (DGifGetImageDesc(gif) == GIF_ERROR) {
                return error_return(gif, *bm, "IMAGE_DESC_RECORD_TYPE");
            }

            if (gif->ImageCount < 1) {    // sanity check
                return error_return(gif, *bm, "ImageCount < 1");
            }

            width = gif->SWidth;
            height = gif->SHeight;
            if (width <= 0 || height <= 0 ||
                !this->chooseFromOneChoice(SkBitmap::kIndex8_Config,
                                           width, height)) {
                return error_return(gif, *bm, "chooseFromOneChoice");
            }

            if (SkImageDecoder::kDecodeBounds_Mode == mode) {
                bm->setConfig(SkBitmap::kIndex8_Config, width, height);
                return true;
            }
#ifdef SK_BUILD_FOR_ANDROID
            // No Bitmap reuse supported for this format
            if (!bm->isNull()) {
                return false;
            }
#endif

            bm->setConfig(SkBitmap::kIndex8_Config, width, height);
            SavedImage* image = &gif->SavedImages[gif->ImageCount-1];
            const GifImageDesc& desc = image->ImageDesc;

            // check for valid descriptor
            if (   (desc.Top | desc.Left) < 0 ||
                    desc.Left + desc.Width > width ||
                    desc.Top + desc.Height > height) {
                return error_return(gif, *bm, "TopLeft");
            }

            // now we decode the colortable
            int colorCount = 0;
            {
                const ColorMapObject* cmap = find_colormap(gif);
                if (NULL == cmap) {
                    return error_return(gif, *bm, "null cmap");
                }

                colorCount = cmap->ColorCount;
                SkColorTable* ctable = SkNEW_ARGS(SkColorTable, (colorCount));
                SkPMColor* colorPtr = ctable->lockColors();
                for (int index = 0; index < colorCount; index++)
                    colorPtr[index] = SkPackARGB32(0xFF,
                                                   cmap->Colors[index].Red,
                                                   cmap->Colors[index].Green,
                                                   cmap->Colors[index].Blue);

                transpIndex = find_transpIndex(temp_save, colorCount);
                if (transpIndex < 0)
                    ctable->setFlags(ctable->getFlags() | SkColorTable::kColorsAreOpaque_Flag);
                else
                    colorPtr[transpIndex] = 0; // ram in a transparent SkPMColor
                ctable->unlockColors(true);

                SkAutoUnref aurts(ctable);
                if (!this->allocPixelRef(bm, ctable)) {
                    return error_return(gif, *bm, "allocPixelRef");
                }
            }

            SkAutoLockPixels alp(*bm);

            // time to decode the scanlines
            //
            uint8_t*  scanline = bm->getAddr8(0, 0);
            const int rowBytes = bm->rowBytes();
            const int innerWidth = desc.Width;
            const int innerHeight = desc.Height;

            // abort if either inner dimension is <= 0
            if (innerWidth <= 0 || innerHeight <= 0) {
                return error_return(gif, *bm, "non-pos inner width/height");
            }

            // are we only a subset of the total bounds?
            if ((desc.Top | desc.Left) > 0 ||
                 innerWidth < width || innerHeight < height)
            {
                int fill;
                if (transpIndex >= 0) {
                    fill = transpIndex;
                } else {
                    fill = gif->SBackGroundColor;
                }
                // check for valid fill index/color
                if (static_cast<unsigned>(fill) >=
                        static_cast<unsigned>(colorCount)) {
                    fill = 0;
                }
                memset(scanline, fill, bm->getSize());
                // bump our starting address
                scanline += desc.Top * rowBytes + desc.Left;
            }

            // now decode each scanline
            if (gif->Image.Interlace)
            {
                GifInterlaceIter iter(innerHeight);
                for (int y = 0; y < innerHeight; y++)
                {
                    uint8_t* row = scanline + iter.currY() * rowBytes;
                    if (DGifGetLine(gif, row, innerWidth) == GIF_ERROR) {
                        return error_return(gif, *bm, "interlace DGifGetLine");
                    }
                    iter.next();
                }
            }
            else
            {
                // easy, non-interlace case
                for (int y = 0; y < innerHeight; y++) {
                    if (DGifGetLine(gif, scanline, innerWidth) == GIF_ERROR) {
                        return error_return(gif, *bm, "DGifGetLine");
                    }
                    scanline += rowBytes;
                }
            }
            goto DONE;
            } break;

        case EXTENSION_RECORD_TYPE:
#if GIFLIB_MAJOR < 5
            if (DGifGetExtension(gif, &temp_save.Function,
                                 &extData) == GIF_ERROR) {
#else
            if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) {
#endif
                return error_return(gif, *bm, "DGifGetExtension");
            }

            while (extData != NULL) {
                /* Create an extension block with our data */
#if GIFLIB_MAJOR < 5
                if (AddExtensionBlock(&temp_save, extData[0],
                                      &extData[1]) == GIF_ERROR) {
#else
                if (GifAddExtensionBlock(&gif->ExtensionBlockCount,
                                         &gif->ExtensionBlocks,
                                         extFunction,
                                         extData[0],
                                         &extData[1]) == GIF_ERROR) {
#endif
                    return error_return(gif, *bm, "AddExtensionBlock");
                }
                if (DGifGetExtensionNext(gif, &extData) == GIF_ERROR) {
                    return error_return(gif, *bm, "DGifGetExtensionNext");
                }
#if GIFLIB_MAJOR < 5
                temp_save.Function = 0;
#endif
            }
            break;

        case TERMINATE_RECORD_TYPE:
            break;

        default:	/* Should be trapped by DGifGetRecordType */
            break;
        }
    } while (recType != TERMINATE_RECORD_TYPE);

DONE:
    return true;
}

///////////////////////////////////////////////////////////////////////////////
DEFINE_DECODER_CREATOR(GIFImageDecoder);
///////////////////////////////////////////////////////////////////////////////

#include "SkTRegistry.h"

static SkImageDecoder* sk_libgif_dfactory(SkStream* stream) {
    char buf[GIF_STAMP_LEN];
    if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
        if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
                memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
                memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) {
            return SkNEW(SkGIFImageDecoder);
        }
    }
    return NULL;
}

static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libgif_dfactory);
<commit_msg>skia: Fix Codenomicon image open failure.<commit_after>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkImageDecoder.h"
#include "SkColor.h"
#include "SkColorPriv.h"
#include "SkStream.h"
#include "SkTemplates.h"
#include "SkPackBits.h"

#include "gif_lib.h"

class SkGIFImageDecoder : public SkImageDecoder {
public:
    virtual Format getFormat() const {
        return kGIF_Format;
    }

protected:
    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
};

static const uint8_t gStartingIterlaceYValue[] = {
    0, 4, 2, 1
};
static const uint8_t gDeltaIterlaceYValue[] = {
    8, 8, 4, 2
};

/*  Implement the GIF interlace algorithm in an iterator.
    1) grab every 8th line beginning at 0
    2) grab every 8th line beginning at 4
    3) grab every 4th line beginning at 2
    4) grab every 2nd line beginning at 1
*/
class GifInterlaceIter {
public:
    GifInterlaceIter(int height) : fHeight(height) {
        fStartYPtr = gStartingIterlaceYValue;
        fDeltaYPtr = gDeltaIterlaceYValue;

        fCurrY = *fStartYPtr++;
        fDeltaY = *fDeltaYPtr++;
    }

    int currY() const {
        SkASSERT(fStartYPtr);
        SkASSERT(fDeltaYPtr);
        return fCurrY;
    }

    void next() {
        SkASSERT(fStartYPtr);
        SkASSERT(fDeltaYPtr);

        int y = fCurrY + fDeltaY;
        // We went from an if statement to a while loop so that we iterate
        // through fStartYPtr until a valid row is found. This is so that images
        // that are smaller than 5x5 will not trash memory.
        while (y >= fHeight) {
            if (gStartingIterlaceYValue +
                    SK_ARRAY_COUNT(gStartingIterlaceYValue) == fStartYPtr) {
                // we done
                SkDEBUGCODE(fStartYPtr = NULL;)
                SkDEBUGCODE(fDeltaYPtr = NULL;)
                y = 0;
            } else {
                y = *fStartYPtr++;
                fDeltaY = *fDeltaYPtr++;
            }
        }
        fCurrY = y;
    }

private:
    const int fHeight;
    int fCurrY;
    int fDeltaY;
    const uint8_t* fStartYPtr;
    const uint8_t* fDeltaYPtr;
};

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

//#define GIF_STAMP       "GIF"    /* First chars in file - GIF stamp. */
//#define GIF_STAMP_LEN   (sizeof(GIF_STAMP) - 1)

static int DecodeCallBackProc(GifFileType* fileType, GifByteType* out,
                              int size) {
    SkStream* stream = (SkStream*) fileType->UserData;
    return (int) stream->read(out, size);
}

void CheckFreeExtension(SavedImage* Image) {
    if (Image->ExtensionBlocks) {
#if GIFLIB_MAJOR < 5
        FreeExtension(Image);
#else
        GifFreeExtensions(&Image->ExtensionBlockCount, &Image->ExtensionBlocks);
#endif
    }
}

// return NULL on failure
static const ColorMapObject* find_colormap(const GifFileType* gif) {
    const ColorMapObject* cmap = gif->Image.ColorMap;
    if (NULL == cmap) {
        cmap = gif->SColorMap;
    }

    if (NULL == cmap) {
        // no colormap found
        return NULL;
    }
    // some sanity checks
    if (cmap && ((unsigned)cmap->ColorCount > 256 ||
                 cmap->ColorCount != (1 << cmap->BitsPerPixel))) {
        cmap = NULL;
    }
    return cmap;
}

// return -1 if not found (i.e. we're completely opaque)
static int find_transpIndex(const SavedImage& image, int colorCount) {
    int transpIndex = -1;
    for (int i = 0; i < image.ExtensionBlockCount; ++i) {
        const ExtensionBlock* eb = image.ExtensionBlocks + i;
        if (eb->Function == 0xF9 && eb->ByteCount == 4) {
            if (eb->Bytes[0] & 1) {
                transpIndex = (unsigned char)eb->Bytes[3];
                // check for valid transpIndex
                if (transpIndex >= colorCount) {
                    transpIndex = -1;
                }
                break;
            }
        }
    }
    return transpIndex;
}

static bool error_return(GifFileType* gif, const SkBitmap& bm,
                         const char msg[]) {
#if 0
    SkDebugf("libgif error <%s> bitmap [%d %d] pixels %p colortable %p\n",
             msg, bm.width(), bm.height(), bm.getPixels(), bm.getColorTable());
#endif
    return false;
}

bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
#if GIFLIB_MAJOR < 5
    GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
#else
    GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc, NULL);
#endif
    if (NULL == gif) {
        return error_return(gif, *bm, "DGifOpen");
    }

    SkAutoTCallIProc<GifFileType, DGifCloseFile> acp(gif);

    SavedImage temp_save;
    temp_save.ExtensionBlocks=NULL;
    temp_save.ExtensionBlockCount=0;
    SkAutoTCallVProc<SavedImage, CheckFreeExtension> acp2(&temp_save);

    int width, height;
    GifRecordType recType;
    GifByteType *extData;
#if GIFLIB_MAJOR >= 5
    int extFunction;
#endif
    int transpIndex = -1;   // -1 means we don't have it (yet)

    do {
        if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
            return error_return(gif, *bm, "DGifGetRecordType");
        }

        switch (recType) {
        case IMAGE_DESC_RECORD_TYPE: {
            if (DGifGetImageDesc(gif) == GIF_ERROR) {
                return error_return(gif, *bm, "IMAGE_DESC_RECORD_TYPE");
            }

            if (gif->ImageCount < 1) {    // sanity check
                return error_return(gif, *bm, "ImageCount < 1");
            }

            width = gif->SWidth;
            height = gif->SHeight;
            if (width <= 0 || height <= 0 ||
                !this->chooseFromOneChoice(SkBitmap::kIndex8_Config,
                                           width, height)) {
                return error_return(gif, *bm, "chooseFromOneChoice");
            }

            if (SkImageDecoder::kDecodeBounds_Mode == mode) {
                bm->setConfig(SkBitmap::kIndex8_Config, width, height);
                return true;
            }
#ifdef SK_BUILD_FOR_ANDROID
            // No Bitmap reuse supported for this format
            if (!bm->isNull()) {
                return false;
            }
#endif

            bm->setConfig(SkBitmap::kIndex8_Config, width, height);
            SavedImage* image = &gif->SavedImages[gif->ImageCount-1];
            const GifImageDesc& desc = image->ImageDesc;

            // check for valid descriptor
            if (   (desc.Top | desc.Left) < 0 ||
                    desc.Left + desc.Width > width ||
                    desc.Top + desc.Height > height) {
                return error_return(gif, *bm, "TopLeft");
            }

            // now we decode the colortable
            int colorCount = 0;
            {
                const ColorMapObject* cmap = find_colormap(gif);
                if (NULL == cmap) {
                    return error_return(gif, *bm, "null cmap");
                }

                colorCount = cmap->ColorCount;
                SkColorTable* ctable = SkNEW_ARGS(SkColorTable, (colorCount));
                SkPMColor* colorPtr = ctable->lockColors();
                for (int index = 0; index < colorCount; index++)
                    colorPtr[index] = SkPackARGB32(0xFF,
                                                   cmap->Colors[index].Red,
                                                   cmap->Colors[index].Green,
                                                   cmap->Colors[index].Blue);

                transpIndex = find_transpIndex(temp_save, colorCount);
                if (transpIndex < 0)
                    ctable->setFlags(ctable->getFlags() | SkColorTable::kColorsAreOpaque_Flag);
                else
                    colorPtr[transpIndex] = 0; // ram in a transparent SkPMColor
                ctable->unlockColors(true);

                SkAutoUnref aurts(ctable);
                if (!this->allocPixelRef(bm, ctable)) {
                    return error_return(gif, *bm, "allocPixelRef");
                }
            }

            SkAutoLockPixels alp(*bm);

            // time to decode the scanlines
            //
            uint8_t*  scanline = bm->getAddr8(0, 0);
            const int rowBytes = bm->rowBytes();
            const int innerWidth = desc.Width;
            const int innerHeight = desc.Height;

            // abort if either inner dimension is <= 0
            if (innerWidth <= 0 || innerHeight <= 0) {
                return error_return(gif, *bm, "non-pos inner width/height");
            }

            // are we only a subset of the total bounds?
            if ((desc.Top | desc.Left) > 0 ||
                 innerWidth < width || innerHeight < height)
            {
                int fill;
                if (transpIndex >= 0) {
                    fill = transpIndex;
                } else {
                    fill = gif->SBackGroundColor;
                }
                // check for valid fill index/color
                if (static_cast<unsigned>(fill) >=
                        static_cast<unsigned>(colorCount)) {
                    fill = 0;
                }
                memset(scanline, fill, bm->getSize());
                // bump our starting address
                scanline += desc.Top * rowBytes + desc.Left;
            }

            // now decode each scanline
            if (gif->Image.Interlace)
            {
                GifInterlaceIter iter(innerHeight);
                for (int y = 0; y < innerHeight; y++)
                {
                    uint8_t* row = scanline + iter.currY() * rowBytes;
                    if (DGifGetLine(gif, row, innerWidth) == GIF_ERROR) {
                        return error_return(gif, *bm, "interlace DGifGetLine");
                    }
                    iter.next();
                }
            }
            else
            {
                // easy, non-interlace case
                for (int y = 0; y < innerHeight; y++) {
                    if (DGifGetLine(gif, scanline, innerWidth) == GIF_ERROR) {
                        return error_return(gif, *bm, "DGifGetLine");
                    }
                    scanline += rowBytes;
                }
            }
        }
        return true;

        case EXTENSION_RECORD_TYPE:
#if GIFLIB_MAJOR < 5
            if (DGifGetExtension(gif, &temp_save.Function,
                                 &extData) == GIF_ERROR) {
#else
            if (DGifGetExtension(gif, &extFunction, &extData) == GIF_ERROR) {
#endif
                return error_return(gif, *bm, "DGifGetExtension");
            }

            while (extData != NULL) {
                /* Create an extension block with our data */
#if GIFLIB_MAJOR < 5
                if (AddExtensionBlock(&temp_save, extData[0],
                                      &extData[1]) == GIF_ERROR) {
#else
                if (GifAddExtensionBlock(&gif->ExtensionBlockCount,
                                         &gif->ExtensionBlocks,
                                         extFunction,
                                         extData[0],
                                         &extData[1]) == GIF_ERROR) {
#endif
                    return error_return(gif, *bm, "AddExtensionBlock");
                }
                if (DGifGetExtensionNext(gif, &extData) == GIF_ERROR) {
                    return error_return(gif, *bm, "DGifGetExtensionNext");
                }
#if GIFLIB_MAJOR < 5
                temp_save.Function = 0;
#endif
            }
            break;

        case TERMINATE_RECORD_TYPE:
            break;

        default:	/* Should be trapped by DGifGetRecordType */
            break;
        }
    } while (recType != TERMINATE_RECORD_TYPE);
    // Return error, since the image descriptor record type is not present
    return error_return(gif, *bm, "no image descriptor");
}

///////////////////////////////////////////////////////////////////////////////
DEFINE_DECODER_CREATOR(GIFImageDecoder);
///////////////////////////////////////////////////////////////////////////////

#include "SkTRegistry.h"

static SkImageDecoder* sk_libgif_dfactory(SkStream* stream) {
    char buf[GIF_STAMP_LEN];
    if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
        if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
                memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
                memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) {
            return SkNEW(SkGIFImageDecoder);
        }
    }
    return NULL;
}

static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libgif_dfactory);
<|endoftext|>


<commit_before>#ifndef PARSER_HXX_RGFUMH5N
#define PARSER_HXX_RGFUMH5N

#include "ast.hxx"
#include "token.hxx"
#include "lemon.hxx"

namespace miniml
{

struct Parser
{
  Parser();
  ~Parser();

  Ptr<Expr> parse(const Ptr<String>);

private:
  void *parser;
};

}

#endif /* end of include guard: PARSER_HXX_RGFUMH5N */
<commit_msg>FIXUP parse vec<commit_after>#ifndef PARSER_HXX_RGFUMH5N
#define PARSER_HXX_RGFUMH5N

#include "ast.hxx"
#include "token.hxx"
#include "lemon.hxx"
#include <vector>

namespace miniml
{

struct Parser
{
  Parser();
  ~Parser();

  Ptr<Expr> parse(const Ptr<String>);
  Ptr<Expr> parse(const std::vector<Ptr<Token>>&);

private:
  void *parser;
};

}

#endif /* end of include guard: PARSER_HXX_RGFUMH5N */
<|endoftext|>


<commit_before>#include <string>
struct person
{
	std::string surname;
	std::string name;
	std::string year;
};
struct PersonHash
{
	std::size_t operator()(person const & s) const
	{
		std::size_t h1 = std::hash<std::string>{}(s.surname);
		std::size_t h2 = std::hash<std::string>{}(s.name);
		std::size_t h3 = std::hash<std::string>{}(s.year);
		return h1 ^ ((h2 ^ (h3 << 1)) << 1); // or use boost::hash_combine
	}
};
bool operator==(const person & left, const person & right) {
	return left.name == right.name && left.surname == right.surname && left.surname == right.surname;
}
std::ostream & operator<<(std::ostream & output, person const & _person)
{
	output << _person.surname << " ";
	output << _person.name << " ";
	output << _person.year;
	return output;
}
std::istream & operator>>(std::istream & input, person & _person)
{
	input >> _person.surname;
	input >> _person.name;
	input >> _person.year;
	return input;
}
person readPersonFromFile(std::string file_name, size_t index) {
	person result;
	std::ifstream file(file_name);
	for (size_t i = 0; i < index + 1; i++) {
		file >> result;
	}
	file.close();
	return result;
}
<commit_msg>Update person.hpp<commit_after>#include <string>
struct person
{
	std::string surname;
	std::string name;
	std::string year;
};
struct PersonHash
{
	std::size_t operator()(person const & s) const
	{
		std::size_t h1 = std::hash<std::string>{}(s.surname);
		std::size_t h2 = std::hash<std::string>{}(s.name);
		std::size_t h3 = std::hash<std::string>{}(s.year);
		return h1 ^ ((h2 ^ (h3 << 1)) << 1); // or use boost::hash_combine
	}
};
bool operator==(const person & left, const person & right) {
	return left.name == right.name && left.surname == right.surname && left.year == right.year;
}
std::ostream & operator<<(std::ostream & output, person const & _person)
{
	output << _person.surname << " ";
	output << _person.name << " ";
	output << _person.year;
	return output;
}
std::istream & operator>>(std::istream & input, person & _person)
{
	input >> _person.surname;
	input >> _person.name;
	input >> _person.year;
	return input;
}
person readPersonFromFile(std::string file_name, size_t index) {
	person result;
	std::ifstream file(file_name);
	for (size_t i = 0; i < index + 1; i++) {
		file >> result;
	}
	file.close();
	return result;
}
<|endoftext|>


<commit_before>// Copyright 2013 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/browser/chromeos/login/chrome_restart_request.h"

#include <vector>

#include "ash/ash_switches.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/prefs/json_pref_store.h"
#include "base/prefs/pref_service.h"
#include "base/process/launch.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "cc/base/switches.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/login/user_names.h"
#include "components/policy/core/common/policy_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "media/base/media_switches.h"
#include "third_party/cros_system_api/switches/chrome_switches.h"
#include "ui/app_list/app_list_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "ui/ozone/public/ozone_switches.h"
#include "ui/wm/core/wm_core_switches.h"
#include "url/gurl.h"

using content::BrowserThread;

namespace chromeos {

namespace {

// Increase logging level for Guest mode to avoid INFO messages in logs.
const char kGuestModeLoggingLevel[] = "1";

// Format of command line switch.
const char kSwitchFormatString[] = " --%s=\"%s\"";

// Derives the new command line from |base_command_line| by doing the following:
// - Forward a given switches list to new command;
// - Set start url if given;
// - Append/override switches using |new_switches|;
std::string DeriveCommandLine(const GURL& start_url,
                              const CommandLine& base_command_line,
                              const base::DictionaryValue& new_switches,
                              CommandLine* command_line) {
  DCHECK_NE(&base_command_line, command_line);

  static const char* kForwardSwitches[] = {
    ::switches::kDisableAccelerated2dCanvas,
    ::switches::kDisableAcceleratedOverflowScroll,
    ::switches::kDisableAcceleratedVideoDecode,
    ::switches::kDisableDelegatedRenderer,
    ::switches::kDisableDistanceFieldText,
    ::switches::kDisableGpuShaderDiskCache,
    ::switches::kDisableGpuWatchdog,
    ::switches::kDisableGpuCompositing,
    ::switches::kDisableGpuRasterization,
    ::switches::kDisableImplSidePainting,
    ::switches::kDisableLowResTiling,
    ::switches::kDisableMediaSource,
    ::switches::kDisablePrefixedEncryptedMedia,
    ::switches::kDisablePanelFitting,
    ::switches::kDisableSeccompFilterSandbox,
    ::switches::kDisableSetuidSandbox,
    ::switches::kDisableTouchDragDrop,
    ::switches::kDisableTouchEditing,
    ::switches::kDisableAcceleratedFixedRootBackground,
    ::switches::kDisableZeroCopy,
    ::switches::kEnableAcceleratedFixedRootBackground,
    ::switches::kEnableAcceleratedOverflowScroll,
    ::switches::kEnableBeginFrameScheduling,
    ::switches::kEnableCompositingForFixedPosition,
    ::switches::kEnableDelegatedRenderer,
    ::switches::kEnableDisplayList2dCanvas,
    ::switches::kEnableEncryptedMedia,
    ::switches::kDisableGpuSandbox,
    ::switches::kDisableDeferredFilters,
    ::switches::kEnableContainerCulling,
    ::switches::kEnableDistanceFieldText,
    ::switches::kEnableGpuRasterization,
    ::switches::kEnableImplSidePainting,
    ::switches::kEnableLogging,
    ::switches::kEnableLowResTiling,
    ::switches::kEnableOneCopy,
    ::switches::kEnablePinch,
    ::switches::kEnableTouchDragDrop,
    ::switches::kEnableTouchEditing,
    ::switches::kEnableViewport,
    ::switches::kEnableViewportMeta,
    ::switches::kEnableZeroCopy,
    ::switches::kMainFrameResizesAreOrientationChanges,
    ::switches::kForceDeviceScaleFactor,
    ::switches::kForceGpuRasterization,
    ::switches::kGpuStartupDialog,
    ::switches::kGpuSandboxAllowSysVShm,
    ::switches::kGpuSandboxFailuresFatal,
    ::switches::kGpuSandboxStartEarly,
    ::switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode,
    ::switches::kNoSandbox,
    ::switches::kNumRasterThreads,
    ::switches::kPpapiFlashArgs,
    ::switches::kPpapiFlashPath,
    ::switches::kPpapiFlashVersion,
    ::switches::kPpapiInProcess,
    ::switches::kRendererStartupDialog,
    ::switches::kEnableShareGroupAsyncTextureUpload,
    ::switches::kTabCaptureUpscaleQuality,
    ::switches::kTabCaptureDownscaleQuality,
#if defined(USE_XI2_MT)
    ::switches::kTouchCalibration,
#endif
    ::switches::kTouchDevices,
    ::switches::kTouchEvents,
    ::switches::kUIDisableThreadedCompositing,
    ::switches::kUIPrioritizeInGpuProcess,
#if defined(USE_CRAS)
    ::switches::kUseCras,
#endif
    ::switches::kUseDiscardableMemory,
    ::switches::kUseGL,
    ::switches::kUserDataDir,
    ::switches::kV,
    ::switches::kVModule,
    ::switches::kEnableWebGLDraftExtensions,
    ::switches::kEnableWebGLImageChromium,
#if defined(ENABLE_WEBRTC)
    ::switches::kDisableAudioTrackProcessing,
    ::switches::kDisableWebRtcHWDecoding,
    ::switches::kDisableWebRtcHWEncoding,
    ::switches::kEnableWebRtcHWVp8Encoding,
#endif
    ::switches::kEnableVaapiAcceleratedVideoEncode,
#if defined(USE_OZONE)
    ::switches::kOzonePlatform,
#endif
    app_list::switches::kDisableSyncAppList,
    app_list::switches::kEnableSyncAppList,
    ash::switches::kAshDefaultWallpaperLarge,
    ash::switches::kAshDefaultWallpaperSmall,
    ash::switches::kAshGuestWallpaperLarge,
    ash::switches::kAshGuestWallpaperSmall,
    ash::switches::kAshHostWindowBounds,
    ash::switches::kAshTouchHud,
    ash::switches::kAuraLegacyPowerButton,
    // Please keep these in alphabetical order. Non-UI Compositor switches
    // here should also be added to
    // content/browser/renderer_host/render_process_host_impl.cc.
    cc::switches::kCompositeToMailbox,
    cc::switches::kDisableCompositedAntialiasing,
    cc::switches::kDisableMainFrameBeforeActivation,
    cc::switches::kDisableMainFrameBeforeDraw,
    cc::switches::kDisablePinchVirtualViewport,
    cc::switches::kDisableThreadedAnimation,
    cc::switches::kEnableGpuBenchmarking,
    cc::switches::kEnablePinchVirtualViewport,
    cc::switches::kEnableMainFrameBeforeActivation,
    cc::switches::kEnableTopControlsPositionCalculation,
    cc::switches::kMaxTilesForInterestArea,
    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
    cc::switches::kShowCompositedLayerBorders,
    cc::switches::kShowFPSCounter,
    cc::switches::kShowLayerAnimationBounds,
    cc::switches::kShowNonOccludingRects,
    cc::switches::kShowOccludingRects,
    cc::switches::kShowPropertyChangedRects,
    cc::switches::kShowReplicaScreenSpaceRects,
    cc::switches::kShowScreenSpaceRects,
    cc::switches::kShowSurfaceDamageRects,
    cc::switches::kSlowDownRasterScaleFactor,
    cc::switches::kUIDisablePartialSwap,
    chromeos::switches::kConsumerDeviceManagementUrl,
    chromeos::switches::kDbusStub,
    chromeos::switches::kDisableLoginAnimations,
    chromeos::switches::kEnableConsumerManagement,
    chromeos::switches::kEnterpriseEnableForcedReEnrollment,
    chromeos::switches::kHasChromeOSDiamondKey,
    chromeos::switches::kHasChromeOSKeyboard,
    chromeos::switches::kLoginProfile,
    chromeos::switches::kNaturalScrollDefault,
    chromeos::switches::kSystemInDevMode,
    policy::switches::kDeviceManagementUrl,
    ::switches::kEnableBrowserTextSubpixelPositioning,
    ::switches::kEnableWebkitTextSubpixelPositioning,
    wm::switches::kWindowAnimationsDisabled,
  };
  command_line->CopySwitchesFrom(base_command_line,
                                 kForwardSwitches,
                                 arraysize(kForwardSwitches));

  if (start_url.is_valid())
    command_line->AppendArg(start_url.spec());

  for (base::DictionaryValue::Iterator it(new_switches);
       !it.IsAtEnd();
       it.Advance()) {
    std::string value;
    CHECK(it.value().GetAsString(&value));
    command_line->AppendSwitchASCII(it.key(), value);
  }

  std::string cmd_line_str = command_line->GetCommandLineString();
  // Special workaround for the arguments that should be quoted.
  // Copying switches won't be needed when Guest mode won't need restart
  // http://crosbug.com/6924
  if (base_command_line.HasSwitch(::switches::kRegisterPepperPlugins)) {
    cmd_line_str += base::StringPrintf(
        kSwitchFormatString,
        ::switches::kRegisterPepperPlugins,
        base_command_line.GetSwitchValueNative(
            ::switches::kRegisterPepperPlugins).c_str());
  }

  return cmd_line_str;
}

// Simulates a session manager restart by launching give command line
// and exit current process.
void ReLaunch(const std::string& command_line) {
  std::vector<std::string> argv;

  // This is not a proper way to get |argv| but it's good enough for debugging.
  base::SplitString(command_line, ' ', &argv);

  base::LaunchProcess(argv, base::LaunchOptions(), NULL);
  chrome::AttemptUserExit();
}

// Empty function that run by the local state task runner to ensure last
// commit goes through.
void EnsureLocalStateIsWritten() {}

// Wraps the work of sending chrome restart request to session manager.
// If local state is present, try to commit it first. The request is fired when
// the commit goes through or some time (3 seconds) has elapsed.
class ChromeRestartRequest
    : public base::SupportsWeakPtr<ChromeRestartRequest> {
 public:
  explicit ChromeRestartRequest(const std::string& command_line);
  ~ChromeRestartRequest();

  // Starts the request.
  void Start();

 private:
  // Fires job restart request to session manager.
  void RestartJob();

  const int pid_;
  const std::string command_line_;
  base::OneShotTimer<ChromeRestartRequest> timer_;

  DISALLOW_COPY_AND_ASSIGN(ChromeRestartRequest);
};

ChromeRestartRequest::ChromeRestartRequest(const std::string& command_line)
    : pid_(getpid()),
      command_line_(command_line) {}

ChromeRestartRequest::~ChromeRestartRequest() {}

void ChromeRestartRequest::Start() {
  VLOG(1) << "Requesting a restart with PID " << pid_
          << " and command line: " << command_line_;

  // Session Manager may kill the chrome anytime after this point.
  // Write exit_cleanly and other stuff to the disk here.
  g_browser_process->EndSession();

  PrefService* local_state = g_browser_process->local_state();
  if (!local_state) {
    RestartJob();
    return;
  }

  // XXX: normally this call must not be needed, however RestartJob
  // just kills us so settings may be lost. See http://crosbug.com/13102
  local_state->CommitPendingWrite();
  timer_.Start(
      FROM_HERE, base::TimeDelta::FromSeconds(3), this,
      &ChromeRestartRequest::RestartJob);

  // Post a task to local state task runner thus it occurs last on the task
  // queue, so it would be executed after committing pending write on that
  // thread.
  scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
      JsonPrefStore::GetTaskRunnerForFile(
          base::FilePath(chrome::kLocalStorePoolName),
          BrowserThread::GetBlockingPool());
  local_state_task_runner->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&EnsureLocalStateIsWritten),
      base::Bind(&ChromeRestartRequest::RestartJob, AsWeakPtr()));
}

void ChromeRestartRequest::RestartJob() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  DBusThreadManager::Get()->GetSessionManagerClient()->RestartJob(
      pid_, command_line_);

  delete this;
}

}  // namespace

std::string GetOffTheRecordCommandLine(
    const GURL& start_url,
    bool is_oobe_completed,
    const CommandLine& base_command_line,
    CommandLine* command_line) {
  base::DictionaryValue otr_switches;
  otr_switches.SetString(switches::kGuestSession, std::string());
  otr_switches.SetString(::switches::kIncognito, std::string());
  otr_switches.SetString(::switches::kLoggingLevel, kGuestModeLoggingLevel);
  otr_switches.SetString(switches::kLoginUser, chromeos::login::kGuestUserName);

  // Override the home page.
  otr_switches.SetString(::switches::kHomePage,
                         GURL(chrome::kChromeUINewTabURL).spec());

  // If OOBE is not finished yet, lock down the guest session to not allow
  // surfing the web. Guest mode is still useful to inspect logs and run network
  // diagnostics.
  if (!is_oobe_completed)
    otr_switches.SetString(switches::kOobeGuestSession, std::string());

  return DeriveCommandLine(start_url,
                           base_command_line,
                           otr_switches,
                           command_line);
}

void RestartChrome(const std::string& command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  BootTimesLoader::Get()->set_restart_requested();

  static bool restart_requested = false;
  if (restart_requested) {
    NOTREACHED() << "Request chrome restart for more than once.";
  }
  restart_requested = true;

  if (!base::SysInfo::IsRunningOnChromeOS()) {
    // Relaunch chrome without session manager on dev box.
    ReLaunch(command_line);
    return;
  }

  // ChromeRestartRequest deletes itself after request sent to session manager.
  (new ChromeRestartRequest(command_line))->Start();
}

}  // namespace chromeos
<commit_msg>Restore disable gpu flag after r286726<commit_after>// Copyright 2013 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/browser/chromeos/login/chrome_restart_request.h"

#include <vector>

#include "ash/ash_switches.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/prefs/json_pref_store.h"
#include "base/prefs/pref_service.h"
#include "base/process/launch.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "cc/base/switches.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/login/user_names.h"
#include "components/policy/core/common/policy_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "media/base/media_switches.h"
#include "third_party/cros_system_api/switches/chrome_switches.h"
#include "ui/app_list/app_list_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "ui/ozone/public/ozone_switches.h"
#include "ui/wm/core/wm_core_switches.h"
#include "url/gurl.h"

using content::BrowserThread;

namespace chromeos {

namespace {

// Increase logging level for Guest mode to avoid INFO messages in logs.
const char kGuestModeLoggingLevel[] = "1";

// Format of command line switch.
const char kSwitchFormatString[] = " --%s=\"%s\"";

// Derives the new command line from |base_command_line| by doing the following:
// - Forward a given switches list to new command;
// - Set start url if given;
// - Append/override switches using |new_switches|;
std::string DeriveCommandLine(const GURL& start_url,
                              const CommandLine& base_command_line,
                              const base::DictionaryValue& new_switches,
                              CommandLine* command_line) {
  DCHECK_NE(&base_command_line, command_line);

  static const char* kForwardSwitches[] = {
    ::switches::kDisableAccelerated2dCanvas,
    ::switches::kDisableAcceleratedOverflowScroll,
    ::switches::kDisableAcceleratedVideoDecode,
    ::switches::kDisableDelegatedRenderer,
    ::switches::kDisableDistanceFieldText,
    ::switches::kDisableGpu,
    ::switches::kDisableGpuShaderDiskCache,
    ::switches::kDisableGpuWatchdog,
    ::switches::kDisableGpuCompositing,
    ::switches::kDisableGpuRasterization,
    ::switches::kDisableImplSidePainting,
    ::switches::kDisableLowResTiling,
    ::switches::kDisableMediaSource,
    ::switches::kDisablePrefixedEncryptedMedia,
    ::switches::kDisablePanelFitting,
    ::switches::kDisableSeccompFilterSandbox,
    ::switches::kDisableSetuidSandbox,
    ::switches::kDisableTouchDragDrop,
    ::switches::kDisableTouchEditing,
    ::switches::kDisableAcceleratedFixedRootBackground,
    ::switches::kDisableZeroCopy,
    ::switches::kEnableAcceleratedFixedRootBackground,
    ::switches::kEnableAcceleratedOverflowScroll,
    ::switches::kEnableBeginFrameScheduling,
    ::switches::kEnableCompositingForFixedPosition,
    ::switches::kEnableDelegatedRenderer,
    ::switches::kEnableDisplayList2dCanvas,
    ::switches::kEnableEncryptedMedia,
    ::switches::kDisableGpuSandbox,
    ::switches::kDisableDeferredFilters,
    ::switches::kEnableContainerCulling,
    ::switches::kEnableDistanceFieldText,
    ::switches::kEnableGpuRasterization,
    ::switches::kEnableImplSidePainting,
    ::switches::kEnableLogging,
    ::switches::kEnableLowResTiling,
    ::switches::kEnableOneCopy,
    ::switches::kEnablePinch,
    ::switches::kEnableTouchDragDrop,
    ::switches::kEnableTouchEditing,
    ::switches::kEnableViewport,
    ::switches::kEnableViewportMeta,
    ::switches::kEnableZeroCopy,
    ::switches::kMainFrameResizesAreOrientationChanges,
    ::switches::kForceDeviceScaleFactor,
    ::switches::kForceGpuRasterization,
    ::switches::kGpuStartupDialog,
    ::switches::kGpuSandboxAllowSysVShm,
    ::switches::kGpuSandboxFailuresFatal,
    ::switches::kGpuSandboxStartEarly,
    ::switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode,
    ::switches::kNoSandbox,
    ::switches::kNumRasterThreads,
    ::switches::kPpapiFlashArgs,
    ::switches::kPpapiFlashPath,
    ::switches::kPpapiFlashVersion,
    ::switches::kPpapiInProcess,
    ::switches::kRendererStartupDialog,
    ::switches::kEnableShareGroupAsyncTextureUpload,
    ::switches::kTabCaptureUpscaleQuality,
    ::switches::kTabCaptureDownscaleQuality,
#if defined(USE_XI2_MT)
    ::switches::kTouchCalibration,
#endif
    ::switches::kTouchDevices,
    ::switches::kTouchEvents,
    ::switches::kUIDisableThreadedCompositing,
    ::switches::kUIPrioritizeInGpuProcess,
#if defined(USE_CRAS)
    ::switches::kUseCras,
#endif
    ::switches::kUseDiscardableMemory,
    ::switches::kUseGL,
    ::switches::kUserDataDir,
    ::switches::kV,
    ::switches::kVModule,
    ::switches::kEnableWebGLDraftExtensions,
    ::switches::kEnableWebGLImageChromium,
#if defined(ENABLE_WEBRTC)
    ::switches::kDisableAudioTrackProcessing,
    ::switches::kDisableWebRtcHWDecoding,
    ::switches::kDisableWebRtcHWEncoding,
    ::switches::kEnableWebRtcHWVp8Encoding,
#endif
    ::switches::kEnableVaapiAcceleratedVideoEncode,
#if defined(USE_OZONE)
    ::switches::kOzonePlatform,
#endif
    app_list::switches::kDisableSyncAppList,
    app_list::switches::kEnableSyncAppList,
    ash::switches::kAshDefaultWallpaperLarge,
    ash::switches::kAshDefaultWallpaperSmall,
    ash::switches::kAshGuestWallpaperLarge,
    ash::switches::kAshGuestWallpaperSmall,
    ash::switches::kAshHostWindowBounds,
    ash::switches::kAshTouchHud,
    ash::switches::kAuraLegacyPowerButton,
    // Please keep these in alphabetical order. Non-UI Compositor switches
    // here should also be added to
    // content/browser/renderer_host/render_process_host_impl.cc.
    cc::switches::kCompositeToMailbox,
    cc::switches::kDisableCompositedAntialiasing,
    cc::switches::kDisableMainFrameBeforeActivation,
    cc::switches::kDisableMainFrameBeforeDraw,
    cc::switches::kDisablePinchVirtualViewport,
    cc::switches::kDisableThreadedAnimation,
    cc::switches::kEnableGpuBenchmarking,
    cc::switches::kEnablePinchVirtualViewport,
    cc::switches::kEnableMainFrameBeforeActivation,
    cc::switches::kEnableTopControlsPositionCalculation,
    cc::switches::kMaxTilesForInterestArea,
    cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
    cc::switches::kShowCompositedLayerBorders,
    cc::switches::kShowFPSCounter,
    cc::switches::kShowLayerAnimationBounds,
    cc::switches::kShowNonOccludingRects,
    cc::switches::kShowOccludingRects,
    cc::switches::kShowPropertyChangedRects,
    cc::switches::kShowReplicaScreenSpaceRects,
    cc::switches::kShowScreenSpaceRects,
    cc::switches::kShowSurfaceDamageRects,
    cc::switches::kSlowDownRasterScaleFactor,
    cc::switches::kUIDisablePartialSwap,
    chromeos::switches::kConsumerDeviceManagementUrl,
    chromeos::switches::kDbusStub,
    chromeos::switches::kDisableLoginAnimations,
    chromeos::switches::kEnableConsumerManagement,
    chromeos::switches::kEnterpriseEnableForcedReEnrollment,
    chromeos::switches::kHasChromeOSDiamondKey,
    chromeos::switches::kHasChromeOSKeyboard,
    chromeos::switches::kLoginProfile,
    chromeos::switches::kNaturalScrollDefault,
    chromeos::switches::kSystemInDevMode,
    policy::switches::kDeviceManagementUrl,
    ::switches::kEnableBrowserTextSubpixelPositioning,
    ::switches::kEnableWebkitTextSubpixelPositioning,
    wm::switches::kWindowAnimationsDisabled,
  };
  command_line->CopySwitchesFrom(base_command_line,
                                 kForwardSwitches,
                                 arraysize(kForwardSwitches));

  if (start_url.is_valid())
    command_line->AppendArg(start_url.spec());

  for (base::DictionaryValue::Iterator it(new_switches);
       !it.IsAtEnd();
       it.Advance()) {
    std::string value;
    CHECK(it.value().GetAsString(&value));
    command_line->AppendSwitchASCII(it.key(), value);
  }

  std::string cmd_line_str = command_line->GetCommandLineString();
  // Special workaround for the arguments that should be quoted.
  // Copying switches won't be needed when Guest mode won't need restart
  // http://crosbug.com/6924
  if (base_command_line.HasSwitch(::switches::kRegisterPepperPlugins)) {
    cmd_line_str += base::StringPrintf(
        kSwitchFormatString,
        ::switches::kRegisterPepperPlugins,
        base_command_line.GetSwitchValueNative(
            ::switches::kRegisterPepperPlugins).c_str());
  }

  return cmd_line_str;
}

// Simulates a session manager restart by launching give command line
// and exit current process.
void ReLaunch(const std::string& command_line) {
  std::vector<std::string> argv;

  // This is not a proper way to get |argv| but it's good enough for debugging.
  base::SplitString(command_line, ' ', &argv);

  base::LaunchProcess(argv, base::LaunchOptions(), NULL);
  chrome::AttemptUserExit();
}

// Empty function that run by the local state task runner to ensure last
// commit goes through.
void EnsureLocalStateIsWritten() {}

// Wraps the work of sending chrome restart request to session manager.
// If local state is present, try to commit it first. The request is fired when
// the commit goes through or some time (3 seconds) has elapsed.
class ChromeRestartRequest
    : public base::SupportsWeakPtr<ChromeRestartRequest> {
 public:
  explicit ChromeRestartRequest(const std::string& command_line);
  ~ChromeRestartRequest();

  // Starts the request.
  void Start();

 private:
  // Fires job restart request to session manager.
  void RestartJob();

  const int pid_;
  const std::string command_line_;
  base::OneShotTimer<ChromeRestartRequest> timer_;

  DISALLOW_COPY_AND_ASSIGN(ChromeRestartRequest);
};

ChromeRestartRequest::ChromeRestartRequest(const std::string& command_line)
    : pid_(getpid()),
      command_line_(command_line) {}

ChromeRestartRequest::~ChromeRestartRequest() {}

void ChromeRestartRequest::Start() {
  VLOG(1) << "Requesting a restart with PID " << pid_
          << " and command line: " << command_line_;

  // Session Manager may kill the chrome anytime after this point.
  // Write exit_cleanly and other stuff to the disk here.
  g_browser_process->EndSession();

  PrefService* local_state = g_browser_process->local_state();
  if (!local_state) {
    RestartJob();
    return;
  }

  // XXX: normally this call must not be needed, however RestartJob
  // just kills us so settings may be lost. See http://crosbug.com/13102
  local_state->CommitPendingWrite();
  timer_.Start(
      FROM_HERE, base::TimeDelta::FromSeconds(3), this,
      &ChromeRestartRequest::RestartJob);

  // Post a task to local state task runner thus it occurs last on the task
  // queue, so it would be executed after committing pending write on that
  // thread.
  scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
      JsonPrefStore::GetTaskRunnerForFile(
          base::FilePath(chrome::kLocalStorePoolName),
          BrowserThread::GetBlockingPool());
  local_state_task_runner->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&EnsureLocalStateIsWritten),
      base::Bind(&ChromeRestartRequest::RestartJob, AsWeakPtr()));
}

void ChromeRestartRequest::RestartJob() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  DBusThreadManager::Get()->GetSessionManagerClient()->RestartJob(
      pid_, command_line_);

  delete this;
}

}  // namespace

std::string GetOffTheRecordCommandLine(
    const GURL& start_url,
    bool is_oobe_completed,
    const CommandLine& base_command_line,
    CommandLine* command_line) {
  base::DictionaryValue otr_switches;
  otr_switches.SetString(switches::kGuestSession, std::string());
  otr_switches.SetString(::switches::kIncognito, std::string());
  otr_switches.SetString(::switches::kLoggingLevel, kGuestModeLoggingLevel);
  otr_switches.SetString(switches::kLoginUser, chromeos::login::kGuestUserName);

  // Override the home page.
  otr_switches.SetString(::switches::kHomePage,
                         GURL(chrome::kChromeUINewTabURL).spec());

  // If OOBE is not finished yet, lock down the guest session to not allow
  // surfing the web. Guest mode is still useful to inspect logs and run network
  // diagnostics.
  if (!is_oobe_completed)
    otr_switches.SetString(switches::kOobeGuestSession, std::string());

  return DeriveCommandLine(start_url,
                           base_command_line,
                           otr_switches,
                           command_line);
}

void RestartChrome(const std::string& command_line) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  BootTimesLoader::Get()->set_restart_requested();

  static bool restart_requested = false;
  if (restart_requested) {
    NOTREACHED() << "Request chrome restart for more than once.";
  }
  restart_requested = true;

  if (!base::SysInfo::IsRunningOnChromeOS()) {
    // Relaunch chrome without session manager on dev box.
    ReLaunch(command_line);
    return;
  }

  // ChromeRestartRequest deletes itself after request sent to session manager.
  (new ChromeRestartRequest(command_line))->Start();
}

}  // namespace chromeos
<|endoftext|>