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

// INCLUDE ---------------------------------------------------------------

#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif
#ifndef _SFXLSTNER_HXX //autogen
#include <svtools/lstner.hxx>
#endif
#ifndef _TRANSFER_HXX
#include <svtools/transfer.hxx>
#endif
#ifndef _SFX_CHILDWIN_HXX //autogen
#include <sfx2/childwin.hxx>
#endif
#ifndef _SFXCTRLITEM_HXX //autogen
#include <sfx2/ctrlitem.hxx>
#endif

#ifndef _CONTTREE_HXX
#include <conttree.hxx>
#endif
#ifndef _POPBOX_HXX
#include <popbox.hxx>
#endif

class SwWrtShell;
class SwNavigationPI;
class SwNavigationChild;
class SfxBindings;
class NumEditAction;
class SwView;
class SwNavigationConfig;
class SfxObjectShellLock;
class SfxChildWindowContext;

//-----------------------------------------------------------------------
class SwNavigationPI;
class SwNavHelpToolBox : public SwHelpToolBox
{
    virtual void    MouseButtonDown(const MouseEvent &rEvt);
    virtual void    RequestHelp( const HelpEvent& rHEvt );

    public:
        SwNavHelpToolBox(SwNavigationPI* pParent, const ResId &rResId);
};

// CLASS -----------------------------------------------------------------
class SwNavigationPI : public Window,
                        public SfxControllerItem, public SfxListener
{
    friend class SwNavigationChild;
    friend class SwContentTree;
    friend class SwGlobalTree;

    // --------- members -----------------------------
    SwNavHelpToolBox    aContentToolBox;
    SwHelpToolBox       aGlobalToolBox;
    ImageList           aContentImageList;
    SwContentTree       aContentTree;
    SwGlobalTree        aGlobalTree;
    ListBox             aDocListBox;
    Timer               aPageChgTimer;
    String              sContentFileName;
    String              aContextArr[3];
    String              aStatusArr[4];
    Point               aBoxBottomLeft; // Pos., wenn Box unten ist

    SfxObjectShellLock  *pxObjectShell;
    SwView              *pContentView;
    SwWrtShell          *pContentWrtShell;
    SwView              *pActContView;
    SwView              *pCreateView;

    SfxChildWindowContext* pContextWin;

    SwNavigationConfig  *pConfig;
    SfxBindings         &rBindings;

    long    nDocLBIniHeight;
    long    nWishWidth;
    USHORT  nActMark;
    USHORT  nAutoMarkIdx;
    USHORT  nRegionMode; // 0 - URL, 1 - Bereich mit Link 2 - B. ohne Link
    short   nZoomIn;
    short   nZoomOutInit;
    short   nZoomOut;

    BOOL    bSmallMode : 1;
    BOOL    bIsZoomedIn : 1;
    BOOL    bPageCtrlsVisible : 1;
    BOOL    bGlobalMode : 1;

    // --------- methods -----------------------------
    BOOL _IsZoomedIn() const {return bIsZoomedIn;}
    void _ZoomOut();
    void _ZoomIn();

    void FillBox();
    void MakeMark();

    DECL_LINK( DocListBoxSelectHdl, ListBox * );
    DECL_LINK( ToolBoxSelectHdl, ToolBox * );
    DECL_LINK( ToolBoxClickHdl, ToolBox * );
    DECL_LINK( EditAction, NumEditAction * );
    DECL_LINK( EditGetFocus, NumEditAction * );
    DECL_LINK( DoneLink, SfxPoolItem * );
    DECL_LINK( MenuSelectHdl, Menu * );
    DECL_LINK( ChangePageHdl, Timer* );
    DECL_LINK( PageEditModifyHdl, Edit* );
    void UsePage(SwWrtShell *);

    void MakeVisible();

    virtual SfxChildAlignment
                    CheckAlignment(SfxChildAlignment,SfxChildAlignment);

protected:

    virtual         BOOL Close();
    virtual         void Resize();

    // zum App-Ende rechtzeitig ObjectShellLock loslassen
    virtual void    Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

    NumEditAction&  GetPageEdit();
    BOOL            ToggleTree();
    void            SetGlobalMode(BOOL bSet) {bGlobalMode = bSet;}

public:
    SwNavigationPI(SfxBindings*, SfxChildWindowContext*, Window*);
    ~SwNavigationPI();

    void            GotoPage(); // Seite anspringen; bindbare Funktion

    void            Update() { FillBox(); }
    void            UpdateListBox();
    void            MoveOutline(USHORT nSource, USHORT nTarget, BOOL bWithCilds);
    virtual void    StateChanged( USHORT nSID, SfxItemState eState,
                                            const SfxPoolItem* pState );

    static String   CreateDropFileName( TransferableDataHelper& rData );
    static void     CleanEntry( String& rEntry );

    USHORT          GetRegionDropMode() const {return nRegionMode;}
    void            SetRegionDropMode(USHORT nNewMode);
    BOOL            IsInDrag() const;

    sal_Int8        AcceptDrop( const AcceptDropEvent& rEvt );
    sal_Int8        ExecuteDrop( const ExecuteDropEvent& rEvt );

    BOOL            IsGlobalDoc() const;
    BOOL            IsGlobalMode() const {return    bGlobalMode;}

    SwView*         GetCreateView() const;
};

class SwNavigationChild : public SfxChildWindowContext
{
public:
    SwNavigationChild( Window* ,
                        USHORT nId,
                        SfxBindings*,
                        SfxChildWinInfo*  );

    SFX_DECL_CHILDWINDOW_CONTEXT( SwNavigationChild )
};

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

// INCLUDE ---------------------------------------------------------------

#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif
#ifndef _SFXLSTNER_HXX //autogen
#include <svtools/lstner.hxx>
#endif
#ifndef _TRANSFER_HXX
#include <svtools/transfer.hxx>
#endif
#ifndef _SFX_CHILDWIN_HXX //autogen
#include <sfx2/childwin.hxx>
#endif
#ifndef _SFXCTRLITEM_HXX //autogen
#include <sfx2/ctrlitem.hxx>
#endif

#ifndef _CONTTREE_HXX
#include <conttree.hxx>
#endif
#ifndef _POPBOX_HXX
#include <popbox.hxx>
#endif

class SwWrtShell;
class SwNavigationPI;
class SwNavigationChild;
class SfxBindings;
class NumEditAction;
class SwView;
class SwNavigationConfig;
class SfxObjectShellLock;
class SfxChildWindowContext;

//-----------------------------------------------------------------------
class SwNavigationPI;
class SwNavHelpToolBox : public SwHelpToolBox
{
    virtual void    MouseButtonDown(const MouseEvent &rEvt);
    virtual void    RequestHelp( const HelpEvent& rHEvt );
    public:
        SwNavHelpToolBox(SwNavigationPI* pParent, const ResId &rResId);
};

// CLASS -----------------------------------------------------------------
class SwNavigationPI : public Window,
                        public SfxControllerItem, public SfxListener
{
    friend class SwNavigationChild;
    friend class SwContentTree;
    friend class SwGlobalTree;

    // --------- members -----------------------------
    SwNavHelpToolBox    aContentToolBox;
    SwHelpToolBox       aGlobalToolBox;
    ImageList           aContentImageList;
    SwContentTree       aContentTree;
    SwGlobalTree        aGlobalTree;
    ListBox             aDocListBox;
    Timer               aPageChgTimer;
    String              sContentFileName;
    String              aContextArr[3];
    String              aStatusArr[4];
    Point               aBoxBottomLeft; // Pos., wenn Box unten ist

    SfxObjectShellLock  *pxObjectShell;
    SwView              *pContentView;
    SwWrtShell          *pContentWrtShell;
    SwView              *pActContView;
    SwView              *pCreateView;

    SfxChildWindowContext* pContextWin;

    SwNavigationConfig  *pConfig;
    SfxBindings         &rBindings;

    long    nDocLBIniHeight;
    long    nWishWidth;
    USHORT  nActMark;
    USHORT  nAutoMarkIdx;
    USHORT  nRegionMode; // 0 - URL, 1 - Bereich mit Link 2 - B. ohne Link
    short   nZoomIn;
    short   nZoomOutInit;
    short   nZoomOut;

    BOOL    bSmallMode : 1;
    BOOL    bIsZoomedIn : 1;
    BOOL    bPageCtrlsVisible : 1;
    BOOL    bGlobalMode : 1;

    // --------- methods -----------------------------
    BOOL _IsZoomedIn() const {return bIsZoomedIn;}
    void _ZoomOut();
    void _ZoomIn();

    void FillBox();
    void MakeMark();

    DECL_LINK( DocListBoxSelectHdl, ListBox * );
    DECL_LINK( ToolBoxSelectHdl, ToolBox * );
    DECL_LINK( ToolBoxClickHdl, ToolBox * );
    DECL_LINK( EditAction, NumEditAction * );
    DECL_LINK( EditGetFocus, NumEditAction * );
    DECL_LINK( DoneLink, SfxPoolItem * );
    DECL_LINK( MenuSelectHdl, Menu * );
    DECL_LINK( ChangePageHdl, Timer* );
    DECL_LINK( PageEditModifyHdl, Edit* );
    void UsePage(SwWrtShell *);

    void MakeVisible();

    virtual SfxChildAlignment
                    CheckAlignment(SfxChildAlignment,SfxChildAlignment);

protected:

    virtual         BOOL Close();
    virtual         void Resize();

    // zum App-Ende rechtzeitig ObjectShellLock loslassen
    virtual void    Notify( SfxBroadcaster& rBC, const SfxHint& rHint );

    NumEditAction&  GetPageEdit();
    BOOL            ToggleTree();
    void            SetGlobalMode(BOOL bSet) {bGlobalMode = bSet;}

public:
    SwNavigationPI(SfxBindings*, SfxChildWindowContext*, Window*);
    ~SwNavigationPI();

    void            GotoPage(); // Seite anspringen; bindbare Funktion

    void            Update() { FillBox(); }
    void            UpdateListBox();
    void            MoveOutline(USHORT nSource, USHORT nTarget, BOOL bWithCilds);
    virtual void    StateChanged( USHORT nSID, SfxItemState eState,
                                            const SfxPoolItem* pState );

    static String   CreateDropFileName( TransferableDataHelper& rData );
    static void     CleanEntry( String& rEntry );

    USHORT          GetRegionDropMode() const {return nRegionMode;}
    void            SetRegionDropMode(USHORT nNewMode);
    BOOL            IsInDrag() const;

    sal_Int8        AcceptDrop( const AcceptDropEvent& rEvt );
    sal_Int8        ExecuteDrop( const ExecuteDropEvent& rEvt );

    BOOL            IsGlobalDoc() const;
    BOOL            IsGlobalMode() const {return    bGlobalMode;}

    SwView*         GetCreateView() const;
    void            CreateNavigationTool(const Rectangle& rRect, BOOL bSetFocus);
};

class SwNavigationChild : public SfxChildWindowContext
{
public:
    SwNavigationChild( Window* ,
                        USHORT nId,
                        SfxBindings*,
                        SfxChildWinInfo*  );

    SFX_DECL_CHILDWINDOW_CONTEXT( SwNavigationChild )
};

#endif
<|endoftext|>


<commit_before>#include "SFMLSystem.hpp"

#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Window/Event.hpp>

#include "kengine.hpp"

#include "imgui-sfml/imgui-SFML.h"

#include "data/AdjustableComponent.hpp"
#include "data/ImGuiScaleComponent.hpp"

#include "functions/Execute.hpp"
#include "functions/OnEntityRemoved.hpp"
#include "functions/OnTerminate.hpp"

#include "helpers/logHelper.hpp"

#include "SFMLWindowComponent.hpp"
#include "SFMLTextureComponent.hpp"
#include "data/GraphicsComponent.hpp"

#include "data/InputBufferComponent.hpp"
#include "data/ModelComponent.hpp"
#include "data/TransformComponent.hpp"
#include "data/WindowComponent.hpp"
#include "helpers/instanceHelper.hpp"
#include "helpers/resourceHelper.hpp"

namespace kengine {
	struct sfml {
		static void init(Entity & e) noexcept {
			kengine_log(Log, "Init", "SFMLSystem");

			e += functions::Execute{ execute };
			e += functions::OnEntityCreated{ onEntityCreated };
			e += functions::OnEntityRemoved{ onEntityRemoved };
			e += functions::OnTerminate{ terminate };

			auto & scale = e.attach<ImGuiScaleComponent>();

			e += AdjustableComponent{
				"ImGui", {
					{ "scale", &scale.scale }
				}
			};
		}

		static void execute(float deltaTime) noexcept {
			kengine_log(Verbose, "Execute", "SFMLSystem");

			const auto sfDeltaTime = g_deltaClock.restart();

			if (g_inputBuffer == nullptr) {
				for (const auto & [e, inputBuffer] : entities.with<InputBufferComponent>()) {
					g_inputBuffer = &inputBuffer;
					break;
				}
			}

			for (auto [window, sfWindow] : entities.with<SFMLWindowComponent>()) {
				updateWindowState(window, sfWindow);
				processEvents(window.id, sfWindow.window);
				render(sfWindow, sfDeltaTime);
			}
		}

		static bool updateWindowState(Entity & windowEntity, SFMLWindowComponent & sfWindowComp) noexcept {
			const auto * windowComp = windowEntity.tryGet<WindowComponent>();
			if (windowComp == nullptr) {
				kengine_logf(Verbose, "Execute/SFMLSystem", "%zu: destroying window as WindowComponent was removed", windowEntity.id);
				windowEntity.detach<SFMLWindowComponent>();
				return false;
			}

			if (!sfWindowComp.window.isOpen()) {
				kengine_logf(Verbose, "Execute/SFMLSystem", "%zu: window was closed", windowEntity.id);
				if (windowComp->shutdownOnClose)
					stopRunning();
				else
					entities -= windowEntity;
				return false;
			}

			sfWindowComp.window.setSize({ windowComp->size.x, windowComp->size.y });
			return true;
		}

		static void processEvents(EntityID window, sf::RenderWindow & sfWindow) noexcept {
			sf::Event event;
			while (sfWindow.pollEvent(event)) {
				ImGui::SFML::ProcessEvent(sfWindow, event);

				if (event.type == sf::Event::Closed)
					sfWindow.close();

				processInput(window, event);
			}
		}

		static void processInput(EntityID window, const sf::Event & e) noexcept {
			if (g_inputBuffer == nullptr)
				return;

			switch (e.type) {
				case sf::Event::KeyPressed:
				case sf::Event::KeyReleased: {
					if (ImGui::GetIO().WantCaptureKeyboard)
						break;

					g_inputBuffer->keys.push_back(InputBufferComponent::KeyEvent{
						.window = window,
						.key = e.key.code,
						.pressed = e.type == sf::Event::KeyPressed
					});
					break;
				}
				case sf::Event::MouseMoved: {
					if (ImGui::GetIO().WantCaptureMouse)
						break;

					static putils::Point2f previousPos{ 0.f, 0.f };

					const putils::Point2f pos{ (float)e.mouseMove.x, (float)e.mouseMove.y };
					const putils::Point2f rel = pos - previousPos;
					previousPos = pos;

					g_inputBuffer->moves.push_back(InputBufferComponent::MouseMoveEvent{
						.window = window,
						.pos = pos,
						.rel = rel
					});
					break;
				}
				case sf::Event::MouseButtonPressed:
				case sf::Event::MouseButtonReleased: {
					if (ImGui::GetIO().WantCaptureMouse)
						break;

					g_inputBuffer->clicks.push_back(InputBufferComponent::ClickEvent{
						.window = window,
						.pos = { (float)e.mouseButton.x, (float)e.mouseButton.y },
						.button = e.mouseButton.button,
						.pressed = e.type == sf::Event::MouseButtonPressed
					});
					break;
				}
				case sf::Event::MouseWheelScrolled: {
					if (ImGui::GetIO().WantCaptureMouse)
						return;

					g_inputBuffer->scrolls.push_back(InputBufferComponent::MouseScrollEvent{
						.window = window,
						.xoffset = 0,
						.yoffset = e.mouseWheelScroll.delta,
						.pos = { (float)e.mouseWheelScroll.x, (float)e.mouseWheelScroll.y }
					});
					break;
				}
				default:
					// don't assert, this could be a joystick event or something
					break;
			}
		}

		static void render(SFMLWindowComponent & window, sf::Time deltaTime) {
			window.window.clear();
			ImGui::SFML::Render(window.window);

			struct ZOrderedSprite {
				sf::Sprite sprite;
				float height;
			};
			std::vector<ZOrderedSprite> sprites;

			for (const auto & [e, transform, graphics] : entities.with<TransformComponent, GraphicsComponent>()) {
				const auto * texture = instanceHelper::tryGetModel<SFMLTextureComponent>(e);
				if (texture == nullptr)
					continue;

				sf::Sprite sprite(texture->texture);
				sprite.setColor(sf::Color(toColor(graphics.color).rgba));
				sprite.setPosition(transform.boundingBox.position.x, transform.boundingBox.position.z);
				sprite.setScale(transform.boundingBox.size.x, transform.boundingBox.size.y);
				sprite.setRotation(transform.yaw);
				sprites.push_back({ .sprite = std::move(sprite), .height = transform.boundingBox.position.y });
			}

			std::sort(sprites.begin(), sprites.end(), [](const auto & lhs, const auto & rhs) { return lhs.height > rhs.height; });
			for (const auto & sprite : sprites)
				window.window.draw(sprite.sprite);

			window.window.display();
			ImGui::SFML::Update(window.window, deltaTime);
		}

		static void onEntityCreated(Entity & e) noexcept {
			if (const auto * window = e.tryGet<WindowComponent>())
				createWindow(e, *window);

			if (const auto * model = e.tryGet<ModelComponent>())
				createTexture(e, *model);
		}

		static void createWindow(Entity & e, const WindowComponent & windowComp) noexcept {
			kengine_logf(Log, "SFML", "Creating window '%s'", windowComp.name.c_str());

			auto & sfWindow = e.attach<SFMLWindowComponent>();
			sfWindow.window.create(
				sf::VideoMode{ windowComp.size.x, windowComp.size.y },
				windowComp.name.c_str(),
				windowComp.fullscreen ? sf::Style::Fullscreen : sf::Style::Default);

			ImGui::SFML::Init(sfWindow.window);

			e += ImGuiContextComponent{ ImGui::GetCurrentContext() };
#if 0
			auto & io = ImGui::GetIO();
			io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
			io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
			io.ConfigViewportsNoTaskBarIcon = true;
#endif
			ImGui::SFML::Update(sfWindow.window, g_deltaClock.restart());
		}

		static void createTexture(Entity & e, const ModelComponent & model) noexcept {
			sf::Texture texture;
			if (texture.loadFromFile(model.file.c_str())) {
				kengine_logf(Log, "SFML", "Loaded texture for '%s'", model.file.c_str());
				e += SFMLTextureComponent{ std::move(texture) };
			}
		}

		static void onEntityRemoved(Entity & e) noexcept {
			if (const auto * sfWindow = e.tryGet<SFMLWindowComponent>()) {
				kengine_log(Log, "SFML", "Shutting down ImGui for window");
				ImGui::SFML::Shutdown(sfWindow->window);
			}
		}

		static void terminate() noexcept {
			kengine_log(Log, "Terminate/SFML", "Shutting down ImGui");
			ImGui::SFML::Shutdown();
		}

		static inline sf::Clock g_deltaClock;
		static inline InputBufferComponent * g_inputBuffer = nullptr;
	};
}

namespace kengine {
	EntityCreator * SFMLSystem() noexcept {
		return [](Entity & e) noexcept {
			sfml::init(e);
		};
	}
}
<commit_msg>[sfml] add display<commit_after>#include "SFMLSystem.hpp"

#include "kengine.hpp"

#include <imgui.h>
#include <SFML/Graphics/RenderTexture.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Window/Event.hpp>

#include "imgui-sfml/imgui-SFML.h"
#include "SFMLWindowComponent.hpp"
#include "SFMLTextureComponent.hpp"

#include "data/AdjustableComponent.hpp"
#include "data/ImGuiScaleComponent.hpp"

#include "functions/Execute.hpp"
#include "functions/OnEntityRemoved.hpp"
#include "functions/OnTerminate.hpp"

#include "helpers/logHelper.hpp"

#include "data/CameraComponent.hpp"
#include "data/GraphicsComponent.hpp"
#include "data/ImGuiContextComponent.hpp"
#include "data/InputBufferComponent.hpp"
#include "data/ModelComponent.hpp"
#include "data/TransformComponent.hpp"
#include "data/ViewportComponent.hpp"
#include "data/WindowComponent.hpp"

#include "helpers/cameraHelper.hpp"
#include "helpers/instanceHelper.hpp"

#include "vector.hpp"

#ifndef KENGINE_MAX_VIEWPORTS
# define KENGINE_MAX_VIEWPORTS 8
#endif

namespace kengine {
	struct sfml {
		static void init(Entity & e) noexcept {
			kengine_log(Log, "Init", "SFMLSystem");

			e += functions::Execute{ execute };
			e += functions::OnEntityCreated{ onEntityCreated };
			e += functions::OnEntityRemoved{ onEntityRemoved };
			e += functions::OnTerminate{ terminate };

			auto & scale = e.attach<ImGuiScaleComponent>();

			e += AdjustableComponent{
				"ImGui", {
					{ "scale", &scale.scale }
				}
			};
		}

		static void execute(float deltaTime) noexcept {
			kengine_log(Verbose, "Execute", "SFMLSystem");

			const auto sfDeltaTime = g_deltaClock.restart();

			if (g_inputBuffer == nullptr) {
				for (const auto & [e, inputBuffer] : entities.with<InputBufferComponent>()) {
					g_inputBuffer = &inputBuffer;
					break;
				}
			}

			for (auto [window, sfWindow] : entities.with<SFMLWindowComponent>()) {
				kengine_logf(Verbose, "Execute/SFMLSystem", "Processing window %zu", window.id);
				if (!updateWindowState(window, sfWindow))
					continue;
				// We process events after rendering, even though it's not the expected order, because
				// of how the SFML-ImGui binding handles input :(
				render(window, sfWindow);
				processEvents(window.id, sfWindow.window, sfDeltaTime);
			}
		}

		static bool updateWindowState(Entity & windowEntity, SFMLWindowComponent & sfWindowComp) noexcept {
			const auto * windowComp = windowEntity.tryGet<WindowComponent>();
			if (windowComp == nullptr) {
				kengine_logf(Verbose, "Execute/SFMLSystem", "%zu: destroying window as WindowComponent was removed", windowEntity.id);
				windowEntity.detach<SFMLWindowComponent>();
				return false;
			}

			if (!sfWindowComp.window.isOpen()) {
				kengine_logf(Verbose, "Execute/SFMLSystem", "%zu: window was closed", windowEntity.id);
				if (windowComp->shutdownOnClose)
					stopRunning();
				else
					entities -= windowEntity;
				return false;
			}

			sfWindowComp.window.setSize({ windowComp->size.x, windowComp->size.y });
			return true;
		}

		static void processEvents(EntityID window, sf::RenderWindow & sfWindow, sf::Time deltaTime) noexcept {
			sf::Event event;
			while (sfWindow.pollEvent(event)) {
				ImGui::SFML::ProcessEvent(sfWindow, event);

				if (event.type == sf::Event::Closed)
					sfWindow.close();

				processInput(window, event);
			}
			ImGui::SFML::Update(sfWindow, deltaTime);
		}

		static void processInput(EntityID window, const sf::Event & e) noexcept {
			if (g_inputBuffer == nullptr)
				return;

			switch (e.type) {
				case sf::Event::KeyPressed:
				case sf::Event::KeyReleased: {
					if (ImGui::GetIO().WantCaptureKeyboard)
						break;

					g_inputBuffer->keys.push_back(InputBufferComponent::KeyEvent{
						.window = window,
						.key = e.key.code,
						.pressed = e.type == sf::Event::KeyPressed
					});
					break;
				}
				case sf::Event::MouseMoved: {
					if (ImGui::GetIO().WantCaptureMouse)
						break;

					static putils::Point2f previousPos{ 0.f, 0.f };

					const putils::Point2f pos{ (float)e.mouseMove.x, (float)e.mouseMove.y };
					const putils::Point2f rel = pos - previousPos;
					previousPos = pos;

					g_inputBuffer->moves.push_back(InputBufferComponent::MouseMoveEvent{
						.window = window,
						.pos = pos,
						.rel = rel
					});
					break;
				}
				case sf::Event::MouseButtonPressed:
				case sf::Event::MouseButtonReleased: {
					if (ImGui::GetIO().WantCaptureMouse)
						break;

					g_inputBuffer->clicks.push_back(InputBufferComponent::ClickEvent{
						.window = window,
						.pos = { (float)e.mouseButton.x, (float)e.mouseButton.y },
						.button = e.mouseButton.button,
						.pressed = e.type == sf::Event::MouseButtonPressed
					});
					break;
				}
				case sf::Event::MouseWheelScrolled: {
					if (ImGui::GetIO().WantCaptureMouse)
						return;

					g_inputBuffer->scrolls.push_back(InputBufferComponent::MouseScrollEvent{
						.window = window,
						.xoffset = 0,
						.yoffset = e.mouseWheelScroll.delta,
						.pos = { (float)e.mouseWheelScroll.x, (float)e.mouseWheelScroll.y }
					});
					break;
				}
				default:
					// don't assert, this could be a joystick event or something
					break;
			}
		}

		static void render(const Entity & windowEntity, SFMLWindowComponent & sfWindow) noexcept {
			sfWindow.window.clear();

			struct ToBlit {
				const sf::RenderTexture * renderTexture;
				const ViewportComponent * viewport;
			};
			putils::vector<ToBlit, KENGINE_MAX_VIEWPORTS> toBlit;

			for (auto [e, cam, viewport] : entities.with<CameraComponent, ViewportComponent>()) {
				if (viewport.window == INVALID_ID) {
					kengine_logf(Log, "OpenGLSystem", "Setting target window for ViewportComponent in %zu", e.id);
					viewport.window = windowEntity.id;
				}
				else if (viewport.window != windowEntity.id)
					continue;

				sf::RenderTexture * renderTexture = (sf::RenderTexture *)viewport.renderTexture;
				if (viewport.renderTexture == ViewportComponent::INVALID_RENDER_TEXTURE) {
					renderTexture = new sf::RenderTexture;
					renderTexture->create(viewport.resolution.x, viewport.resolution.y);
					viewport.renderTexture = renderTexture;
				}

				renderTexture->setView(sf::View{
					{ cam.frustum.position.x, cam.frustum.position.y },
					{ cam.frustum.size.x, cam.frustum.size.y }
				});
				renderToTexture(*renderTexture);
				toBlit.push_back(ToBlit{ renderTexture, &viewport });
			}

			std::sort(toBlit.begin(), toBlit.end(), [](const ToBlit & lhs, const ToBlit & rhs) noexcept {
				return lhs.viewport->zOrder < rhs.viewport->zOrder;
			});

			for (const auto & blit : toBlit) {
				auto renderTextureSprite = createRenderTextureSprite(*blit.renderTexture, sfWindow.window, *blit.viewport);
				sfWindow.window.draw(std::move(renderTextureSprite));
			}

			ImGui::SFML::Render(sfWindow.window);
			sfWindow.window.display();
		}

		static void renderToTexture(sf::RenderTexture & renderTexture) noexcept {
			renderTexture.clear();

			struct ZOrderedSprite {
				sf::Sprite sprite;
				float height;
			};
			std::vector<ZOrderedSprite> sprites;

			for (const auto & [e, transform, graphics] : entities.with<TransformComponent, GraphicsComponent>()) {
				auto sprite = createEntitySprite(e, transform, graphics);
				if (sprite != std::nullopt)
					sprites.push_back({ .sprite = std::move(*sprite), .height = transform.boundingBox.position.y });
			}

			std::sort(sprites.begin(), sprites.end(), [](const auto & lhs, const auto & rhs) noexcept { return lhs.height > rhs.height; });
			for (const auto & sprite : sprites)
				renderTexture.draw(sprite.sprite);

			renderTexture.display();
		}

		static std::optional<sf::Sprite> createEntitySprite(const Entity & e, const TransformComponent & transform, const GraphicsComponent & graphics) noexcept {
			const auto * texture = instanceHelper::tryGetModel<SFMLTextureComponent>(e);
			if (texture == nullptr)
				return std::nullopt;

			sf::Sprite sprite(texture->texture);
			sprite.setColor(sf::Color(toColor(graphics.color).rgba));
			sprite.setPosition(transform.boundingBox.position.x - transform.boundingBox.size.x / 2.f, transform.boundingBox.position.y - transform.boundingBox.size.y / 2.f);

			const auto textureSize = texture->texture.getSize();
			sprite.setScale(transform.boundingBox.size.x / textureSize.x, transform.boundingBox.size.y / textureSize.y);
			sprite.setRotation(transform.yaw);
			return sprite;
		}

		static sf::Sprite createRenderTextureSprite(const sf::RenderTexture & renderTexture, const sf::RenderWindow & window, const ViewportComponent & viewport) noexcept {
			sf::Sprite renderTextureSprite(renderTexture.getTexture());

			const auto screenSize = window.getSize();
			const auto box = cameraHelper::convertToScreenPercentage({ viewport.boundingBox.position, viewport.boundingBox.size }, { (float)screenSize.x, (float)screenSize.y }, viewport);
			renderTextureSprite.setPosition(screenSize.x * box.position.x, screenSize.y * box.position.y);

			const auto textureSize = renderTexture.getTexture().getSize();
			renderTextureSprite.setScale(screenSize.x / textureSize.x * box.size.x, screenSize.y / textureSize.y * box.size.y);

			return renderTextureSprite;
		}

		static void onEntityCreated(Entity & e) noexcept {
			if (const auto * window = e.tryGet<WindowComponent>())
				createWindow(e, *window);

			if (const auto * model = e.tryGet<ModelComponent>())
				createTexture(e, *model);
		}

		static void createWindow(Entity & e, const WindowComponent & windowComp) noexcept {
			kengine_logf(Log, "SFML", "Creating window '%s'", windowComp.name.c_str());

			auto & sfWindow = e.attach<SFMLWindowComponent>();
			sfWindow.window.create(
				sf::VideoMode{ windowComp.size.x, windowComp.size.y },
				windowComp.name.c_str(),
				windowComp.fullscreen ? sf::Style::Fullscreen : sf::Style::Default);

			ImGui::SFML::Init(sfWindow.window);

			e += ImGuiContextComponent{ ImGui::GetCurrentContext() };
#if 0
			auto & io = ImGui::GetIO();
			io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
			io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
			io.ConfigViewportsNoTaskBarIcon = true;
#endif
			ImGui::SFML::Update(sfWindow.window, g_deltaClock.restart());
		}

		static void createTexture(Entity & e, const ModelComponent & model) noexcept {
			sf::Texture texture;
			if (texture.loadFromFile(model.file.c_str())) {
				kengine_logf(Log, "SFML", "Loaded texture for '%s'", model.file.c_str());
				e += SFMLTextureComponent{ std::move(texture) };
			}
		}

		static void onEntityRemoved(Entity & e) noexcept {
			if (const auto * sfWindow = e.tryGet<SFMLWindowComponent>()) {
				kengine_log(Log, "SFML", "Shutting down ImGui for window");
				ImGui::SFML::Shutdown(sfWindow->window);
			}
		}

		static void terminate() noexcept {
			kengine_log(Log, "Terminate/SFML", "Shutting down ImGui");
			ImGui::SFML::Shutdown();
		}

		static inline sf::Clock g_deltaClock;
		static inline InputBufferComponent * g_inputBuffer = nullptr;
	};
}

namespace kengine {
	EntityCreator * SFMLSystem() noexcept {
		return [](Entity & e) noexcept {
			sfml::init(e);
		};
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 the V8 project authors. 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 <stdlib.h>

#include "v8.h"

#include "factory.h"
#include "macro-assembler.h"
#include "cctest.h"
#include "code-stubs.h"
#include "objects.h"

#ifdef USE_SIMULATOR
#include "simulator.h"
#endif

using namespace v8::internal;

typedef uint32_t (*HASH_FUNCTION)();

static v8::Persistent<v8::Context> env;

#define __ assm->

void generate(MacroAssembler* assm, i::Vector<const char> string) {
#ifdef V8_TARGET_ARCH_IA32
  __ mov(eax, Immediate(0));
  if (string.length() > 0) {
    __ mov(ebx, Immediate(string.at(0)));
    StringHelper::GenerateHashInit(assm, eax, ebx, ecx);
  }
  for (int i = 1; i < string.length(); i++) {
    __ mov(ebx, Immediate(string.at(i)));
    StringHelper::GenerateHashAddCharacter(assm, eax, ebx, ecx);
  }
  StringHelper::GenerateHashGetHash(assm, eax, ecx);
  __ Ret();
#elif V8_TARGET_ARCH_X64
  __ movq(rax, Immediate(0));
  if (string.length() > 0) {
    __ movq(rbx, Immediate(string.at(0)));
    StringHelper::GenerateHashInit(assm, rax, rbx, rcx);
  }
  for (int i = 1; i < string.length(); i++) {
    __ movq(rbx, Immediate(string.at(i)));
    StringHelper::GenerateHashAddCharacter(assm, rax, rbx, rcx);
  }
  StringHelper::GenerateHashGetHash(assm, rax, rcx);
  __ Ret();
#elif V8_TARGET_ARCH_ARM
  __ mov(r0, Operand(0));
  if (string.length() > 0) {
    __ mov(r1, Operand(string.at(0)));
    StringHelper::GenerateHashInit(assm, r0, r1);
  }
  for (int i = 1; i < string.length(); i++) {
    __ mov(r1, Operand(string.at(i)));
    StringHelper::GenerateHashAddCharacter(assm, r0, r1);
  }
  StringHelper::GenerateHashGetHash(assm, r0);
  __ mov(pc, Operand(lr));
#elif V8_TARGET_ARCH_MIPS
  __ li(v0, Operand(0));
  if (string.length() > 0) {
    __ li(v1, Operand(string.at(0)));
    StringHelper::GenerateHashInit(assm, v0, v1);
  }
  for (int i = 1; i < string.length(); i++) {
    __ li(v1, Operand(string.at(i)));
    StringHelper::GenerateHashAddCharacter(assm, v0, v1);
  }
  StringHelper::GenerateHashGetHash(assm, v0);
  __ jr(ra);
#endif
}

void check(i::Vector<const char> string) {
  v8::HandleScope scope;
  v8::internal::byte buffer[2048];
  MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer);

  generate(&assm, string);

  CodeDesc desc;
  assm.GetCode(&desc);
  Code* code = Code::cast(HEAP->CreateCode(
      desc,
      Code::ComputeFlags(Code::STUB),
      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
  CHECK(code->IsCode());

  HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(Code::cast(code)->entry());
  Handle<String> v8_string = FACTORY->NewStringFromAscii(string);
  v8_string->set_hash_field(String::kEmptyHashField);
#ifdef USE_SIMULATOR
  uint32_t codegen_hash =
      reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
#else
  uint32_t codegen_hash = hash();
#endif
  uint32_t runtime_hash = v8_string->Hash();
  CHECK(runtime_hash == codegen_hash);
}

void check_twochars(char a, char b) {
  char ab[2] = {a, b};
  check(i::Vector<const char>(ab, 2));
}

TEST(StringHash) {
  if (env.IsEmpty()) env = v8::Context::New();
  for (int a = 0; a < String::kMaxAsciiCharCode; a++) {
    // Numbers are hashed differently.
    if (a >= '0' && a <= '9') continue;
    for (int b = 0; b < String::kMaxAsciiCharCode; b++) {
      if (b >= '0' && b <= '9') continue;
      check_twochars(static_cast<char>(a), static_cast<char>(b));
    }
  }
  check(i::Vector<const char>("",        0));
  check(i::Vector<const char>("*",       1));
  check(i::Vector<const char>(".zZ",     3));
  check(i::Vector<const char>("muc",     3));
  check(i::Vector<const char>("(>'_')>", 7));
  check(i::Vector<const char>("-=[ vee eight ftw ]=-", 21));
}

#undef __
<commit_msg>Fixing crash of StringHash test.<commit_after>// Copyright 2011 the V8 project authors. 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 <stdlib.h>

#include "v8.h"

#include "factory.h"
#include "macro-assembler.h"
#include "cctest.h"
#include "code-stubs.h"
#include "objects.h"

#ifdef USE_SIMULATOR
#include "simulator.h"
#endif

using namespace v8::internal;

typedef uint32_t (*HASH_FUNCTION)();

static v8::Persistent<v8::Context> env;

#define __ assm->

void generate(MacroAssembler* assm, i::Vector<const char> string) {
#ifdef V8_TARGET_ARCH_IA32
  __ push(ebx);
  __ push(ecx);
  __ mov(eax, Immediate(0));
  if (string.length() > 0) {
    __ mov(ebx, Immediate(string.at(0)));
    StringHelper::GenerateHashInit(assm, eax, ebx, ecx);
  }
  for (int i = 1; i < string.length(); i++) {
    __ mov(ebx, Immediate(string.at(i)));
    StringHelper::GenerateHashAddCharacter(assm, eax, ebx, ecx);
  }
  StringHelper::GenerateHashGetHash(assm, eax, ecx);
  __ pop(ecx);
  __ pop(ebx);
  __ Ret();
#elif V8_TARGET_ARCH_X64
  __ push(rbx);
  __ push(rcx);
  __ movq(rax, Immediate(0));
  if (string.length() > 0) {
    __ movq(rbx, Immediate(string.at(0)));
    StringHelper::GenerateHashInit(assm, rax, rbx, rcx);
  }
  for (int i = 1; i < string.length(); i++) {
    __ movq(rbx, Immediate(string.at(i)));
    StringHelper::GenerateHashAddCharacter(assm, rax, rbx, rcx);
  }
  StringHelper::GenerateHashGetHash(assm, rax, rcx);
  __ pop(rcx);
  __ pop(rbx);
  __ Ret();
#elif V8_TARGET_ARCH_ARM
  __ mov(r0, Operand(0));
  if (string.length() > 0) {
    __ mov(ip, Operand(string.at(0)));
    StringHelper::GenerateHashInit(assm, r0, ip);
  }
  for (int i = 1; i < string.length(); i++) {
    __ mov(ip, Operand(string.at(i)));
    StringHelper::GenerateHashAddCharacter(assm, r0, ip);
  }
  StringHelper::GenerateHashGetHash(assm, r0);
  __ mov(pc, Operand(lr));
#elif V8_TARGET_ARCH_MIPS
  __ li(v0, Operand(0));
  if (string.length() > 0) {
    __ li(t1, Operand(string.at(0)));
    StringHelper::GenerateHashInit(assm, v0, t1);
  }
  for (int i = 1; i < string.length(); i++) {
    __ li(t1, Operand(string.at(i)));
    StringHelper::GenerateHashAddCharacter(assm, v0, t1);
  }
  StringHelper::GenerateHashGetHash(assm, v0);
  __ jr(ra);
#endif
}

void check(i::Vector<const char> string) {
  v8::HandleScope scope;
  v8::internal::byte buffer[2048];
  MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer);

  generate(&assm, string);

  CodeDesc desc;
  assm.GetCode(&desc);
  Code* code = Code::cast(HEAP->CreateCode(
      desc,
      Code::ComputeFlags(Code::STUB),
      Handle<Object>(HEAP->undefined_value()))->ToObjectChecked());
  CHECK(code->IsCode());

  HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(Code::cast(code)->entry());
  Handle<String> v8_string = FACTORY->NewStringFromAscii(string);
  v8_string->set_hash_field(String::kEmptyHashField);
#ifdef USE_SIMULATOR
  uint32_t codegen_hash =
      reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0));
#else
  uint32_t codegen_hash = hash();
#endif
  uint32_t runtime_hash = v8_string->Hash();
  CHECK(runtime_hash == codegen_hash);
}

void check_twochars(char a, char b) {
  char ab[2] = {a, b};
  check(i::Vector<const char>(ab, 2));
}

TEST(StringHash) {
  if (env.IsEmpty()) env = v8::Context::New();
  for (int a = 0; a < String::kMaxAsciiCharCode; a++) {
    // Numbers are hashed differently.
    if (a >= '0' && a <= '9') continue;
    for (int b = 0; b < String::kMaxAsciiCharCode; b++) {
      if (b >= '0' && b <= '9') continue;
      check_twochars(static_cast<char>(a), static_cast<char>(b));
    }
  }
  check(i::Vector<const char>("",        0));
  check(i::Vector<const char>("*",       1));
  check(i::Vector<const char>(".zZ",     3));
  check(i::Vector<const char>("muc",     3));
  check(i::Vector<const char>("(>'_')>", 7));
  check(i::Vector<const char>("-=[ vee eight ftw ]=-", 21));
}

#undef __
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "../test_common.h"

class ProcTest : public ExpectOutput {};

template <typename Func>
static Output spawnAndWait(IOConfig config, Func func, bool remove = false) {
    return ProcBuilder::spawn(config, func).waitAndGetResult(remove);
}

TEST_F(ProcTest, status) {
    auto ret = spawnAndWait(IOConfig{}, [&]{
        return 100;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 100));

    ret = spawnAndWait(IOConfig{}, [&]()-> int {
        abort();
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, SIGABRT, WaitStatus::SIGNALED));
}

TEST_F(ProcTest, pipe) {
    IOConfig config;
    config.out = IOConfig::PIPE;
    auto ret = spawnAndWait(config, [&]{
       return 10;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 10));

    config.err = IOConfig::PIPE;
    ret = spawnAndWait(config, [&]{
        fprintf(stdout, "hello");
        fprintf(stderr, "world");
        return 10;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 10, WaitStatus::EXITED, "hello", "world"));
}

//static std::string

TEST_F(ProcTest, pty) {
    IOConfig config;
    config.in = IOConfig::PTY;
    config.out = IOConfig::PTY;
    config.err = IOConfig::PIPE;

    auto ret = spawnAndWait(config, [&]{
        if(!isatty(STDIN_FILENO)) {
            return 10;
        }
        if(!isatty(STDOUT_FILENO)) {
            return 20;
        }
        if(isatty(STDERR_FILENO)) {
            return 30;
        }
        printf("hello pty\n");
        printf("!!");
        return 0;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 0, WaitStatus::EXITED, "hello pty\n!!"));

    auto handle = ProcBuilder::spawn(config, [&]{
        char buf[64];
        auto size = read(STDIN_FILENO, buf, 64);
        if(size > 0) {
            buf[size] = '\0';
            printf("%s\n", buf);
            return 0;
        }
        return 1;
    });
    std::string str = "hello";
    write(handle.in(), str.c_str(), str.size());
    auto ret2 = handle.waitAndGetResult(false);
    ASSERT_NO_FATAL_FAILURE(this->expect(ret2, 0, WaitStatus::EXITED, "hello\n"));
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}<commit_msg>fix build error in gcc<commit_after>#include "gtest/gtest.h"

#include "../test_common.h"

class ProcTest : public ExpectOutput {};

template <typename Func>
static Output spawnAndWait(IOConfig config, Func func, bool remove = false) {
    return ProcBuilder::spawn(config, func).waitAndGetResult(remove);
}

TEST_F(ProcTest, status) {
    auto ret = spawnAndWait(IOConfig{}, [&]{
        return 100;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 100));

    ret = spawnAndWait(IOConfig{}, [&]()-> int {
        abort();
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, SIGABRT, WaitStatus::SIGNALED));
}

TEST_F(ProcTest, pipe) {
    IOConfig config;
    config.out = IOConfig::PIPE;
    auto ret = spawnAndWait(config, [&]{
       return 10;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 10));

    config.err = IOConfig::PIPE;
    ret = spawnAndWait(config, [&]{
        fprintf(stdout, "hello");
        fprintf(stderr, "world");
        return 10;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 10, WaitStatus::EXITED, "hello", "world"));
}

//static std::string

TEST_F(ProcTest, pty) {
    IOConfig config;
    config.in = IOConfig::PTY;
    config.out = IOConfig::PTY;
    config.err = IOConfig::PIPE;

    auto ret = spawnAndWait(config, [&]{
        if(!isatty(STDIN_FILENO)) {
            return 10;
        }
        if(!isatty(STDOUT_FILENO)) {
            return 20;
        }
        if(isatty(STDERR_FILENO)) {
            return 30;
        }
        printf("hello pty\n");
        printf("!!");
        return 0;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 0, WaitStatus::EXITED, "hello pty\n!!"));

    auto handle = ProcBuilder::spawn(config, [&]{
        char buf[64];
        auto size = read(STDIN_FILENO, buf, 64);
        if(size > 0) {
            buf[size] = '\0';
            printf("%s\n", buf);
            return 0;
        }
        return 1;
    });
    std::string str = "hello";
    (void)write(handle.in(), str.c_str(), str.size());
    auto ret2 = handle.waitAndGetResult(false);
    ASSERT_NO_FATAL_FAILURE(this->expect(ret2, 0, WaitStatus::EXITED, "hello\n"));
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "../test_common.h"

class ProcTest : public ExpectOutput {};

template <typename Func>
static Output spawnAndWait(IOConfig config, Func func, bool remove = false) {
    return ProcBuilder::spawn(config, func).waitAndGetResult(remove);
}

TEST_F(ProcTest, status) {
    auto ret = spawnAndWait(IOConfig{}, [&]{
        return 100;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 100));

    ret = spawnAndWait(IOConfig{}, [&]()-> int {
        abort();
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, SIGABRT, WaitStatus::SIGNALED));
}

TEST_F(ProcTest, pipe) {
    IOConfig config;
    config.out = IOConfig::PIPE;
    auto ret = spawnAndWait(config, [&]{
       return 10;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 10));

    config.err = IOConfig::PIPE;
    ret = spawnAndWait(config, [&]{
        fprintf(stdout, "hello");
        fprintf(stderr, "world");
        return 10;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 10, WaitStatus::EXITED, "hello", "world"));
}

//static std::string

TEST_F(ProcTest, pty) {
    IOConfig config;
    config.in = IOConfig::PTY;
    config.out = IOConfig::PTY;
    config.err = IOConfig::PIPE;

    auto ret = spawnAndWait(config, [&]{
        if(!isatty(STDIN_FILENO)) {
            return 10;
        }
        if(!isatty(STDOUT_FILENO)) {
            return 20;
        }
        if(isatty(STDERR_FILENO)) {
            return 30;
        }
        printf("hello pty\n");
        printf("!!");
        return 0;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 0, WaitStatus::EXITED, "hello pty\n!!"));
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}<commit_msg>update test case<commit_after>#include "gtest/gtest.h"

#include "../test_common.h"

class ProcTest : public ExpectOutput {};

template <typename Func>
static Output spawnAndWait(IOConfig config, Func func, bool remove = false) {
    return ProcBuilder::spawn(config, func).waitAndGetResult(remove);
}

TEST_F(ProcTest, status) {
    auto ret = spawnAndWait(IOConfig{}, [&]{
        return 100;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 100));

    ret = spawnAndWait(IOConfig{}, [&]()-> int {
        abort();
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, SIGABRT, WaitStatus::SIGNALED));
}

TEST_F(ProcTest, pipe) {
    IOConfig config;
    config.out = IOConfig::PIPE;
    auto ret = spawnAndWait(config, [&]{
       return 10;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 10));

    config.err = IOConfig::PIPE;
    ret = spawnAndWait(config, [&]{
        fprintf(stdout, "hello");
        fprintf(stderr, "world");
        return 10;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 10, WaitStatus::EXITED, "hello", "world"));
}

//static std::string

TEST_F(ProcTest, pty) {
    IOConfig config;
    config.in = IOConfig::PTY;
    config.out = IOConfig::PTY;
    config.err = IOConfig::PIPE;

    auto ret = spawnAndWait(config, [&]{
        if(!isatty(STDIN_FILENO)) {
            return 10;
        }
        if(!isatty(STDOUT_FILENO)) {
            return 20;
        }
        if(isatty(STDERR_FILENO)) {
            return 30;
        }
        printf("hello pty\n");
        printf("!!");
        return 0;
    });
    ASSERT_NO_FATAL_FAILURE(this->expect(ret, 0, WaitStatus::EXITED, "hello pty\n!!"));

    auto handle = ProcBuilder::spawn(config, [&]{
        char buf[64];
        auto size = read(STDIN_FILENO, buf, 64);
        if(size > 0) {
            buf[size] = '\0';
            printf("%s\n", buf);
            return 0;
        }
        return 1;
    });
    std::string str = "hello";
    write(handle.in(), str.c_str(), str.size());
    auto ret2 = handle.waitAndGetResult(false);
    ASSERT_NO_FATAL_FAILURE(this->expect(ret2, 0, WaitStatus::EXITED, "hello\n"));
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include "libtorrent/policy.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6()
#include <boost/crc.hpp>

#include "test.hpp"

using namespace libtorrent;

boost::uint32_t hash_buffer(char const* buf, int len)
{
	boost::crc_optimal<32, 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc;
	crc.process_block(buf, buf + len);
	return crc.checksum();
}

int test_main()
{

	// when the IP is the same, we hash the ports, sorted
	boost::uint32_t p = peer_priority(
		tcp::endpoint(address::from_string("230.12.123.3"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\x01\x2c\x04\xd2", 4));

	// when we're in the same /24, we just hash the IPs
	p = peer_priority(
		tcp::endpoint(address::from_string("230.12.123.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x7b\x01\xe6\x0c\x7b\x03", 8));

	// when we're in the same /16, we just hash the IPs masked by
	// 0xffffff55
	p = peer_priority(
		tcp::endpoint(address::from_string("230.12.23.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x17\x01\xe6\x0c\x7b\x01", 8));

	// when we're in different /16, we just hash the IPs masked by
	// 0xffff5555
	p = peer_priority(
		tcp::endpoint(address::from_string("230.120.23.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x51\x01\xe6\x78\x15\x01", 8));

	if (supports_ipv6())
	{
		// IPv6 has a twice as wide mask, and we only care about the top 64 bits
		// when the IPs are the same, just hash the ports
		p = peer_priority(
			tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x4d2)
			, tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x12c));
		TEST_EQUAL(p, hash_buffer("\x01\x2c\x04\xd2", 4));

		// these IPs don't belong to the same /32, so apply the full mask
		// 0xffffffff55555555
		p = peer_priority(
			tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x4d2)
			, tcp::endpoint(address::from_string("ffff:0fff:ffff:ffff::1"), 0x12c));
		TEST_EQUAL(p, hash_buffer(
			"\xff\xff\x0f\xff\x55\x55\x55\x55\x00\x00\x00\x00\x00\x00\x00\x01"
			"\xff\xff\xff\xff\x55\x55\x55\x55\x00\x00\x00\x00\x00\x00\x00\x01", 32));
	}

	return 0;
}

<commit_msg>add test vector from bep40 to test_peer_priority<commit_after>/*

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

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

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

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

*/

#include "libtorrent/policy.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6()
#include <boost/crc.hpp>

#include "test.hpp"

using namespace libtorrent;

boost::uint32_t hash_buffer(char const* buf, int len)
{
	boost::crc_optimal<32, 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc;
	crc.process_block(buf, buf + len);
	return crc.checksum();
}

int test_main()
{

	// when the IP is the same, we hash the ports, sorted
	boost::uint32_t p = peer_priority(
		tcp::endpoint(address::from_string("230.12.123.3"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\x01\x2c\x04\xd2", 4));

	// when we're in the same /24, we just hash the IPs
	p = peer_priority(
		tcp::endpoint(address::from_string("230.12.123.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x7b\x01\xe6\x0c\x7b\x03", 8));

	// when we're in the same /16, we just hash the IPs masked by
	// 0xffffff55
	p = peer_priority(
		tcp::endpoint(address::from_string("230.12.23.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x17\x01\xe6\x0c\x7b\x01", 8));

	// when we're in different /16, we just hash the IPs masked by
	// 0xffff5555
	p = peer_priority(
		tcp::endpoint(address::from_string("230.120.23.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x51\x01\xe6\x78\x15\x01", 8));

	// test vectors from BEP 40
	TEST_EQUAL(peer_priority(
		tcp::endpoint(address::from_string("123.213.32.10"), 0)
		, tcp::endpoint(address::from_string("98.76.54.32"), 0))
		, 0xec2d7224);

	TEST_EQUAL(peer_priority(
		tcp::endpoint(address::from_string("123.213.32.10"), 0)
		, tcp::endpoint(address::from_string("123.213.32.234"), 0))
		, 0x99568189);

	if (supports_ipv6())
	{
		// IPv6 has a twice as wide mask, and we only care about the top 64 bits
		// when the IPs are the same, just hash the ports
		p = peer_priority(
			tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x4d2)
			, tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x12c));
		TEST_EQUAL(p, hash_buffer("\x01\x2c\x04\xd2", 4));

		// these IPs don't belong to the same /32, so apply the full mask
		// 0xffffffff55555555
		p = peer_priority(
			tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x4d2)
			, tcp::endpoint(address::from_string("ffff:0fff:ffff:ffff::1"), 0x12c));
		TEST_EQUAL(p, hash_buffer(
			"\xff\xff\x0f\xff\x55\x55\x55\x55\x00\x00\x00\x00\x00\x00\x00\x01"
			"\xff\xff\xff\xff\x55\x55\x55\x55\x00\x00\x00\x00\x00\x00\x00\x01", 32));
	}

	return 0;
}

<|endoftext|>


<commit_before>/******************************************************************************
The MIT License(MIT)

Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com

Copyright(c) 2020 jwellbelove

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/

#include "UnitTest++/UnitTest++.h"

#include <ostream>
#include <sstream>
#include <iomanip>

#include "etl/string_stream.h"
#include "etl/cstring.h"
#include "etl/format_spec.h"

#undef STR
#define STR(x) x

namespace
{
  using String = etl::string<50>;
  using IString = etl::istring;
  using Stream = etl::string_stream;
  using Format = etl::format_spec;

  //***********************************
  struct Custom
  {
    int x;
    int y;
  };

  //***********************************
  Stream& operator <<(Stream& ss, const Custom& value)
  {
    ss << STR("X = ") << value.x << STR(" : Y = ") << value.y;
    return ss;
  }
}

namespace etl
{
  //***********************************
  template <size_t SIZE>
  std::ostream& operator << (std::ostream& os, const etl::string<SIZE>& str)
  {
    for (auto c : str)
    {
      os << c;
    }

    return os;
  }

  //***********************************
  std::ostream& operator << (std::ostream& os, const IString& str)
  {
    for (auto c : str)
    {
      os << c;
    }

    return os;
  }
}

namespace
{
  SUITE(test_string_stream)
  {
    //*************************************************************************
    TEST(test_default_format)
    {
      String str;

      Stream ss(str);

      int value = 123;
      String hello(STR("Hello"));
      ss << hello << STR(" World ") << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("Hello World 123")), result);
    }

    //*************************************************************************
    TEST(test_custom_format)
    {
      String str;
      Format format = Format().base(10).width(10).fill(STR('#'));

      Stream ss(str);

      int value = 123;
      String hello(STR("Hello"));
      ss << format << hello << STR("World") << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("#####Hello#####World#######123")), result);
    }

    //*************************************************************************
    TEST(test_custom_multi_format)
    {
      String str;
      Format format1 = Format().base(10).width(10).fill(STR('#'));
      Format format2 = Format().base(10).width(8).fill(STR('*')).left();
      Format format3 = Format().base(16).width(4).fill(STR(' ')).right();

      Stream ss(str);

      int value = 123;
      String hello(STR("Hello"));
      ss << format1 << hello << format2 << STR("World") << format3 << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("#####HelloWorld***  7b")), result);
    }

    //*************************************************************************
    TEST(test_custom_inline_format)
    {
      String str;
      Stream ss(str);

      int value = 123456;

      ss << etl::setbase(10U) << etl::setw(20) << etl::setfill(STR('-')) << etl::left;

      ss << etl::bin << value;
      CHECK_EQUAL(String(STR("11110001001000000---")), ss.str());

      ss.str().clear();
      ss << etl::oct << value;
      CHECK_EQUAL(String(STR("361100--------------")), ss.str());

      ss.str().clear();
      ss << etl::dec << value;
      CHECK_EQUAL(String(STR("123456--------------")), ss.str());

      ss.str().clear();
      ss << etl::hex << etl::uppercase << value;
      CHECK_EQUAL(String(STR("1E240---------------")), ss.str());

      ss.str().clear();
      ss << etl::hex << etl::nouppercase << value;
      CHECK_EQUAL(String(STR("1e240---------------")), ss.str());

      ss.str().clear();
      ss << etl::setw(0);
      ss << etl::noboolalpha << false << STR(" ") << true << STR(" ") << etl::boolalpha << false << STR(" ") << true;
      CHECK_EQUAL(String(STR("0 1 false true")), ss.str());

      ss.str().clear();
      ss << etl::setprecision(4) << 3.1415927;
      CHECK_EQUAL(String(STR("3.1416")), ss.str());

      ss.str().clear();
      ss << STR("abcdef") << STR(" ") << etl::uppercase << STR("abcdef");
      CHECK_EQUAL(String(STR("abcdef abcdef")), ss.str());
    }

    //*************************************************************************
    TEST(test_custom_inline_format_showbase)
    {
      String str;
      Stream ss(str);

      int value = 123456;

      ss << etl::bin << etl::noshowbase << value;
      CHECK_EQUAL(String(STR("11110001001000000")), ss.str());

      ss.str().clear();
      ss << etl::bin << etl::showbase << value;
      CHECK_EQUAL(String(STR("0b11110001001000000")), ss.str());

      ss.str().clear();
      ss << etl::oct << etl::noshowbase << value;
      CHECK_EQUAL(String(STR("361100")), ss.str());

      ss.str().clear();
      ss << etl::oct << etl::showbase << value;
      CHECK_EQUAL(String(STR("0361100")), ss.str());

      ss.str().clear();
      ss << etl::dec << etl::noshowbase << value;
      CHECK_EQUAL(String(STR("123456")), ss.str());

      ss.str().clear();
      ss << etl::dec << etl::showbase << value;
      CHECK_EQUAL(String(STR("123456")), ss.str());

      ss.str().clear();
      ss << etl::hex << etl::noshowbase << value;
      CHECK_EQUAL(String(STR("1e240")), ss.str());

      ss.str().clear();
      ss << etl::hex << etl::showbase << value;
      CHECK_EQUAL(String(STR("0x1e240")), ss.str());
    }

    //*************************************************************************
    TEST(test_custom_multi_inline_format)
    {
      String str;
      Stream ss(str);

      int value = 123;
      String hello(STR("Hello"));
      ss << etl::dec << etl::setw(10) << etl::setfill(STR('#')) << hello
         << etl::setw(8) << etl::setfill(STR('*')) << etl::left << STR("World")
         << etl::hex << etl::setw(4) << etl::setfill(STR(' ')) << etl::right << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("#####HelloWorld***  7b")), result);
    }

    //*************************************************************************
    TEST(test_custom_class_default_format)
    {
      String str;

      Stream ss(str);

      String value_str(STR("Value: "));
      IString& ivalue_str = value_str;
      Custom value = { 1, 2 };

      ss << ivalue_str << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("Value: X = 1 : Y = 2")), result);
    }

    //*************************************************************************
    TEST(test_get_format)
    {
      String str;
      Format format = Format().base(16).width(4).fill(STR(' ')).right();

      Stream ss(str, format);

      Format format2 = ss.get_format();

      CHECK(format == format2);
    }

    //*************************************************************************
    TEST(test_set_from_character_pointer)
    {
      String str;
      Stream ss(str);

      ss.str(STR("Hello"));

      CHECK_EQUAL(String(STR("Hello")), ss.str());
    }

    //*************************************************************************
    TEST(test_set_from_string)
    {
      String str;
      Stream ss(str);

      ss.str(String(STR("Hello")));

      CHECK_EQUAL(String(STR("Hello")), ss.str());
    }

    //*************************************************************************
    TEST(test_get_istring)
    {
      String str;
      Stream ss(str);

      ss.str(String(STR("Hello")));

      IString& istr = ss.str();
      istr.resize(istr.size() - 1);

      CHECK_EQUAL(String(STR("Hell")), istr);
    }

    //*************************************************************************
    TEST(test_get_const_istring)
    {
      String str;
      Stream ss(str);

      ss.str(String(STR("Hello")));

      const IString& istr = ss.str();

      CHECK_EQUAL(String(STR("Hello")), istr);
    }
  };
}

<commit_msg>String stream test << operator<commit_after>/******************************************************************************
The MIT License(MIT)

Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com

Copyright(c) 2020 jwellbelove

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/

#include "UnitTest++/UnitTest++.h"

#include <ostream>
#include <sstream>
#include <iomanip>

#include "etl/string_stream.h"
#include "etl/cstring.h"
#include "etl/format_spec.h"

#undef STR
#define STR(x) x

namespace
{
  using String = etl::string<50>;
  using IString = etl::istring;
  using Stream = etl::string_stream;
  using Format = etl::format_spec;

  //***********************************
  struct Custom
  {
    int x;
    int y;
  };

  //***********************************
  Stream& operator <<(Stream& ss, const Custom& value)
  {
    ss << STR("X = ") << value.x << STR(" : Y = ") << value.y;
    return ss;
  }
}

namespace etl
{
  //***********************************
  std::ostream& operator << (std::ostream& os, const IString& str)
  {
    for (auto c : str)
    {
      os << c;
    }

    return os;
  }
}

namespace
{
  SUITE(test_string_stream)
  {
    //*************************************************************************
    TEST(test_default_format)
    {
      String str;

      Stream ss(str);

      int value = 123;
      String hello(STR("Hello"));
      ss << hello << STR(" World ") << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("Hello World 123")), result);
    }

    //*************************************************************************
    TEST(test_custom_format)
    {
      String str;
      Format format = Format().base(10).width(10).fill(STR('#'));

      Stream ss(str);

      int value = 123;
      String hello(STR("Hello"));
      ss << format << hello << STR("World") << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("#####Hello#####World#######123")), result);
    }

    //*************************************************************************
    TEST(test_custom_multi_format)
    {
      String str;
      Format format1 = Format().base(10).width(10).fill(STR('#'));
      Format format2 = Format().base(10).width(8).fill(STR('*')).left();
      Format format3 = Format().base(16).width(4).fill(STR(' ')).right();

      Stream ss(str);

      int value = 123;
      String hello(STR("Hello"));
      ss << format1 << hello << format2 << STR("World") << format3 << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("#####HelloWorld***  7b")), result);
    }

    //*************************************************************************
    TEST(test_custom_inline_format)
    {
      String str;
      Stream ss(str);

      int value = 123456;

      ss << etl::setbase(10U) << etl::setw(20) << etl::setfill(STR('-')) << etl::left;

      ss << etl::bin << value;
      CHECK_EQUAL(String(STR("11110001001000000---")), ss.str());

      ss.str().clear();
      ss << etl::oct << value;
      CHECK_EQUAL(String(STR("361100--------------")), ss.str());

      ss.str().clear();
      ss << etl::dec << value;
      CHECK_EQUAL(String(STR("123456--------------")), ss.str());

      ss.str().clear();
      ss << etl::hex << etl::uppercase << value;
      CHECK_EQUAL(String(STR("1E240---------------")), ss.str());

      ss.str().clear();
      ss << etl::hex << etl::nouppercase << value;
      CHECK_EQUAL(String(STR("1e240---------------")), ss.str());

      ss.str().clear();
      ss << etl::setw(0);
      ss << etl::noboolalpha << false << STR(" ") << true << STR(" ") << etl::boolalpha << false << STR(" ") << true;
      CHECK_EQUAL(String(STR("0 1 false true")), ss.str());

      ss.str().clear();
      ss << etl::setprecision(4) << 3.1415927;
      CHECK_EQUAL(String(STR("3.1416")), ss.str());

      ss.str().clear();
      ss << STR("abcdef") << STR(" ") << etl::uppercase << STR("abcdef");
      CHECK_EQUAL(String(STR("abcdef abcdef")), ss.str());
    }

    //*************************************************************************
    TEST(test_custom_inline_format_showbase)
    {
      String str;
      Stream ss(str);

      int value = 123456;

      ss << etl::bin << etl::noshowbase << value;
      CHECK_EQUAL(String(STR("11110001001000000")), ss.str());

      ss.str().clear();
      ss << etl::bin << etl::showbase << value;
      CHECK_EQUAL(String(STR("0b11110001001000000")), ss.str());

      ss.str().clear();
      ss << etl::oct << etl::noshowbase << value;
      CHECK_EQUAL(String(STR("361100")), ss.str());

      ss.str().clear();
      ss << etl::oct << etl::showbase << value;
      CHECK_EQUAL(String(STR("0361100")), ss.str());

      ss.str().clear();
      ss << etl::dec << etl::noshowbase << value;
      CHECK_EQUAL(String(STR("123456")), ss.str());

      ss.str().clear();
      ss << etl::dec << etl::showbase << value;
      CHECK_EQUAL(String(STR("123456")), ss.str());

      ss.str().clear();
      ss << etl::hex << etl::noshowbase << value;
      CHECK_EQUAL(String(STR("1e240")), ss.str());

      ss.str().clear();
      ss << etl::hex << etl::showbase << value;
      CHECK_EQUAL(String(STR("0x1e240")), ss.str());
    }

    //*************************************************************************
    TEST(test_custom_multi_inline_format)
    {
      String str;
      Stream ss(str);

      int value = 123;
      String hello(STR("Hello"));
      ss << etl::dec << etl::setw(10) << etl::setfill(STR('#')) << hello
         << etl::setw(8) << etl::setfill(STR('*')) << etl::left << STR("World")
         << etl::hex << etl::setw(4) << etl::setfill(STR(' ')) << etl::right << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("#####HelloWorld***  7b")), result);
    }

    //*************************************************************************
    TEST(test_custom_class_default_format)
    {
      String str;

      Stream ss(str);

      String value_str(STR("Value: "));
      IString& ivalue_str = value_str;
      Custom value = { 1, 2 };

      ss << ivalue_str << value;

      String result = ss.str();

      CHECK_EQUAL(String(STR("Value: X = 1 : Y = 2")), result);
    }

    //*************************************************************************
    TEST(test_get_format)
    {
      String str;
      Format format = Format().base(16).width(4).fill(STR(' ')).right();

      Stream ss(str, format);

      Format format2 = ss.get_format();

      CHECK(format == format2);
    }

    //*************************************************************************
    TEST(test_set_from_character_pointer)
    {
      String str;
      Stream ss(str);

      ss.str(STR("Hello"));

      CHECK_EQUAL(String(STR("Hello")), ss.str());
    }

    //*************************************************************************
    TEST(test_set_from_string)
    {
      String str;
      Stream ss(str);

      ss.str(String(STR("Hello")));

      CHECK_EQUAL(String(STR("Hello")), ss.str());
    }

    //*************************************************************************
    TEST(test_get_istring)
    {
      String str;
      Stream ss(str);

      ss.str(String(STR("Hello")));

      IString& istr = ss.str();
      istr.resize(istr.size() - 1);

      CHECK_EQUAL(String(STR("Hell")), istr);
    }

    //*************************************************************************
    TEST(test_get_const_istring)
    {
      String str;
      Stream ss(str);

      ss.str(String(STR("Hello")));

      const IString& istr = ss.str();

      CHECK_EQUAL(String(STR("Hello")), istr);
    }
  };
}

<|endoftext|>


<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkTypes.h"
#include "Resources.h"
#include "Test.h"

#if SK_SUPPORT_GPU
#include "GrContext.h"
#endif
#include "SkCanvas.h"
#include "SkColorSpace_Base.h"
#include "SkImage.h"
#include "SkSurface.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"

static void test_flatten(skiatest::Reporter* reporter, const SkImageInfo& info) {
    // Need a safe amount of 4-byte aligned storage.  Note that one of the test ICC profiles
    // is ~7500 bytes.
    const size_t storageBytes = 8000;
    SkAutoTMalloc<uint32_t> storage(storageBytes / sizeof(uint32_t));
    SkBinaryWriteBuffer wb(storage.get(), storageBytes);
    info.flatten(wb);
    SkASSERT(wb.bytesWritten() < storageBytes);

    SkReadBuffer rb(storage.get(), wb.bytesWritten());

    // pick a noisy byte pattern, so we ensure that unflatten sets all of our fields
    SkImageInfo info2 = SkImageInfo::Make(0xB8, 0xB8, (SkColorType) 0xB8, (SkAlphaType) 0xB8);

    info2.unflatten(rb);
    REPORTER_ASSERT(reporter, rb.offset() == wb.bytesWritten());

    REPORTER_ASSERT(reporter, info == info2);
}

DEF_TEST(ImageInfo_flattening, reporter) {
     sk_sp<SkData> data =
             SkData::MakeFromFileName(GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str());
    sk_sp<SkColorSpace> space0 = SkColorSpace::MakeICC(data->data(), data->size());
    data = SkData::MakeFromFileName( GetResourcePath("icc_profiles/HP_Z32x.icc").c_str());
    sk_sp<SkColorSpace> space1 = SkColorSpace::MakeICC(data->data(), data->size());
    data = SkData::MakeFromFileName(GetResourcePath("icc_profiles/upperLeft.icc").c_str());
    sk_sp<SkColorSpace> space2 = SkColorSpace::MakeICC(data->data(), data->size());
    data = SkData::MakeFromFileName(GetResourcePath("icc_profiles/upperRight.icc").c_str());
    sk_sp<SkColorSpace> space3 = SkColorSpace::MakeICC(data->data(), data->size());

    sk_sp<SkColorSpace> spaces[] = {
        nullptr,
        SkColorSpace::MakeSRGB(),
        SkColorSpace_Base::MakeNamed(SkColorSpace_Base::kAdobeRGB_Named),
        space0,
        space1,
        space2,
        space3,
    };

    for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
        for (int at = 0; at <= kLastEnum_SkAlphaType; ++at) {
            for (auto& cs : spaces) {
                SkImageInfo info = SkImageInfo::Make(100, 200,
                                                     static_cast<SkColorType>(ct),
                                                     static_cast<SkAlphaType>(at),
                                                     cs);
                test_flatten(reporter, info);
            }
        }
    }
}

static void check_isopaque(skiatest::Reporter* reporter, const sk_sp<SkSurface>& surface,
                           bool expectedOpaque) {
    sk_sp<SkImage> image(surface->makeImageSnapshot());
    REPORTER_ASSERT(reporter, image->isOpaque() == expectedOpaque);
}

DEF_TEST(ImageIsOpaqueTest, reporter) {
    SkImageInfo infoTransparent = SkImageInfo::MakeN32Premul(5, 5);
    auto surfaceTransparent(SkSurface::MakeRaster(infoTransparent));
    check_isopaque(reporter, surfaceTransparent, false);

    SkImageInfo infoOpaque = SkImageInfo::MakeN32(5, 5, kOpaque_SkAlphaType);
    auto surfaceOpaque(SkSurface::MakeRaster(infoOpaque));
    check_isopaque(reporter, surfaceOpaque, true);
}

#if SK_SUPPORT_GPU

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageIsOpaqueTest_Gpu, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    SkImageInfo infoTransparent = SkImageInfo::MakeN32Premul(5, 5);
    auto surfaceTransparent(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, infoTransparent));
    check_isopaque(reporter, surfaceTransparent, false);

    SkImageInfo infoOpaque = SkImageInfo::MakeN32(5, 5, kOpaque_SkAlphaType);
    auto surfaceOpaque(SkSurface::MakeRenderTarget(context,SkBudgeted::kNo, infoOpaque));

    check_isopaque(reporter, surfaceOpaque, true);
}

#endif

///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkPictureRecorder.h"

static sk_sp<SkPicture> make_picture() {
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording({ 0, 0, 10, 10 });
    canvas->drawColor(SK_ColorRED);
    return recorder.finishRecordingAsPicture();
}

DEF_TEST(Image_isAlphaOnly, reporter) {
    SkPMColor pmColors = 0;
    SkPixmap pmap = {
        SkImageInfo::MakeN32Premul(1, 1),
        &pmColors,
        sizeof(pmColors)
    };
    for (auto& image : {
        SkImage::MakeRasterCopy(pmap),
        GetResourceAsImage("mandrill_128.png"),
        GetResourceAsImage("color_wheel.jpg"),
        SkImage::MakeFromPicture(make_picture(), { 10, 10 }, nullptr, nullptr,
                                 SkImage::BitDepth::kU8,
                                 SkColorSpace::MakeSRGB()),
    })
    {
        REPORTER_ASSERT(reporter, image->isAlphaOnly() == false);
    }

    REPORTER_ASSERT(reporter, SkImage::MakeRasterCopy({
        SkImageInfo::MakeA8(1, 1), (uint8_t*)&pmColors, 1})->isAlphaOnly() == true);
}
<commit_msg>don't test index8 -- no longer supported<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkTypes.h"
#include "Resources.h"
#include "Test.h"

#if SK_SUPPORT_GPU
#include "GrContext.h"
#endif
#include "SkCanvas.h"
#include "SkColorSpace_Base.h"
#include "SkImage.h"
#include "SkSurface.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"

static void test_flatten(skiatest::Reporter* reporter, const SkImageInfo& info) {
    // Need a safe amount of 4-byte aligned storage.  Note that one of the test ICC profiles
    // is ~7500 bytes.
    const size_t storageBytes = 8000;
    SkAutoTMalloc<uint32_t> storage(storageBytes / sizeof(uint32_t));
    SkBinaryWriteBuffer wb(storage.get(), storageBytes);
    info.flatten(wb);
    SkASSERT(wb.bytesWritten() < storageBytes);

    SkReadBuffer rb(storage.get(), wb.bytesWritten());

    // pick a noisy byte pattern, so we ensure that unflatten sets all of our fields
    SkImageInfo info2 = SkImageInfo::Make(0xB8, 0xB8, (SkColorType) 0xB8, (SkAlphaType) 0xB8);

    info2.unflatten(rb);
    REPORTER_ASSERT(reporter, rb.offset() == wb.bytesWritten());

    REPORTER_ASSERT(reporter, info == info2);
}

DEF_TEST(ImageInfo_flattening, reporter) {
     sk_sp<SkData> data =
             SkData::MakeFromFileName(GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str());
    sk_sp<SkColorSpace> space0 = SkColorSpace::MakeICC(data->data(), data->size());
    data = SkData::MakeFromFileName( GetResourcePath("icc_profiles/HP_Z32x.icc").c_str());
    sk_sp<SkColorSpace> space1 = SkColorSpace::MakeICC(data->data(), data->size());
    data = SkData::MakeFromFileName(GetResourcePath("icc_profiles/upperLeft.icc").c_str());
    sk_sp<SkColorSpace> space2 = SkColorSpace::MakeICC(data->data(), data->size());
    data = SkData::MakeFromFileName(GetResourcePath("icc_profiles/upperRight.icc").c_str());
    sk_sp<SkColorSpace> space3 = SkColorSpace::MakeICC(data->data(), data->size());

    sk_sp<SkColorSpace> spaces[] = {
        nullptr,
        SkColorSpace::MakeSRGB(),
        SkColorSpace_Base::MakeNamed(SkColorSpace_Base::kAdobeRGB_Named),
        space0,
        space1,
        space2,
        space3,
    };

    for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {
#ifdef SK_SUPPORT_LEGACY_INDEX_8_COLORTYPE
        if (ct == kIndex_8_SkColorType) {
            continue;
        }
#endif
        for (int at = 0; at <= kLastEnum_SkAlphaType; ++at) {
            for (auto& cs : spaces) {
                SkImageInfo info = SkImageInfo::Make(100, 200,
                                                     static_cast<SkColorType>(ct),
                                                     static_cast<SkAlphaType>(at),
                                                     cs);
                test_flatten(reporter, info);
            }
        }
    }
}

static void check_isopaque(skiatest::Reporter* reporter, const sk_sp<SkSurface>& surface,
                           bool expectedOpaque) {
    sk_sp<SkImage> image(surface->makeImageSnapshot());
    REPORTER_ASSERT(reporter, image->isOpaque() == expectedOpaque);
}

DEF_TEST(ImageIsOpaqueTest, reporter) {
    SkImageInfo infoTransparent = SkImageInfo::MakeN32Premul(5, 5);
    auto surfaceTransparent(SkSurface::MakeRaster(infoTransparent));
    check_isopaque(reporter, surfaceTransparent, false);

    SkImageInfo infoOpaque = SkImageInfo::MakeN32(5, 5, kOpaque_SkAlphaType);
    auto surfaceOpaque(SkSurface::MakeRaster(infoOpaque));
    check_isopaque(reporter, surfaceOpaque, true);
}

#if SK_SUPPORT_GPU

DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageIsOpaqueTest_Gpu, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    SkImageInfo infoTransparent = SkImageInfo::MakeN32Premul(5, 5);
    auto surfaceTransparent(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, infoTransparent));
    check_isopaque(reporter, surfaceTransparent, false);

    SkImageInfo infoOpaque = SkImageInfo::MakeN32(5, 5, kOpaque_SkAlphaType);
    auto surfaceOpaque(SkSurface::MakeRenderTarget(context,SkBudgeted::kNo, infoOpaque));

    check_isopaque(reporter, surfaceOpaque, true);
}

#endif

///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkPictureRecorder.h"

static sk_sp<SkPicture> make_picture() {
    SkPictureRecorder recorder;
    SkCanvas* canvas = recorder.beginRecording({ 0, 0, 10, 10 });
    canvas->drawColor(SK_ColorRED);
    return recorder.finishRecordingAsPicture();
}

DEF_TEST(Image_isAlphaOnly, reporter) {
    SkPMColor pmColors = 0;
    SkPixmap pmap = {
        SkImageInfo::MakeN32Premul(1, 1),
        &pmColors,
        sizeof(pmColors)
    };
    for (auto& image : {
        SkImage::MakeRasterCopy(pmap),
        GetResourceAsImage("mandrill_128.png"),
        GetResourceAsImage("color_wheel.jpg"),
        SkImage::MakeFromPicture(make_picture(), { 10, 10 }, nullptr, nullptr,
                                 SkImage::BitDepth::kU8,
                                 SkColorSpace::MakeSRGB()),
    })
    {
        REPORTER_ASSERT(reporter, image->isAlphaOnly() == false);
    }

    REPORTER_ASSERT(reporter, SkImage::MakeRasterCopy({
        SkImageInfo::MakeA8(1, 1), (uint8_t*)&pmColors, 1})->isAlphaOnly() == true);
}
<|endoftext|>


<commit_before>/* vim: set ai et ts=4 sw=4: */

#include <Date.h>
#include <User.h>
#include <gtest/gtest.h>
#include <iostream>

class TestSerialization : public ::testing::Test {
public:
    TestSerialization() { /* init protected members here */ }

    void SetUp() { /* do nothing */ }

    void TearDown() { /* do nothing */ }

    ~TestSerialization() { /* free protected members here */ }

protected:
    /* none */
};

TEST_F(TestSerialization, DateJson) {
    Date d1(1988, 8, 5);
    rapidjson::Document json = d1.toJSON();
    Date d2 = Date::fromJSON(json);
    ASSERT_EQ(d1, d2);
}

TEST_F(TestSerialization, UserJson) {
    User u1(123, "Alex", 79161234567, Date(1988, 8, 5));
    rapidjson::Document json = u1.toJSON();
    User u2 = User::fromJSON(json);
    ASSERT_EQ(u1, u2);
}

int main(int argc, char** argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Remove redundant include file<commit_after>/* vim: set ai et ts=4 sw=4: */

#include <Date.h>
#include <User.h>
#include <gtest/gtest.h>

class TestSerialization : public ::testing::Test {
public:
    TestSerialization() { /* init protected members here */ }

    void SetUp() { /* do nothing */ }

    void TearDown() { /* do nothing */ }

    ~TestSerialization() { /* free protected members here */ }

protected:
    /* none */
};

TEST_F(TestSerialization, DateJson) {
    Date d1(1988, 8, 5);
    rapidjson::Document json = d1.toJSON();
    Date d2 = Date::fromJSON(json);
    ASSERT_EQ(d1, d2);
}

TEST_F(TestSerialization, UserJson) {
    User u1(123, "Alex", 79161234567, Date(1988, 8, 5));
    rapidjson::Document json = u1.toJSON();
    User u2 = User::fromJSON(json);
    ASSERT_EQ(u1, u2);
}

int main(int argc, char** argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>