<commit_before>#include <gl/glew.h>

#include "SpriteRenderer.h"
#include "ShaderMgr.h"
#include "ScreenFBO.h"
#include "BlendShader.h"
#include "FBO.h"

#include "dataset/ISprite.h"
#include "dataset/ISymbol.h"
#include "dataset/AbstractBV.h"
#include "view/Camera.h"
#include "render/LabelNew.h"
#include "render/PrimitiveDraw.h"
#include "common/color_config.h"

namespace d2d
{

SpriteRenderer* SpriteRenderer::m_instance = NULL;

SpriteRenderer::SpriteRenderer()
	: m_fbo(NULL)
	, m_blend_idx(0)
	, m_cam(NULL)
{
}

SpriteRenderer::~SpriteRenderer()
{
	delete m_fbo;
}

void SpriteRenderer::Draw(const ISprite* sprite,
						  const d2d::Matrix& mt,
						  const Colorf& mul,
						  const Colorf& add,
						  const Colorf& r_trans,
						  const Colorf& g_trans,
						  const Colorf& b_trans,
						  bool multi_draw) const
{
	if (!sprite->visiable)
		return;

	if (!multi_draw || sprite->GetBlendMode() == BM_NORMAL) {
		DrawImpl(sprite, mt, mul, add, r_trans, g_trans, b_trans);
	} else {
		if (!m_fbo) {
			InitBlendShader();
		}

		ShaderMgr* mgr = ShaderMgr::Instance();
		mgr->SetSpriteShader(m_blend_idx);

		DrawImplBlend(sprite);

 		mgr->SetSpriteShader(0);
 		mgr->sprite();
		FBO& scr_fbo = ScreenFBO::Instance()->GetFBO();
		mgr->SetFBO(scr_fbo.GetFboID());
	}
}

void SpriteRenderer::Draw(const ISymbol* symbol,
						  const d2d::Matrix& mt,
						  const Vector& pos,
						  float angle/* = 0.0f*/,
						  float xScale/* = 1.0f*/,
						  float yScale/* = 1.0f*/,
						  float xShear/* = 0.0f*/,
						  float yShear/* = 0.0f*/,
						  const Colorf& mul /*= Colorf(1,1,1,1)*/,
						  const Colorf& add /*= Colorf(0,0,0,0)*/,
						  const Colorf& r_trans,
						  const Colorf& g_trans,
						  const Colorf& b_trans) const
{
	Matrix t;
	t.setTransformation(pos.x, pos.y, angle, xScale, yScale, 0, 0, xShear, yShear);
	t = mt * t;
	symbol->Draw(t, mul, add, r_trans, g_trans, b_trans);
}

void SpriteRenderer::DrawName(const std::string& name, float scale, const Matrix& mt) const
{
	if (name.empty() || name[0] == '_') {
		return;
	}

	Vector pos = Math::transVector(Vector(0, 0), mt);

	LabelStyle style;
	style.has_edge = false;
	style.font_size = 20;
	style.width = 200;
	style.height = 50;
	style.color = Colorf(0, 0, 0);
	style.align_hori = HAT_CENTER;
	style.align_vert = VAT_TOP;

	LabelNew::Print(name.c_str(), pos, scale, style);
}

void SpriteRenderer::DrawImpl(const ISprite* sprite,
							  const d2d::Matrix& mt,
							  const Colorf& mul,
							  const Colorf& add,
							  const Colorf& r_trans,
							  const Colorf& g_trans,
							  const Colorf& b_trans) const
{
	Matrix t;
	sprite->GetTransMatrix(t);
	t = mt * t;

	Colorf _mul = cMul(sprite->multiCol, mul),
		_add = cAdd(sprite->addCol, add);

	Colorf _r_trans, _g_trans, _b_trans;

	_r_trans.r = sprite->r_trans.r * r_trans.r + sprite->r_trans.g * g_trans.r + sprite->r_trans.b * b_trans.r;
	_r_trans.g = sprite->r_trans.r * r_trans.g + sprite->r_trans.g * g_trans.g + sprite->r_trans.b * b_trans.g;
	_r_trans.b = sprite->r_trans.r * r_trans.b + sprite->r_trans.g * g_trans.b + sprite->r_trans.b * b_trans.b;

	_g_trans.r = sprite->g_trans.r * r_trans.r + sprite->g_trans.g * g_trans.r + sprite->g_trans.b * b_trans.r;
	_g_trans.g = sprite->g_trans.r * r_trans.g + sprite->g_trans.g * g_trans.g + sprite->g_trans.b * b_trans.g;
	_g_trans.b = sprite->g_trans.r * r_trans.b + sprite->g_trans.g * g_trans.b + sprite->g_trans.b * b_trans.b;

	_b_trans.r = sprite->b_trans.r * r_trans.r + sprite->b_trans.g * g_trans.r + sprite->b_trans.b * b_trans.r;
	_b_trans.g = sprite->b_trans.r * r_trans.g + sprite->b_trans.g * g_trans.g + sprite->b_trans.b * b_trans.g;
	_b_trans.b = sprite->b_trans.r * r_trans.b + sprite->b_trans.g * g_trans.b + sprite->b_trans.b * b_trans.b;

	sprite->GetSymbol().Draw(t, _mul, _add, _r_trans, _g_trans, _b_trans, sprite);

	if (sprite->IsAnchor()) {
		std::vector<Vector> bound;
		sprite->GetBounding()->getBoundPos(bound);
		PrimitiveDraw::drawPolyline(bound, BLACK, true, 4);
		PrimitiveDraw::drawLine(bound[0], bound[2], BLACK, 4);
		PrimitiveDraw::drawLine(bound[1], bound[3], BLACK, 4);
	}
}

void SpriteRenderer::DrawImplBlend(const ISprite* sprite) const
{
//	DrawUnderToTmp(sprite);
 	DrawSprToTmp(sprite);
 	DrawTmpToScreen(sprite);
}

void SpriteRenderer::DrawUnderToTmp(const ISprite* sprite) const
{
	ShaderMgr* mgr = ShaderMgr::Instance();
	FBO& scr_fbo = ScreenFBO::Instance()->GetFBO();

	mgr->sprite();
	mgr->SetFBO(m_fbo->GetFboID());

	mgr->SetBlendMode(BM_NORMAL);

	glClearColor(0, 0, 0, 1);
	glClear(GL_COLOR_BUFFER_BIT);

	// src
	Vector src[4];
	Rect src_rect = sprite->GetRect();
	int scr_w = scr_fbo.GetWidth(),
		scr_h = scr_fbo.GetHeight();
	src[0] = m_cam->transPosProjectToScreen(Vector(src_rect.xMin, src_rect.yMin), scr_w, scr_h);
	src[1] = m_cam->transPosProjectToScreen(Vector(src_rect.xMax, src_rect.yMin), scr_w, scr_h);
	src[2] = m_cam->transPosProjectToScreen(Vector(src_rect.xMax, src_rect.yMax), scr_w, scr_h);
	src[3] = m_cam->transPosProjectToScreen(Vector(src_rect.xMin, src_rect.yMax), scr_w, scr_h);
	for (int i = 0; i < 4; ++i) {
		src[i].y = scr_h - 1 - src[i].y;
		src[i].x /= scr_w;
		src[i].y /= scr_h;
		src[i].x = std::min(std::max(0.0f, src[i].x), 1.0f);
		src[i].y = std::min(std::max(0.0f, src[i].y), 1.0f);
	}

	// dst
	Vector dst[4];
	Rect dst_rect = sprite->GetSymbol().GetSize();
	dst[0] = Vector(dst_rect.xMin, dst_rect.yMin);
	dst[1] = Vector(dst_rect.xMax, dst_rect.yMin);
	dst[2] = Vector(dst_rect.xMax, dst_rect.yMax);
	dst[3] = Vector(dst_rect.xMin, dst_rect.yMax);

	Vector offset;
	float scale;
	mgr->GetModelView(offset, scale);

	mgr->SetModelView(Vector(0, 0), 1);
	Rect r = sprite->GetSymbol().GetSize();
	mgr->SetProjection(r.xLength(), r.yLength());
	glViewport(0, 0, r.xLength(), r.yLength());

	BlendShader* blend_shader = static_cast<BlendShader*>(mgr->GetSpriteShader());
	blend_shader->SetBaseTexID(scr_fbo.GetTexID());
 	blend_shader->DrawBlend(dst, src, src, scr_fbo.GetTexID());

	mgr->Commit();

	mgr->SetModelView(offset, scale);
	mgr->SetProjection(scr_fbo.GetWidth(), scr_fbo.GetHeight());
	glViewport(0, 0, scr_fbo.GetWidth(), scr_fbo.GetHeight());
}

void SpriteRenderer::DrawSprToTmp(const ISprite* sprite) const
{
	ShaderMgr* mgr = ShaderMgr::Instance();
	FBO& scr_fbo = ScreenFBO::Instance()->GetFBO();

	mgr->sprite();
	mgr->SetFBO(m_fbo->GetFboID());

	mgr->SetBlendMode(sprite->GetBlendMode());

	glClearColor(0, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT);

	Vector offset;
	float scale;
	mgr->GetModelView(offset, scale);

	mgr->SetModelView(Vector(0, 0), 1);
	Rect r = sprite->GetSymbol().GetSize();
	mgr->SetProjection(r.xLength(), r.yLength());
	glViewport(0, 0, r.xLength(), r.yLength());

	BlendShader* blend_shader = static_cast<BlendShader*>(mgr->GetSpriteShader());
	blend_shader->SetBaseTexID(scr_fbo.GetTexID());
//	blend_shader->SetBaseTexID(m_fbo->GetTexID());

	sprite->GetSymbol().Draw(Matrix(), sprite->multiCol, sprite->addCol,
		sprite->r_trans, sprite->g_trans, sprite->b_trans, sprite);

	mgr->Commit();

	mgr->SetModelView(offset, scale);
	mgr->SetProjection(scr_fbo.GetWidth(), scr_fbo.GetHeight());
	glViewport(0, 0, scr_fbo.GetWidth(), scr_fbo.GetHeight());
}

void SpriteRenderer::DrawTmpToScreen(const ISprite* sprite) const
{
	ShaderMgr* mgr = ShaderMgr::Instance();
	FBO& scr_fbo = ScreenFBO::Instance()->GetFBO();

	mgr->sprite();
	mgr->SetFBO(0);
	mgr->SetFBO(scr_fbo.GetFboID());

	mgr->SetBlendMode(BM_NORMAL);

	const d2d::Rect& r_dst = sprite->GetRect();
	float xmin = r_dst.xMin, xmax = r_dst.xMax;
	float ymin = r_dst.yMin, ymax = r_dst.yMax;

	d2d::Rect r_src = sprite->GetSymbol().GetSize();
	//  		float txmin = r_src.xMin / m_fbo->GetWidth() + 0.5f,
	//  			txmax = r_src.xMax / m_fbo->GetWidth() + 0.5f;
	//  		float tymin = r_src.yMin / m_fbo->GetHeight() + 0.5f,
	//  			tymax = r_src.yMax / m_fbo->GetHeight() + 0.5f;
	float txmin = 0, txmax = r_src.xLength() / m_fbo->GetWidth();
	float tymin = 0, tymax = r_src.yLength() / m_fbo->GetHeight();
	if (BlendShader* blend_shader = dynamic_cast<BlendShader*>(mgr->GetSpriteShader()))
	{
		const float vertices[] = {
			xmin, ymin, txmin, tymin, txmin, tymin,
			xmin, ymax, txmin, tymax, txmin, tymax,
			xmax, ymax, txmax, tymax, txmax, tymax,
			xmax, ymin, txmax, tymin, txmax, tymin };
		blend_shader->DrawBlend(vertices, m_fbo->GetTexID());
	}
	else
	{
		const float vertices[] = {
			xmin, ymin, txmin, tymin,
			xmin, ymax, txmin, tymax,
			xmax, ymax, txmax, tymax,
			xmax, ymin, txmax, tymin};
		mgr->Draw(vertices, m_fbo->GetTexID());
	}

	mgr->Commit();
}

void SpriteRenderer::InitBlendShader() const
{
	m_fbo = new FBO(600, 600);

	d2d::SpriteShader* blend_shader = new d2d::BlendShader;
	blend_shader->Load();
	m_blend_idx = ShaderMgr::Instance()->AddSpriteShader(blend_shader);
}

SpriteRenderer* SpriteRenderer::Instance()
{
	if (!m_instance) {
		m_instance = new SpriteRenderer();
	}
	return m_instance;
}

} // d2d<commit_msg>[ADDED] anchor draw<commit_after>#include <gl/glew.h>

#include "SpriteRenderer.h"
#include "ShaderMgr.h"
#include "ScreenFBO.h"
#include "BlendShader.h"
#include "FBO.h"

#include "dataset/ISprite.h"
#include "dataset/ISymbol.h"
#include "dataset/AbstractBV.h"
#include "view/Camera.h"
#include "render/LabelNew.h"
#include "render/PrimitiveDraw.h"
#include "common/color_config.h"

namespace d2d
{

SpriteRenderer* SpriteRenderer::m_instance = NULL;

SpriteRenderer::SpriteRenderer()
	: m_fbo(NULL)
	, m_blend_idx(0)
	, m_cam(NULL)
{
}

SpriteRenderer::~SpriteRenderer()
{
	delete m_fbo;
}

void SpriteRenderer::Draw(const ISprite* sprite,
						  const d2d::Matrix& mt,
						  const Colorf& mul,
						  const Colorf& add,
						  const Colorf& r_trans,
						  const Colorf& g_trans,
						  const Colorf& b_trans,
						  bool multi_draw) const
{
	if (!sprite->visiable)
		return;

	if (!multi_draw || sprite->GetBlendMode() == BM_NORMAL) {
		DrawImpl(sprite, mt, mul, add, r_trans, g_trans, b_trans);
	} else {
		if (!m_fbo) {
			InitBlendShader();
		}

		ShaderMgr* mgr = ShaderMgr::Instance();
		mgr->SetSpriteShader(m_blend_idx);

		DrawImplBlend(sprite);

 		mgr->SetSpriteShader(0);
 		mgr->sprite();
		FBO& scr_fbo = ScreenFBO::Instance()->GetFBO();
		mgr->SetFBO(scr_fbo.GetFboID());
	}
}

void SpriteRenderer::Draw(const ISymbol* symbol,
						  const d2d::Matrix& mt,
						  const Vector& pos,
						  float angle/* = 0.0f*/,
						  float xScale/* = 1.0f*/,
						  float yScale/* = 1.0f*/,
						  float xShear/* = 0.0f*/,
						  float yShear/* = 0.0f*/,
						  const Colorf& mul /*= Colorf(1,1,1,1)*/,
						  const Colorf& add /*= Colorf(0,0,0,0)*/,
						  const Colorf& r_trans,
						  const Colorf& g_trans,
						  const Colorf& b_trans) const
{
	Matrix t;
	t.setTransformation(pos.x, pos.y, angle, xScale, yScale, 0, 0, xShear, yShear);
	t = mt * t;
	symbol->Draw(t, mul, add, r_trans, g_trans, b_trans);
}

void SpriteRenderer::DrawName(const std::string& name, float scale, const Matrix& mt) const
{
	if (name.empty() || name[0] == '_') {
		return;
	}

	Vector pos = Math::transVector(Vector(0, 0), mt);

	LabelStyle style;
	style.has_edge = false;
	style.font_size = 20;
	style.width = 200;
	style.height = 50;
	style.color = Colorf(0, 0, 0);
	style.align_hori = HAT_CENTER;
	style.align_vert = VAT_TOP;

	LabelNew::Print(name.c_str(), pos, scale, style);
}

void SpriteRenderer::DrawImpl(const ISprite* sprite,
							  const d2d::Matrix& mt,
							  const Colorf& mul,
							  const Colorf& add,
							  const Colorf& r_trans,
							  const Colorf& g_trans,
							  const Colorf& b_trans) const
{
	Matrix t;
	sprite->GetTransMatrix(t);
	t = mt * t;

	Colorf _mul = cMul(sprite->multiCol, mul),
		_add = cAdd(sprite->addCol, add);

	Colorf _r_trans, _g_trans, _b_trans;

	_r_trans.r = sprite->r_trans.r * r_trans.r + sprite->r_trans.g * g_trans.r + sprite->r_trans.b * b_trans.r;
	_r_trans.g = sprite->r_trans.r * r_trans.g + sprite->r_trans.g * g_trans.g + sprite->r_trans.b * b_trans.g;
	_r_trans.b = sprite->r_trans.r * r_trans.b + sprite->r_trans.g * g_trans.b + sprite->r_trans.b * b_trans.b;

	_g_trans.r = sprite->g_trans.r * r_trans.r + sprite->g_trans.g * g_trans.r + sprite->g_trans.b * b_trans.r;
	_g_trans.g = sprite->g_trans.r * r_trans.g + sprite->g_trans.g * g_trans.g + sprite->g_trans.b * b_trans.g;
	_g_trans.b = sprite->g_trans.r * r_trans.b + sprite->g_trans.g * g_trans.b + sprite->g_trans.b * b_trans.b;

	_b_trans.r = sprite->b_trans.r * r_trans.r + sprite->b_trans.g * g_trans.r + sprite->b_trans.b * b_trans.r;
	_b_trans.g = sprite->b_trans.r * r_trans.g + sprite->b_trans.g * g_trans.g + sprite->b_trans.b * b_trans.g;
	_b_trans.b = sprite->b_trans.r * r_trans.b + sprite->b_trans.g * g_trans.b + sprite->b_trans.b * b_trans.b;

	sprite->GetSymbol().Draw(t, _mul, _add, _r_trans, _g_trans, _b_trans, sprite);

	if (sprite->IsAnchor()) {
		std::vector<Vector> bound;
		sprite->GetBounding()->getBoundPos(bound);
		for (int i = 0, n = bound.size(); i < n; ++i) {
			bound[i] = d2d::Math::transVector(bound[i], t);
		}
		PrimitiveDraw::drawPolyline(bound, BLACK, true, 4);
		PrimitiveDraw::drawLine(bound[0], bound[2], BLACK, 4);
		PrimitiveDraw::drawLine(bound[1], bound[3], BLACK, 4);
	}
}

void SpriteRenderer::DrawImplBlend(const ISprite* sprite) const
{
//	DrawUnderToTmp(sprite);
 	DrawSprToTmp(sprite);
 	DrawTmpToScreen(sprite);
}

void SpriteRenderer::DrawUnderToTmp(const ISprite* sprite) const
{
	ShaderMgr* mgr = ShaderMgr::Instance();
	FBO& scr_fbo = ScreenFBO::Instance()->GetFBO();

	mgr->sprite();
	mgr->SetFBO(m_fbo->GetFboID());

	mgr->SetBlendMode(BM_NORMAL);

	glClearColor(0, 0, 0, 1);
	glClear(GL_COLOR_BUFFER_BIT);

	// src
	Vector src[4];
	Rect src_rect = sprite->GetRect();
	int scr_w = scr_fbo.GetWidth(),
		scr_h = scr_fbo.GetHeight();
	src[0] = m_cam->transPosProjectToScreen(Vector(src_rect.xMin, src_rect.yMin), scr_w, scr_h);
	src[1] = m_cam->transPosProjectToScreen(Vector(src_rect.xMax, src_rect.yMin), scr_w, scr_h);
	src[2] = m_cam->transPosProjectToScreen(Vector(src_rect.xMax, src_rect.yMax), scr_w, scr_h);
	src[3] = m_cam->transPosProjectToScreen(Vector(src_rect.xMin, src_rect.yMax), scr_w, scr_h);
	for (int i = 0; i < 4; ++i) {
		src[i].y = scr_h - 1 - src[i].y;
		src[i].x /= scr_w;
		src[i].y /= scr_h;
		src[i].x = std::min(std::max(0.0f, src[i].x), 1.0f);
		src[i].y = std::min(std::max(0.0f, src[i].y), 1.0f);
	}

	// dst
	Vector dst[4];
	Rect dst_rect = sprite->GetSymbol().GetSize();
	dst[0] = Vector(dst_rect.xMin, dst_rect.yMin);
	dst[1] = Vector(dst_rect.xMax, dst_rect.yMin);
	dst[2] = Vector(dst_rect.xMax, dst_rect.yMax);
	dst[3] = Vector(dst_rect.xMin, dst_rect.yMax);

	Vector offset;
	float scale;
	mgr->GetModelView(offset, scale);

	mgr->SetModelView(Vector(0, 0), 1);
	Rect r = sprite->GetSymbol().GetSize();
	mgr->SetProjection(r.xLength(), r.yLength());
	glViewport(0, 0, r.xLength(), r.yLength());

	BlendShader* blend_shader = static_cast<BlendShader*>(mgr->GetSpriteShader());
	blend_shader->SetBaseTexID(scr_fbo.GetTexID());
 	blend_shader->DrawBlend(dst, src, src, scr_fbo.GetTexID());

	mgr->Commit();

	mgr->SetModelView(offset, scale);
	mgr->SetProjection(scr_fbo.GetWidth(), scr_fbo.GetHeight());
	glViewport(0, 0, scr_fbo.GetWidth(), scr_fbo.GetHeight());
}

void SpriteRenderer::DrawSprToTmp(const ISprite* sprite) const
{
	ShaderMgr* mgr = ShaderMgr::Instance();
	FBO& scr_fbo = ScreenFBO::Instance()->GetFBO();

	mgr->sprite();
	mgr->SetFBO(m_fbo->GetFboID());

	mgr->SetBlendMode(sprite->GetBlendMode());

	glClearColor(0, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT);

	Vector offset;
	float scale;
	mgr->GetModelView(offset, scale);

	mgr->SetModelView(Vector(0, 0), 1);
	Rect r = sprite->GetSymbol().GetSize();
	mgr->SetProjection(r.xLength(), r.yLength());
	glViewport(0, 0, r.xLength(), r.yLength());

	BlendShader* blend_shader = static_cast<BlendShader*>(mgr->GetSpriteShader());
	blend_shader->SetBaseTexID(scr_fbo.GetTexID());
//	blend_shader->SetBaseTexID(m_fbo->GetTexID());

	sprite->GetSymbol().Draw(Matrix(), sprite->multiCol, sprite->addCol,
		sprite->r_trans, sprite->g_trans, sprite->b_trans, sprite);

	mgr->Commit();

	mgr->SetModelView(offset, scale);
	mgr->SetProjection(scr_fbo.GetWidth(), scr_fbo.GetHeight());
	glViewport(0, 0, scr_fbo.GetWidth(), scr_fbo.GetHeight());
}

void SpriteRenderer::DrawTmpToScreen(const ISprite* sprite) const
{
	ShaderMgr* mgr = ShaderMgr::Instance();
	FBO& scr_fbo = ScreenFBO::Instance()->GetFBO();

	mgr->sprite();
	mgr->SetFBO(0);
	mgr->SetFBO(scr_fbo.GetFboID());

	mgr->SetBlendMode(BM_NORMAL);

	const d2d::Rect& r_dst = sprite->GetRect();
	float xmin = r_dst.xMin, xmax = r_dst.xMax;
	float ymin = r_dst.yMin, ymax = r_dst.yMax;

	d2d::Rect r_src = sprite->GetSymbol().GetSize();
	//  		float txmin = r_src.xMin / m_fbo->GetWidth() + 0.5f,
	//  			txmax = r_src.xMax / m_fbo->GetWidth() + 0.5f;
	//  		float tymin = r_src.yMin / m_fbo->GetHeight() + 0.5f,
	//  			tymax = r_src.yMax / m_fbo->GetHeight() + 0.5f;
	float txmin = 0, txmax = r_src.xLength() / m_fbo->GetWidth();
	float tymin = 0, tymax = r_src.yLength() / m_fbo->GetHeight();
	if (BlendShader* blend_shader = dynamic_cast<BlendShader*>(mgr->GetSpriteShader()))
	{
		const float vertices[] = {
			xmin, ymin, txmin, tymin, txmin, tymin,
			xmin, ymax, txmin, tymax, txmin, tymax,
			xmax, ymax, txmax, tymax, txmax, tymax,
			xmax, ymin, txmax, tymin, txmax, tymin };
		blend_shader->DrawBlend(vertices, m_fbo->GetTexID());
	}
	else
	{
		const float vertices[] = {
			xmin, ymin, txmin, tymin,
			xmin, ymax, txmin, tymax,
			xmax, ymax, txmax, tymax,
			xmax, ymin, txmax, tymin};
		mgr->Draw(vertices, m_fbo->GetTexID());
	}

	mgr->Commit();
}

void SpriteRenderer::InitBlendShader() const
{
	m_fbo = new FBO(600, 600);

	d2d::SpriteShader* blend_shader = new d2d::BlendShader;
	blend_shader->Load();
	m_blend_idx = ShaderMgr::Instance()->AddSpriteShader(blend_shader);
}

SpriteRenderer* SpriteRenderer::Instance()
{
	if (!m_instance) {
		m_instance = new SpriteRenderer();
	}
	return m_instance;
}

} // d2d<|endoftext|>


<commit_before>/*
 * $Id$
 *
 * Copyright (c) 2011 Surfnet
 * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation).
 * Copyright (c) 2011 OpenDNSSEC AB (svb)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <ctime>
#include <iostream>
#include <cassert>

#include "enforcer/update_all_cmd.h"
#include "enforcer/setup_cmd.h"
#include "enforcer/autostart_cmd.h"
#include "enforcer/update_conf_task.h"

#include "shared/duration.h"
#include "shared/file.h"
#include "shared/str.h"
#include "daemon/engine.h"
#include "utils/kc_helper.h"

#include "policy/update_kasp_task.h"
#include "policy/kasp.pb.h"

#include "keystate/update_keyzones_task.h"
#include "keystate/keystate.pb.h"

#include "hsmkey/update_hsmkeys_task.h"
#include "hsmkey/hsmkey_gen_task.h"
#include "hsmkey/hsmkey.pb.h"

static const char *module_str = "update_all_cmd";

void help_update_all_cmd(int sockfd)
{
	ods_printf(sockfd,
	           "update all             Perform update kasp, zonelist and repositorylist.\n"
	);
}

static void
flush_all_tasks(int sockfd, engine_type* engine)
{
	ods_log_debug("[%s] flushing all tasks...", module_str);
	ods_printf(sockfd,"flushing all tasks...\n");

	ods_log_assert(engine);
	ods_log_assert(engine->taskq);
	lock_basic_lock(&engine->taskq->schedule_lock);
	/* [LOCK] schedule */
	schedule_flush(engine->taskq, TASK_NONE);
	/* [UNLOCK] schedule */
	lock_basic_unlock(&engine->taskq->schedule_lock);
	engine_wakeup_workers(engine);
}

int
handled_update_all_cmd(int sockfd, engine_type* engine, const char *cmd,
	ssize_t n)
{
	const char *scmd = "update all";
	cmd = ods_check_command(cmd,n,scmd);
	if (!cmd) return 0; // not handled
	ods_log_debug("[%s] %s command", module_str, scmd);

	// check that we are using a compatible protobuf version.
	GOOGLE_PROTOBUF_VERIFY_VERSION;
	time_t tstart = time(NULL);

	autostart(engine);

	/* todo error checking */

	char *kasp = NULL;
	char *zonelist = NULL;
	char **replist = NULL;
	int repcount, i;

	int error = 1;
	if (check_conf(engine->config->cfg_filename, &kasp,
			&zonelist, &replist, &repcount, 0))
		ods_log_error_and_printf(sockfd, module_str,
			"Unable to validate '%s' consistency.",
			engine->config->cfg_filename);
	else if (check_kasp(kasp, replist, repcount, 0))
		ods_log_error_and_printf(sockfd, module_str,
			"Unable to validate '%s' consistency.", kasp);
	else if (check_zonelist(zonelist, 0))
		ods_log_error_and_printf(sockfd, module_str,
			"Unable to validate '%s' consistency.", zonelist);
	else error = 0;

	free(kasp);
	free(zonelist);
	if (replist) {
		for (i = 0; i < repcount; i++) free(replist[i]);
	}

	if (!error) {
		perform_update_conf(sockfd, engine, cmd, n);
		perform_update_kasp(sockfd, engine->config);
		perform_update_keyzones(sockfd, engine->config);
		perform_update_hsmkeys(sockfd, engine->config, 0 /* automatic */);
		perform_hsmkey_gen(sockfd, engine->config, 0 /* automatic */,
						   engine->config->automatic_keygen_duration);
		flush_all_tasks(sockfd, engine);
	}
	ods_printf(sockfd, "%s completed in %ld seconds.\n",scmd,time(NULL)-tstart);
	return 1;
}

<commit_msg>OPENDNSSEC-321 - forgot to commit<commit_after>/*
 * $Id$
 *
 * Copyright (c) 2011 Surfnet
 * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation).
 * Copyright (c) 2011 OpenDNSSEC AB (svb)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <ctime>
#include <iostream>
#include <cassert>

#include "enforcer/update_all_cmd.h"
#include "enforcer/setup_cmd.h"
#include "enforcer/autostart_cmd.h"
#include "enforcer/update_conf_task.h"

#include "shared/duration.h"
#include "shared/file.h"
#include "shared/str.h"
#include "daemon/engine.h"
#include "utils/kc_helper.h"

#include "policy/update_kasp_task.h"
#include "policy/kasp.pb.h"

#include "keystate/update_keyzones_task.h"
#include "keystate/keystate.pb.h"

#include "hsmkey/update_hsmkeys_task.h"
#include "hsmkey/hsmkey_gen_task.h"
#include "hsmkey/hsmkey.pb.h"

static const char *module_str = "update_all_cmd";

void help_update_all_cmd(int sockfd)
{
	ods_printf(sockfd,
	           "update all             Perform update kasp, zonelist and repositorylist.\n"
	);
}

static void
flush_all_tasks(int sockfd, engine_type* engine)
{
	ods_log_debug("[%s] flushing all tasks...", module_str);
	ods_printf(sockfd,"flushing all tasks...\n");

	ods_log_assert(engine);
	ods_log_assert(engine->taskq);
	lock_basic_lock(&engine->taskq->schedule_lock);
	/* [LOCK] schedule */
	schedule_flush(engine->taskq, TASK_NONE);
	/* [UNLOCK] schedule */
	lock_basic_unlock(&engine->taskq->schedule_lock);
	engine_wakeup_workers(engine);
}

int
handled_update_all_cmd(int sockfd, engine_type* engine, const char *cmd,
	ssize_t n)
{
	const char *scmd = "update all";
	cmd = ods_check_command(cmd,n,scmd);
	if (!cmd) return 0; // not handled
	ods_log_debug("[%s] %s command", module_str, scmd);

	// check that we are using a compatible protobuf version.
	GOOGLE_PROTOBUF_VERIFY_VERSION;
	time_t tstart = time(NULL);

	autostart(engine);

	/* Check all files for errors. The perform_update_*()
	 * functions check as well but this gives us all or nothing.
	 * Plus we get a complete check of the files mentioned in the
	 * conf which need not be the same as the files in use by the
	 * running enforcer!*/
	char *kasp = NULL;
	char *zonelist = NULL;
	char **replist = NULL;
	int repcount, i;
	int error = 1;
	if (check_conf(engine->config->cfg_filename, &kasp,
			&zonelist, &replist, &repcount, 0))
		ods_log_error_and_printf(sockfd, module_str,
			"Unable to validate '%s' consistency.",
			engine->config->cfg_filename);
	else if (check_kasp(kasp, replist, repcount, 0))
		ods_log_error_and_printf(sockfd, module_str,
			"Unable to validate '%s' consistency.", kasp);
	else if (check_zonelist(zonelist, 0))
		ods_log_error_and_printf(sockfd, module_str,
			"Unable to validate '%s' consistency.", zonelist);
	else error = 0;

	free(kasp);
	free(zonelist);
	if (replist) {
		for (i = 0; i < repcount; i++) free(replist[i]);
	}

	if (!error)
		error |= perform_update_conf(sockfd, engine, cmd, n);
	if (!error)
		error |= perform_update_kasp(sockfd, engine->config);
	if (!error)
		error |= perform_update_keyzones(sockfd, engine->config);
	if (!error) {
		perform_update_hsmkeys(sockfd, engine->config, 0 /* automatic */);
		perform_hsmkey_gen(sockfd, engine->config, 0 /* automatic */,
						   engine->config->automatic_keygen_duration);
		flush_all_tasks(sockfd, engine);
	}
	ods_printf(sockfd, "%s completed in %ld seconds.\n",scmd,time(NULL)-tstart);
	return 1;
}

<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	GUI widget スピン・ボックス・クラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/glfw_app/blob/master/LICENSE
*/
//=====================================================================//
#include "widgets/widget_director.hpp"
#include "widgets/widget_utils.hpp"

namespace gui {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	GUI widget_spinbox クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct widget_spinbox : public widget {

		typedef widget_spinbox value_type;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	widget_spinbox ステート
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class state {
			initial,///< 初期化
			inc,	///< インクリメント
			select,	///< セレクト
			dec,	///< デクリメント
			none	///< 何もしない
		};

		typedef std::function< std::string (state st, int before, int newpos) > select_func_type;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	widget_spinbox パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct param {
			plate_param		plate_param_;
			color_param		color_param_;	///< 頂点カラーで変調する場合のパラメーター
			text_param		text_param_;	///< テキスト描画のパラメータ
			const img::i_img*	image_;		///< 画像を使う場合
			gl::mobj::handle	handle_;	///< モーションオブジェクトを使う場合
			uint32_t			id_;		///< セレクト ID （押された回数）

			select_func_type	select_func_;	///< 選択関数

			int					min_pos_;	///< 最低位置
			int					sel_pos_;	///< 選択位置
			int					max_pos_;	///< 最大位置
			int					page_step_;	///< ページ移動量

			bool				scroll_ctrl_;	///< スクロール・コントロール（マウスのダイアル）
			bool				accel_;			///< ボタンのアクセル・コントロール
			uint16_t			accel_delay_;	///< アクセルが利くまでの遅延
			uint16_t			accel_inter_;	///< アクセル時のインターバル（速度）

			param(int min = 0, int sel = 0, int max = 0) :
				plate_param_(), color_param_(widget_director::default_spinbox_color_),
				text_param_("", img::rgba8(255, 255), img::rgba8(0, 255)),
				image_(0), handle_(0), id_(0),
				select_func_(),
				min_pos_(min), sel_pos_(sel), max_pos_(max), page_step_((max - min) / 10),
				scroll_ctrl_(true),
				accel_(true), accel_delay_(35), accel_inter_(10)
				{ }
		};

	private:
		widget_director&	wd_;

		param				param_;

		gl::mobj::handle	objh_;
		gl::mobj::handle	up_objh_;
		gl::mobj::handle	dn_objh_;

		bool	initial_;

		uint16_t	delay_cnt_;

		state get_button_state_(int& d) const
		{
			state st = state::none;
			auto x = get_param().in_point_.x;
			auto xs = get_rect().size.x;
			if(x < (xs / 3)) {  // inc
				d = 1;
				st = state::inc;
			} else if(x >= (xs * 2 / 3)) {  // dec
				d = -1;
				st = state::dec;
			} else {
				st = state::select;
			}
			return st;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-----------------------------------------------------------------//
		widget_spinbox(widget_director& wd, const widget::param& bp, const param& p) :
			widget(bp), wd_(wd), param_(p), objh_(0), up_objh_(0), dn_objh_(0),
		    initial_(false), delay_cnt_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-----------------------------------------------------------------//
		virtual ~widget_spinbox() { }

		//-----------------------------------------------------------------//
		/*!
			@brief	型を取得
		*/
		//-----------------------------------------------------------------//
		type_id type() const override { return get_type_id<value_type>(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	widget 型の基本名称を取得
			@return widget 型の基本名称
		*/
		//-----------------------------------------------------------------//
		const char* type_name() const override { return "spinbox"; }

		//-----------------------------------------------------------------//
		/*!
			@brief	ハイブリッド・ウィジェットのサイン
			@return ハイブリッド・ウィジェットの場合「true」を返す。
		*/
		//-----------------------------------------------------------------//
		bool hybrid() const override { return true; }

		//-----------------------------------------------------------------//
		/*!
			@brief	個別パラメーターへの取得(ro)
			@return 個別パラメーター
		*/
		//-----------------------------------------------------------------//
		const param& get_local_param() const { return param_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	個別パラメーターへの取得
			@return 個別パラメーター
		*/
		//-----------------------------------------------------------------//
		param& at_local_param() { return param_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択テキストの取得
			@return 選択テキスト
		*/
		//-----------------------------------------------------------------//
		std::string get_select_text() const { return param_.text_param_.get_text(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択位置の取得
			@return 選択位置
		*/
		//-----------------------------------------------------------------//
		uint32_t get_select_pos() const { return param_.sel_pos_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	初期化
		*/
		//-----------------------------------------------------------------//
		void initialize() override
		{
			// ボタンは標準的に固定、サイズ固定、選択時拡大
			at_param().state_.set(widget::state::SERVICE);
			at_param().state_.set(widget::state::POSITION_LOCK);
			at_param().state_.set(widget::state::SIZE_LOCK);
			at_param().state_.set(widget::state::MOVE_STALL);
			at_param().action_.set(widget::action::SELECT_SCALE);

			using namespace img;

			if(param_.handle_) {
				at_rect().size = wd_.at_mobj().get_size(param_.handle_);
				objh_ = param_.handle_;
			} else if(param_.image_) {
				paint pa;
				const vtx::spos& size = get_rect().size;
				create_image_base(param_.image_, size, pa);
				at_rect().size = pa.get_size();
				objh_ = wd_.at_mobj().install(&pa);
			} else {
				vtx::spos size;
				if(param_.plate_param_.resizeble_) {
					vtx::spos rsz = param_.plate_param_.grid_ * 3;
					if(get_param().rect_.size.x >= rsz.x) size.x = rsz.x;
					else size.x = get_param().rect_.size.x;
					if(get_param().rect_.size.y >= rsz.y) size.y = rsz.y;
					else size.y = get_param().rect_.size.y;
				} else {
					size = get_param().rect_.size;
				}
				share_t t;
				t.size_ = size;
				t.color_param_ = param_.color_param_;
				t.plate_param_ = param_.plate_param_;
				objh_ = wd_.share_add(t);
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	アップデート
		*/
		//-----------------------------------------------------------------//
		void update() override
		{
			if(!initial_ && param_.select_func_ != nullptr) {
				initial_ = true;
				auto t = param_.select_func_(state::initial, param_.sel_pos_, param_.sel_pos_);
				if(!t.empty()) {
					param_.text_param_.set_text(t);
				}
			}

			state st = state::none;
			int d = 0;
			if(get_selected()) {
				st = get_button_state_(d);
				delay_cnt_ = 0;
			} else if(get_focus() && param_.scroll_ctrl_) {
				if(get_select()) {
					st = get_button_state_(d);
					if(st == state::inc || st == state::dec) {
						++delay_cnt_;
						if(delay_cnt_ >= param_.accel_delay_) {
							if(delay_cnt_ > param_.accel_inter_) {
								delay_cnt_ -= param_.accel_inter_;
							} else {
								delay_cnt_ = 0;
							}
						} else {
							st = state::none;
						}
					}
				} else {
					delay_cnt_ = 0;
					const vtx::spos& scr = wd_.get_scroll();
					if(scr.y != 0) {
						d = -scr.y;
						if(d > 0) st = state::inc;
						else if(d < 0) st = state::dec;
					}
				}
			}
#if 0
			if(get_focus()) {
				const utils::lstring& ins = wd_.get_keyboard().input();
				for(uint32_t ch : ins) {
// std::cout << "Key: " << ch << std::endl;
				}
			}
#endif
			if(st != state::none) {
				int before = param_.sel_pos_;
				++param_.id_;
				if(d > 0) {
					param_.sel_pos_ += d;
					if(param_.sel_pos_ > param_.max_pos_) param_.sel_pos_ = param_.max_pos_;
					st = state::inc;
				} else if(d < 0) {
					param_.sel_pos_ += d;
					if(param_.sel_pos_ < param_.min_pos_) param_.sel_pos_ = param_.min_pos_;
					st = state::dec;
				}
				if(param_.select_func_ != nullptr) {
					auto t = param_.select_func_(st, before, param_.sel_pos_);
					if(!t.empty()) {
						param_.text_param_.set_text(t);
					}
				}
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	サービス
		*/
		//-----------------------------------------------------------------//
		void service() override { }

		//-----------------------------------------------------------------//
		/*!
			@brief	レンダリング
		*/
		//-----------------------------------------------------------------//
		void render() override
		{
			if(objh_ == 0) return;

			using namespace gl;

			core& core = core::get_instance();
			const vtx::spos& siz = core.get_rect().size;

			if(param_.plate_param_.resizeble_) {
				wd_.at_mobj().resize(objh_, get_param().rect_.size);
			}

			render_text(wd_, objh_, get_param(), param_.text_param_, param_.plate_param_);

			// チップの描画
			wd_.at_mobj().setup_matrix(siz.x, siz.y);
			wd_.set_TSC();

			gl::mobj::handle uph = wd_.get_share_image().up_box_;
			gl::mobj::handle dnh = wd_.get_share_image().down_box_;
			const vtx::spos& bs = wd_.at_mobj().get_size(uph);
			const vtx::spos& size = get_rect().size;
			short wf = param_.plate_param_.frame_width_;
			short space = 2;
			vtx::spos pos(size.x - bs.x - wf - space, (size.y - bs.y) / 2);
			wd_.at_mobj().draw(dnh, gl::mobj::attribute::normal, pos);
			pos.x = wf + space;
			wd_.at_mobj().draw(uph, gl::mobj::attribute::normal, pos);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	状態のセーブ
			@param[in]	pre	プリファレンス参照
			@return エラーが無い場合「true」
		*/
		//-----------------------------------------------------------------//
		bool save(sys::preference& pre) override {
			std::string path;
			path += '/';
			path += wd_.create_widget_name(this);

			int err = 0;
			if(!pre.put_integer(path + "/selector", param_.sel_pos_)) ++err;
			return err == 0;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	状態のロード
			@param[in]	pre	プリファレンス参照
			@return エラーが無い場合「true」
		*/
		//-----------------------------------------------------------------//
		bool load(const sys::preference& pre) override {
			std::string path;
			path += '/';
			path += wd_.create_widget_name(this);

			int err = 0;
			if(!pre.get_integer(path + "/selector", param_.sel_pos_)) ++err;
			return err == 0;
		}
	};

}
<commit_msg>update: page key<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	GUI widget スピン・ボックス・クラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/glfw_app/blob/master/LICENSE
*/
//=====================================================================//
#include "widgets/widget_director.hpp"
#include "widgets/widget_utils.hpp"

namespace gui {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	GUI widget_spinbox クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct widget_spinbox : public widget {

		typedef widget_spinbox value_type;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	widget_spinbox ステート
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class state {
			initial,///< 初期化
			inc,	///< インクリメント
			select,	///< セレクト
			dec,	///< デクリメント
			none	///< 何もしない
		};

		typedef std::function< std::string (state st, int before, int newpos) > select_func_type;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	widget_spinbox パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct param {
			plate_param		plate_param_;
			color_param		color_param_;	///< 頂点カラーで変調する場合のパラメーター
			text_param		text_param_;	///< テキスト描画のパラメータ
			const img::i_img*	image_;		///< 画像を使う場合
			gl::mobj::handle	handle_;	///< モーションオブジェクトを使う場合
			uint32_t			id_;		///< セレクト ID （押された回数）

			select_func_type	select_func_;	///< 選択関数

			int					min_pos_;	///< 最低位置
			int					sel_pos_;	///< 選択位置
			int					max_pos_;	///< 最大位置
			int					page_div_;	///< ページ移動分割数
			int					page_step_;	///< ページ移動数(page_div_ が０の場合）

			bool				scroll_ctrl_;	///< スクロール・コントロール（マウスのダイアル）
			bool				accel_;			///< ボタンのアクセル・コントロール
			uint16_t			accel_delay_;	///< アクセルが利くまでの遅延
			uint16_t			accel_inter_;	///< アクセル時のインターバル（速度）

			param(int min = 0, int sel = 0, int max = 0) :
				plate_param_(), color_param_(widget_director::default_spinbox_color_),
				text_param_("", img::rgba8(255, 255), img::rgba8(0, 255)),
				image_(0), handle_(0), id_(0),
				select_func_(),
				min_pos_(min), sel_pos_(sel), max_pos_(max),
				page_div_(0), page_step_((max - min) / 10),
				scroll_ctrl_(true),
				accel_(true), accel_delay_(35), accel_inter_(10)
				{ }
		};

	private:
		widget_director&	wd_;

		param				param_;

		gl::mobj::handle	objh_;
		gl::mobj::handle	up_objh_;
		gl::mobj::handle	dn_objh_;

		bool		initial_;

		uint16_t	delay_cnt_;

		int			sel_pos_;

		state get_button_state_(int& d) const
		{
			state st = state::none;
			auto x = get_param().in_point_.x;
			auto xs = get_rect().size.x;
			if(x < (xs / 3)) {  // inc
				d = 1;
				st = state::inc;
			} else if(x >= (xs * 2 / 3)) {  // dec
				d = -1;
				st = state::dec;
			} else {
				st = state::select;
			}
			return st;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-----------------------------------------------------------------//
		widget_spinbox(widget_director& wd, const widget::param& bp, const param& p) :
			widget(bp), wd_(wd), param_(p), objh_(0), up_objh_(0), dn_objh_(0),
		    initial_(false), delay_cnt_(0), sel_pos_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-----------------------------------------------------------------//
		virtual ~widget_spinbox() { }

		//-----------------------------------------------------------------//
		/*!
			@brief	型を取得
		*/
		//-----------------------------------------------------------------//
		type_id type() const override { return get_type_id<value_type>(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	widget 型の基本名称を取得
			@return widget 型の基本名称
		*/
		//-----------------------------------------------------------------//
		const char* type_name() const override { return "spinbox"; }

		//-----------------------------------------------------------------//
		/*!
			@brief	ハイブリッド・ウィジェットのサイン
			@return ハイブリッド・ウィジェットの場合「true」を返す。
		*/
		//-----------------------------------------------------------------//
		bool hybrid() const override { return true; }

		//-----------------------------------------------------------------//
		/*!
			@brief	個別パラメーターへの取得(ro)
			@return 個別パラメーター
		*/
		//-----------------------------------------------------------------//
		const param& get_local_param() const { return param_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	個別パラメーターへの取得
			@return 個別パラメーター
		*/
		//-----------------------------------------------------------------//
		param& at_local_param() { return param_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択テキストの取得
			@return 選択テキスト
		*/
		//-----------------------------------------------------------------//
		std::string get_select_text() const { return param_.text_param_.get_text(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択位置の取得
			@return 選択位置
		*/
		//-----------------------------------------------------------------//
		int get_select_pos() const { return param_.sel_pos_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択位置の設定
			@param[in]	pos	設定位置
		*/
		//-----------------------------------------------------------------//
		void set_select_pos(int pos) {
			if(param_.min_pos_ <= pos && pos <= param_.max_pos_) {
				param_.sel_pos_ = pos;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	初期化
		*/
		//-----------------------------------------------------------------//
		void initialize() override
		{
			// ボタンは標準的に固定、サイズ固定、選択時拡大
			at_param().state_.set(widget::state::SERVICE);
			at_param().state_.set(widget::state::POSITION_LOCK);
			at_param().state_.set(widget::state::SIZE_LOCK);
			at_param().state_.set(widget::state::MOVE_STALL);
			at_param().action_.set(widget::action::SELECT_SCALE);

			using namespace img;

			if(param_.handle_) {
				at_rect().size = wd_.at_mobj().get_size(param_.handle_);
				objh_ = param_.handle_;
			} else if(param_.image_) {
				paint pa;
				const vtx::spos& size = get_rect().size;
				create_image_base(param_.image_, size, pa);
				at_rect().size = pa.get_size();
				objh_ = wd_.at_mobj().install(&pa);
			} else {
				vtx::spos size;
				if(param_.plate_param_.resizeble_) {
					vtx::spos rsz = param_.plate_param_.grid_ * 3;
					if(get_param().rect_.size.x >= rsz.x) size.x = rsz.x;
					else size.x = get_param().rect_.size.x;
					if(get_param().rect_.size.y >= rsz.y) size.y = rsz.y;
					else size.y = get_param().rect_.size.y;
				} else {
					size = get_param().rect_.size;
				}
				share_t t;
				t.size_ = size;
				t.color_param_ = param_.color_param_;
				t.plate_param_ = param_.plate_param_;
				objh_ = wd_.share_add(t);
			}

			sel_pos_ = param_.sel_pos_;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	アップデート
		*/
		//-----------------------------------------------------------------//
		void update() override
		{
			if(!initial_ && param_.select_func_ != nullptr) {
				initial_ = true;
				auto t = param_.select_func_(state::initial, param_.sel_pos_, param_.sel_pos_);
				if(!t.empty()) {
					param_.text_param_.set_text(t);
				}
			}

			state st = state::none;
			int d = 0;
			if(get_selected()) {
				st = get_button_state_(d);
				delay_cnt_ = 0;
			} else if(get_focus() && param_.scroll_ctrl_) {
				if(get_select()) {
					st = get_button_state_(d);
					if(st == state::inc || st == state::dec) {
						++delay_cnt_;
						if(delay_cnt_ >= param_.accel_delay_) {
							if(delay_cnt_ > param_.accel_inter_) {
								delay_cnt_ -= param_.accel_inter_;
							} else {
								delay_cnt_ = 0;
							}
						} else {
							st = state::none;
						}
					}
				} else {
					delay_cnt_ = 0;
					const vtx::spos& scr = wd_.get_scroll();
					if(scr.y != 0) {
						d = -scr.y;
						if(d > 0) st = state::inc;
						else if(d < 0) st = state::dec;
					}
				}
			}

			if(get_focus()) {
				gl::core& core = gl::core::get_instance();
				const gl::device& dev = core.get_device();
				int step = param_.page_step_;
				if(param_.page_div_ != 0) {
					step = (param_.max_pos_ - param_.min_pos_) / param_.page_div_;
				}
				if(dev.get_positive(gl::device::key::PAGE_UP)) {
					d =  step;
					st = state::inc;
				} else if(dev.get_positive(gl::device::key::PAGE_DOWN)) {
					d = -step;
					st = state::dec;
				}
			}

			if(st != state::none || sel_pos_ != param_.sel_pos_) {
				++param_.id_;
				if(d > 0) {
					param_.sel_pos_ += d;
					if(param_.sel_pos_ > param_.max_pos_) param_.sel_pos_ = param_.max_pos_;
					st = state::inc;
				} else if(d < 0) {
					param_.sel_pos_ += d;
					if(param_.sel_pos_ < param_.min_pos_) param_.sel_pos_ = param_.min_pos_;
					st = state::dec;
				}
				if(param_.select_func_ != nullptr) {
					auto t = param_.select_func_(st, sel_pos_, param_.sel_pos_);
					if(!t.empty()) {
						param_.text_param_.set_text(t);
					}
				}
				sel_pos_ = param_.sel_pos_;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	サービス
		*/
		//-----------------------------------------------------------------//
		void service() override { }

		//-----------------------------------------------------------------//
		/*!
			@brief	レンダリング
		*/
		//-----------------------------------------------------------------//
		void render() override
		{
			if(objh_ == 0) return;

			using namespace gl;

			core& core = core::get_instance();
			const vtx::spos& siz = core.get_rect().size;

			if(param_.plate_param_.resizeble_) {
				wd_.at_mobj().resize(objh_, get_param().rect_.size);
			}

			render_text(wd_, objh_, get_param(), param_.text_param_, param_.plate_param_);

			// チップの描画
			wd_.at_mobj().setup_matrix(siz.x, siz.y);
			wd_.set_TSC();

			gl::mobj::handle uph = wd_.get_share_image().up_box_;
			gl::mobj::handle dnh = wd_.get_share_image().down_box_;
			const vtx::spos& bs = wd_.at_mobj().get_size(uph);
			const vtx::spos& size = get_rect().size;
			short wf = param_.plate_param_.frame_width_;
			short space = 2;
			vtx::spos pos(size.x - bs.x - wf - space, (size.y - bs.y) / 2);
			wd_.at_mobj().draw(dnh, gl::mobj::attribute::normal, pos);
			pos.x = wf + space;
			wd_.at_mobj().draw(uph, gl::mobj::attribute::normal, pos);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	状態のセーブ
			@param[in]	pre	プリファレンス参照
			@return エラーが無い場合「true」
		*/
		//-----------------------------------------------------------------//
		bool save(sys::preference& pre) override {
			std::string path;
			path += '/';
			path += wd_.create_widget_name(this);

			int err = 0;
			if(!pre.put_integer(path + "/selector", param_.sel_pos_)) ++err;
			return err == 0;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	状態のロード
			@param[in]	pre	プリファレンス参照
			@return エラーが無い場合「true」
		*/
		//-----------------------------------------------------------------//
		bool load(const sys::preference& pre) override {
			std::string path;
			path += '/';
			path += wd_.create_widget_name(this);

			int err = 0;
			if(!pre.get_integer(path + "/selector", param_.sel_pos_)) ++err;
			return err == 0;
		}
	};

}
<|endoftext|>


<commit_before>//
//  OptimalLinkList.cpp
//  DataStruct
//
//  Created by guyuexing on 2017/5/22.
//  Copyright © 2017年 neu. All rights reserved.
//

#include "OptimalLinkList.hpp"

//分配由p指向的值为e的结点，并返回OK，若分配失败，则返回error
Status MakeNode(Link &p, ElemType e){
    p = (Link)malloc(sizeof(LNode));
    if (!p) {
        return ERROR;
    }
    p->data = e;
    return OK;
}

//释放p所指结点
void FreeNode(Link &p){
    free(p);
    p = NULL;
}

//构造一个空的线性链表L
Status InitList(LinkList &L){
    //生成头结点
    Link p = (Link)malloc(sizeof(LNode));
    if (!p) {
        return ERROR;
    }
    p->data = NULL;
    p->next = NULL;
    L.header = L.tail = p;
    L.len = 0;
    return OK;
}

//清空线性链表L，并释放原链表的结点空间
Status ClearList(LinkList &L){
    //如果不是空表
    if (L.header!=L.tail) {
        Link p,q;
        //p，q均指向链表的第一个结点
        p = q = L.header->next;
        //将链表L的第一个结点置为空
        L.header->next = NULL;
        while (p!=L.tail) {
            q = p->next;
            free(p);
            p = q;
        }
        //释放最后一个结点
        free(L.tail);
        //头结点和尾结点均指向头结点
        L.tail = L.header;
        L.len = 0;
    }
    return OK;
}

//销毁线性链表L
Status DestoryList(LinkList &L){
    ClearList(L);
    FreeNode(L.header);
    L.tail = NULL;
    L.len = 0;
    return OK;
}

//已知h指向线性链表的头结点，将s所指结点插入在原第一个结点之前（即s成为第一个结点）
Status InsFirst(LinkList &L, Link s, Link h){
    //p指向原来的第一个节点
    Link p = h->next;
    h->next = s;
    s->next = p;
    if (h == L.tail) { //说明原链表为空表，头指针和尾指针均指向头结点；如果不相等，即使插入结点（只要不是插到链表尾部），也不需要移动尾指针
        L.tail = h->next;
    }
    L.len++;
    return OK;
}

//已知h指向线性链表的头结点，删除链表中的第一个结点并以q返回
Status DelFirst(LinkList &L, Link h, Link &q){
    q = h->next;
    //如果q存在，即链表非空
    if (q) {
        h->next = q->next;
        //即删除第一个结点之后判断表是否为空
        if (!h->next) {
            //如果表为空，修改尾指针
            L.tail = h;
        }
        L.len--;
        return OK;
    }else{
        return FALSE;
    }
}

//将指针s(s->data为第一个数据元素)所指(彼此以指针相链接，以NULL结尾)的一串结点链接在链表L的最后一个结点之后，并改变链表L的尾指针指向新的尾结点
Status Append(LinkList &L, Link s){
    Link p = s;
    int i = 1;
    //这段循环目的是为了找到s的最后一个结点
    while (p->next) {
        i++;
        p = p->next;
    }
    L.tail->next = s;
    //L的尾结点指向s的最后一个结点
    L.tail = p;
    L.len += i;
    return OK;
}

//已知p指向线性链表L中的一个结点，返回p所指结点的直接前驱的位置，若无前驱，则返回NULL
Position PriorPos(LinkList L, Link p){
    //如果p是链表L的第一个节点，无前驱
    if (p==L.header->next) {
        return NULL;
    }
    Link q = L.header->next;
    while (q->next!=L.tail) {
        if (q->next == p) {
            return q;
        }
        q = q->next;
    }
    return NULL;
}

//删除线性表L中的尾结点并以q返回，改变链表L的尾指针指向新的尾结点
Status Remove(LinkList &L, Link &q){
    //如果L为空表
    if (L.len == 0) {
        q = NULL;
        return FALSE;
    }
    //p指向L的第一个结点
    Link p = L.header->next;
    //for循环找到链表L尾结点的前一个结点
    while (p->next!=L.tail) {
        p = p->next;
    }
    q = L.tail;
    p->next = NULL;
    L.tail = p;
    L.len--;
    return OK;
}

//已知p指向线性链表L中的一个节点，将s所指节点插入在p所指节点之前，并修改指针p指向新插入的结点
Status InsBefore(LinkList &L, Link &p, Link s){
    //q是p节点的前驱
    Link q = PriorPos(L, p);
    //如果p节点没有前驱，则q指向链表L的头结点
    if (!q) {
        q = L.header;
    }
    //插入s节点
    q->next = s;
    s->next = p;
    p = s;
    L.len++;
    return OK;
}

//已知p指向线性链表L中的一个结点，将s所指结点插入在p所指节点之后，并修改指针p指向新插入的结点
Status InsAfter(LinkList &L, Link &p, Link s){
    s->next = p->next;
    p->next = s;
    if (p==L.tail) { //修改尾指针
        L.tail = s;
    }
    p = s;
    L.len++;
    return OK;
}

//已知p指向线性链表的一个结点，用e更新p指向结点的数据元素的值
Status SetCurElem(Link p, ElemType e){
    p->data = e;
    return OK;
}

//已知p指向线性链表的一个结点，返回结点的数据元素的值
ElemType GetCurElem(Link p){
    return p->data;
}

//若线性链表为空表返回True，否则返回False
Status ListEmpty(LinkList L){
    if (!L.len) {
        return TRUE;
    }else{
        return FALSE;
    }
}

//返回线性链表的元素个数
int ListLength(LinkList L){
    return L.len;
}

//返回线性链表头结点的位置
Position GetHeader(LinkList L){
    return L.header;
}

//返回线性链表最后一个结点的位置
Position GetLast(LinkList L){
    return L.tail;
}

//已知p指向线性链表中的一个结点，返回p所指向结点的直接后继，若无直接后继，则返回NULL
Position NextPos(Link p){
    return p->next;
}

//用p返回线性链表L中第i个结点的位置，并返回OK，如果i值不合法则返回error
Status LocatePos(LinkList L, int i, Link &p){
    if (i<1 || i>ListLength(L)) {
        return ERROR;
    }
    Link q = L.header;
    int j = 0;
    while (j<i && q!=NULL) {
        j++;
        q = q->next;
    }
    if (j>i || j>ListLength(L)) {
        return ERROR;
    }
    p = q;
    return OK;
}

//返回线性链表L中第一个与e满足compare判定关系的结点的位置，若不存在这样的元素，则返回NULL
Position LocateElem(LinkList L, ElemType e, Status (*compare)(ElemType e1, ElemType e2)){
    Link p = L.header->next;
    while (p!=NULL) {
        if (compare(p->data,e)) {
            return p;
        }
        p = p->next;
    }
    return NULL;
}

//依次对L中的每个调用数据元素调用visit函数。一旦visit失败，则操作失败
Status ListTraverse(LinkList L, void (*visit)(ElemType e)){
    Link p = L.header->next;
    while (p!=NULL) {
        visit(p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
}

//已知L为有序线性链表，将e元素按非降序插入在L中（用于一元多项式）
Status OrderInsert(LinkList &L, ElemType e, Status (*compare)(ElemType, ElemType)){
    Link p = L.header->next;
    Link q = L.header; //q用来表示p的前驱
    while (p!=NULL) { //之所以用p!=NULL作为循环结束条件，是为了让e能与链表L的最后一个结点元素值做比较

        //比较p指向结点的数据与e的大小，当p->data第一次大于等于e时，e即插入在p的前驱和p之间
        if (compare(p->data,e)>=0) {
            break;
        }
        q = p;
        p = p->next;
    }
    Link s = (Link)malloc(sizeof(LNode));
    s->data = e;
    q->next = s;
    s->next = p;
    //如果p等于NULL说明遍历到最后也没有找到比e大的值，因此e所在结点是表尾，修改表尾指针
    if (p==NULL) {
        L.tail = s;
    }
    L.len++;
    return OK;
}

//若升序链表L中存在与e满足判定函数compare取值为0的元素，则p返回L中第一个值为e的结点的位置，并返回true；否则p指示第一个与e满足判定函数compare>0的元素的前驱的位置，并返回false（用于一元多项式）
Status LocatElem(LinkList L, ElemType e, Position &p, int(*compare)(ElemType, ElemType)){
//    Link q = L.header->next;
//    Link s = L.header;
//    while (!q) {
//        if (compare(q->data,e)==0) {
//            p = q;
//            return OK;
//        }else if (compare(q->data,e)>0){
//            p = s;
//            return FALSE;
//        }
//        s = q;
//        q = q->next;
//    }
    Link q = L.header;
    Link s;
    do {
        s = q;
        q = q->next;
    } while (q && compare(q->data,e)<0); //循环结束后q可能到了表尾，也可能是compare(q->data,e)>=0
    if (!q||compare(q->data,e)>0) {
        p = s;
        return FALSE;
    }else{
        p = q;
        return TRUE;
    }
}

<commit_msg>fix bug，能循环遍历到最后一个数据元素<commit_after>//
//  OptimalLinkList.cpp
//  DataStruct
//
//  Created by guyuexing on 2017/5/22.
//  Copyright © 2017年 neu. All rights reserved.
//

#include "OptimalLinkList.hpp"

//分配由p指向的值为e的结点，并返回OK，若分配失败，则返回error
Status MakeNode(Link &p, ElemType e){
    p = (Link)malloc(sizeof(LNode));
    if (!p) {
        return ERROR;
    }
    p->data = e;
    return OK;
}

//释放p所指结点
void FreeNode(Link &p){
    free(p);
    p = NULL;
}

//构造一个空的线性链表L
Status InitList(LinkList &L){
    //生成头结点
    Link p = (Link)malloc(sizeof(LNode));
    if (!p) {
        return ERROR;
    }
    p->data = NULL;
    p->next = NULL;
    L.header = L.tail = p;
    L.len = 0;
    return OK;
}

//清空线性链表L，并释放原链表的结点空间
Status ClearList(LinkList &L){
    //如果不是空表
    if (L.header!=L.tail) {
        Link p,q;
        //p，q均指向链表的第一个结点
        p = q = L.header->next;
        //将链表L的第一个结点置为空
        L.header->next = NULL;
        while (p!=L.tail) {
            q = p->next;
            free(p);
            p = q;
        }
        //释放最后一个结点
        free(L.tail);
        //头结点和尾结点均指向头结点
        L.tail = L.header;
        L.len = 0;
    }
    return OK;
}

//销毁线性链表L
Status DestoryList(LinkList &L){
    ClearList(L);
    FreeNode(L.header);
    L.tail = NULL;
    L.len = 0;
    return OK;
}

//已知h指向线性链表的头结点，将s所指结点插入在原第一个结点之前（即s成为第一个结点）
Status InsFirst(LinkList &L, Link s, Link h){
    //p指向原来的第一个节点
    Link p = h->next;
    h->next = s;
    s->next = p;
    if (h == L.tail) { //说明原链表为空表，头指针和尾指针均指向头结点；如果不相等，即使插入结点（只要不是插到链表尾部），也不需要移动尾指针
        L.tail = h->next;
    }
    L.len++;
    return OK;
}

//已知h指向线性链表的头结点，删除链表中的第一个结点并以q返回
Status DelFirst(LinkList &L, Link h, Link &q){
    q = h->next;
    //如果q存在，即链表非空
    if (q) {
        h->next = q->next;
        //即删除第一个结点之后判断表是否为空
        if (!h->next) {
            //如果表为空，修改尾指针
            L.tail = h;
        }
        L.len--;
        return OK;
    }else{
        return FALSE;
    }
}

//将指针s(s->data为第一个数据元素)所指(彼此以指针相链接，以NULL结尾)的一串结点链接在链表L的最后一个结点之后，并改变链表L的尾指针指向新的尾结点
Status Append(LinkList &L, Link s){
    Link p = s;
    int i = 1;
    //这段循环目的是为了找到s的最后一个结点
    while (p->next) {
        i++;
        p = p->next;
    }
    L.tail->next = s;
    //L的尾结点指向s的最后一个结点
    L.tail = p;
    L.len += i;
    return OK;
}

//已知p指向线性链表L中的一个结点，返回p所指结点的直接前驱的位置，若无前驱，则返回NULL
Position PriorPos(LinkList L, Link p){
    //如果p是链表L的第一个节点，无前驱
    if (p==L.header->next) {
        return NULL;
    }
    Link q = L.header->next;
    while (q->next) {
        if (q->next == p) {
            return q;
        }
        q = q->next;
    }
    return NULL;
}

//删除线性表L中的尾结点并以q返回，改变链表L的尾指针指向新的尾结点
Status Remove(LinkList &L, Link &q){
    //如果L为空表
    if (L.len == 0) {
        q = NULL;
        return FALSE;
    }
    //p指向L的第一个结点
    Link p = L.header->next;
    //for循环找到链表L尾结点的前一个结点
    while (p->next!=L.tail) {
        p = p->next;
    }
    q = L.tail;
    p->next = NULL;
    L.tail = p;
    L.len--;
    return OK;
}

//已知p指向线性链表L中的一个节点，将s所指节点插入在p所指节点之前，并修改指针p指向新插入的结点
Status InsBefore(LinkList &L, Link &p, Link s){
    //q是p节点的前驱
    Link q = PriorPos(L, p);
    //如果p节点没有前驱，则q指向链表L的头结点
    if (!q) {
        q = L.header;
    }
    //插入s节点
    q->next = s;
    s->next = p;
    p = s;
    L.len++;
    return OK;
}

//已知p指向线性链表L中的一个结点，将s所指结点插入在p所指节点之后，并修改指针p指向新插入的结点
Status InsAfter(LinkList &L, Link &p, Link s){
    s->next = p->next;
    p->next = s;
    if (p==L.tail) { //修改尾指针
        L.tail = s;
    }
    p = s;
    L.len++;
    return OK;
}

//已知p指向线性链表的一个结点，用e更新p指向结点的数据元素的值
Status SetCurElem(Link p, ElemType e){
    p->data = e;
    return OK;
}

//已知p指向线性链表的一个结点，返回结点的数据元素的值
ElemType GetCurElem(Link p){
    return p->data;
}

//若线性链表为空表返回True，否则返回False
Status ListEmpty(LinkList L){
    if (!L.len) {
        return TRUE;
    }else{
        return FALSE;
    }
}

//返回线性链表的元素个数
int ListLength(LinkList L){
    return L.len;
}

//返回线性链表头结点的位置
Position GetHeader(LinkList L){
    return L.header;
}

//返回线性链表最后一个结点的位置
Position GetLast(LinkList L){
    return L.tail;
}

//已知p指向线性链表中的一个结点，返回p所指向结点的直接后继，若无直接后继，则返回NULL
Position NextPos(Link p){
    return p->next;
}

//用p返回线性链表L中第i个结点的位置，并返回OK，如果i值不合法则返回error
Status LocatePos(LinkList L, int i, Link &p){
    if (i<1 || i>ListLength(L)) {
        return ERROR;
    }
    Link q = L.header;
    int j = 0;
    while (j<i && q!=NULL) {
        j++;
        q = q->next;
    }
    if (j>i || j>ListLength(L)) {
        return ERROR;
    }
    p = q;
    return OK;
}

//返回线性链表L中第一个与e满足compare判定关系的结点的位置，若不存在这样的元素，则返回NULL
Position LocateElem(LinkList L, ElemType e, Status (*compare)(ElemType e1, ElemType e2)){
    Link p = L.header->next;
    while (p!=NULL) {
        if (compare(p->data,e)) {
            return p;
        }
        p = p->next;
    }
    return NULL;
}

//依次对L中的每个调用数据元素调用visit函数。一旦visit失败，则操作失败
Status ListTraverse(LinkList L, void (*visit)(ElemType e)){
    Link p = L.header->next;
    while (p!=NULL) {
        visit(p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
}

//已知L为有序线性链表，将e元素按非降序插入在L中（用于一元多项式）
Status OrderInsert(LinkList &L, ElemType e, Status (*compare)(ElemType, ElemType)){
    Link p = L.header->next;
    Link q = L.header; //q用来表示p的前驱
    while (p!=NULL) { //之所以用p!=NULL作为循环结束条件，是为了让e能与链表L的最后一个结点元素值做比较

        //比较p指向结点的数据与e的大小，当p->data第一次大于等于e时，e即插入在p的前驱和p之间
        if (compare(p->data,e)>=0) {
            break;
        }
        q = p;
        p = p->next;
    }
    Link s = (Link)malloc(sizeof(LNode));
    s->data = e;
    q->next = s;
    s->next = p;
    //如果p等于NULL说明遍历到最后也没有找到比e大的值，因此e所在结点是表尾，修改表尾指针
    if (p==NULL) {
        L.tail = s;
    }
    L.len++;
    return OK;
}

//若升序链表L中存在与e满足判定函数compare取值为0的元素，则p返回L中第一个值为e的结点的位置，并返回true；否则p指示第一个与e满足判定函数compare>0的元素的前驱的位置，并返回false（用于一元多项式）
Status LocatElem(LinkList L, ElemType e, Position &p, int(*compare)(ElemType, ElemType)){
//    Link q = L.header->next;
//    Link s = L.header;
//    while (!q) {
//        if (compare(q->data,e)==0) {
//            p = q;
//            return OK;
//        }else if (compare(q->data,e)>0){
//            p = s;
//            return FALSE;
//        }
//        s = q;
//        q = q->next;
//    }
    Link q = L.header;
    Link s;
    do {
        s = q;
        q = q->next;
    } while (q && compare(q->data,e)<0); //循环结束后q可能到了表尾，也可能是compare(q->data,e)>=0
    if (!q||compare(q->data,e)>0) {
        p = s;
        return FALSE;
    }else{
        p = q;
        return TRUE;
    }
}

<|endoftext|>


<commit_before>/*
 * RemoteSyslogAppender.cpp
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Walter Stroebel. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "PortabilityImpl.hh"

#ifdef LOG4CPP_HAVE_UNISTD_H
#    include <unistd.h>
#endif
#include <cstdlib>
#include <stdio.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <log4cpp/RemoteSyslogAppender.hh>
#include <log4cpp/FactoryParams.hh>
#include <memory>

#ifdef WIN32
#include <winsock2.h>
#else
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

namespace log4cpp {

    int RemoteSyslogAppender::toSyslogPriority(Priority::Value priority) {
        static int priorities[8] = { LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
                                     LOG_WARNING, LOG_NOTICE, LOG_INFO,
                                     LOG_DEBUG };
        int result;

        priority++;
        priority /= 100;

        if (priority < 0) {
            result = LOG_EMERG;
        } else if (priority > 7) {
            result = LOG_DEBUG;
        } else {
            result = priorities[priority];
        }

        return result;
    }

    RemoteSyslogAppender::RemoteSyslogAppender(const std::string& name,
                                   const std::string& syslogName,
                                   const std::string& relayer,
                                   int facility,
                                   int portNumber) :
        LayoutAppender(name),
        _syslogName(syslogName),
        _relayer(relayer),
        _facility((facility == -1) ? LOG_USER : facility),
        _portNumber((portNumber == -1) ? 514 : portNumber),
        _socket (0),
        _ipAddr (0),
        _cludge (0)
    {
        open();
    }

    RemoteSyslogAppender::~RemoteSyslogAppender() {
        close();
#ifdef WIN32
        if (_cludge) {
            // we started it, we end it.
            WSACleanup ();
        }
#endif
    }

    void RemoteSyslogAppender::open() {
        if (!_ipAddr) {
            struct hostent *pent = gethostbyname (_relayer.c_str ());
#ifdef WIN32
            if (pent == NULL) {
                if (WSAGetLastError () == WSANOTINITIALISED) {
                    WSADATA wsaData;
                    int err;

                    err = WSAStartup (0x101, &wsaData );
                    if (err) {
                        // loglog("RemoteSyslogAppender: WSAStartup returned %d", err);
                        return; // fail silently
                    }
                    pent = gethostbyname (_relayer.c_str ());
                    _cludge = 1;
                } else {
                    // loglog("RemoteSyslogAppender: gethostbyname returned error");
                    return; // fail silently
                }
            }
#endif
            if (pent == NULL) {
                in_addr_t ip = inet_addr (_relayer.c_str ());
                pent = gethostbyaddr ((const char *) &ip, sizeof(in_addr_t), AF_INET);
                if (pent == NULL) {
                    // loglog("RemoteSyslogAppender: failed to resolve host %s", _relayer.c_str());
                    return; // fail silently
                }
            }
            _ipAddr = *(in_addr_t*)(pent->h_addr); // fixed bug #1579890
        }
        // Get a datagram socket.

        if ((_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            // loglog("RemoteSyslogAppender: failed to open socket");
            return; // fail silently
        }
    }

    void RemoteSyslogAppender::close() {
        if (_socket) {
#ifdef WIN32
            closesocket (_socket);
#else
            ::close (_socket);
#endif
            _socket = 0;
        }
    }

    void RemoteSyslogAppender::_append(const LoggingEvent& event) {
        const std::string message(_getLayout().format(event));
        size_t messageLength = message.length();
        char *buf = new char [messageLength + 16];
        int priority = _facility + toSyslogPriority(event.priority);
        int preambleLength = sprintf (buf, "<%d>", priority);
        memcpy (buf + preambleLength, message.data(), messageLength);

        sockaddr_in sain;
        sain.sin_family = AF_INET;
        sain.sin_port   = htons (_portNumber);
        // NO, do NOT use htonl on _ipAddr. Is already in network order.
        sain.sin_addr.s_addr = _ipAddr;

        while (messageLength > 0) {
            /* if packet larger than maximum (900 bytes), split
               into two or more syslog packets. */
            if (preambleLength + messageLength > 900) {
                sendto (_socket, buf, 900, 0, (struct sockaddr *) &sain, sizeof (sain));
                messageLength -= (900 - preambleLength);
                std::memmove (buf + preambleLength, buf + 900, messageLength);
                // note: we might need to sleep a bit here
            } else {
                sendto (_socket, buf, preambleLength + messageLength, 0, (struct sockaddr *) &sain, sizeof (sain));
                break;
            }
        }

        delete[] buf;
    }

    bool RemoteSyslogAppender::reopen() {
        close();
        open();
        return true;
    }

    std::auto_ptr<Appender> create_remote_syslog_appender(const FactoryParams& params)
    {
       std::string name, syslog_name, relayer;
       int facility = -1, port_number = -1;
       params.get_for("remote syslog appender").required("name", name)("syslog_name", syslog_name)("relayer", relayer)
                                               .optional("facility", facility)("port", port_number);
       return std::auto_ptr<Appender>(new RemoteSyslogAppender(name, syslog_name, relayer, facility, port_number));
    }
}
<commit_msg>Update include<commit_after>/*
 * RemoteSyslogAppender.cpp
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Walter Stroebel. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "PortabilityImpl.hh"

#ifdef LOG4CPP_HAVE_UNISTD_H
#    include <unistd.h>
#endif
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <log4cpp/RemoteSyslogAppender.hh>
#include <log4cpp/FactoryParams.hh>
#include <memory>

#ifdef WIN32
#include <winsock2.h>
#else
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

namespace log4cpp {

    int RemoteSyslogAppender::toSyslogPriority(Priority::Value priority) {
        static int priorities[8] = { LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR,
                                     LOG_WARNING, LOG_NOTICE, LOG_INFO,
                                     LOG_DEBUG };
        int result;

        priority++;
        priority /= 100;

        if (priority < 0) {
            result = LOG_EMERG;
        } else if (priority > 7) {
            result = LOG_DEBUG;
        } else {
            result = priorities[priority];
        }

        return result;
    }

    RemoteSyslogAppender::RemoteSyslogAppender(const std::string& name,
                                   const std::string& syslogName,
                                   const std::string& relayer,
                                   int facility,
                                   int portNumber) :
        LayoutAppender(name),
        _syslogName(syslogName),
        _relayer(relayer),
        _facility((facility == -1) ? LOG_USER : facility),
        _portNumber((portNumber == -1) ? 514 : portNumber),
        _socket (0),
        _ipAddr (0),
        _cludge (0)
    {
        open();
    }

    RemoteSyslogAppender::~RemoteSyslogAppender() {
        close();
#ifdef WIN32
        if (_cludge) {
            // we started it, we end it.
            WSACleanup ();
        }
#endif
    }

    void RemoteSyslogAppender::open() {
        if (!_ipAddr) {
            struct hostent *pent = gethostbyname (_relayer.c_str ());
#ifdef WIN32
            if (pent == NULL) {
                if (WSAGetLastError () == WSANOTINITIALISED) {
                    WSADATA wsaData;
                    int err;

                    err = WSAStartup (0x101, &wsaData );
                    if (err) {
                        // loglog("RemoteSyslogAppender: WSAStartup returned %d", err);
                        return; // fail silently
                    }
                    pent = gethostbyname (_relayer.c_str ());
                    _cludge = 1;
                } else {
                    // loglog("RemoteSyslogAppender: gethostbyname returned error");
                    return; // fail silently
                }
            }
#endif
            if (pent == NULL) {
                in_addr_t ip = inet_addr (_relayer.c_str ());
                pent = gethostbyaddr ((const char *) &ip, sizeof(in_addr_t), AF_INET);
                if (pent == NULL) {
                    // loglog("RemoteSyslogAppender: failed to resolve host %s", _relayer.c_str());
                    return; // fail silently
                }
            }
            _ipAddr = *(in_addr_t*)(pent->h_addr); // fixed bug #1579890
        }
        // Get a datagram socket.

        if ((_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            // loglog("RemoteSyslogAppender: failed to open socket");
            return; // fail silently
        }
    }

    void RemoteSyslogAppender::close() {
        if (_socket) {
#ifdef WIN32
            closesocket (_socket);
#else
            ::close (_socket);
#endif
            _socket = 0;
        }
    }

    void RemoteSyslogAppender::_append(const LoggingEvent& event) {
        const std::string message(_getLayout().format(event));
        size_t messageLength = message.length();
        char *buf = new char [messageLength + 16];
        int priority = _facility + toSyslogPriority(event.priority);
        int preambleLength = sprintf (buf, "<%d>", priority);
        memcpy (buf + preambleLength, message.data(), messageLength);

        sockaddr_in sain;
        sain.sin_family = AF_INET;
        sain.sin_port   = htons (_portNumber);
        // NO, do NOT use htonl on _ipAddr. Is already in network order.
        sain.sin_addr.s_addr = _ipAddr;

        while (messageLength > 0) {
            /* if packet larger than maximum (900 bytes), split
               into two or more syslog packets. */
            if (preambleLength + messageLength > 900) {
                sendto (_socket, buf, 900, 0, (struct sockaddr *) &sain, sizeof (sain));
                messageLength -= (900 - preambleLength);
                std::memmove (buf + preambleLength, buf + 900, messageLength);
                // note: we might need to sleep a bit here
            } else {
                sendto (_socket, buf, preambleLength + messageLength, 0, (struct sockaddr *) &sain, sizeof (sain));
                break;
            }
        }

        delete[] buf;
    }

    bool RemoteSyslogAppender::reopen() {
        close();
        open();
        return true;
    }

    std::auto_ptr<Appender> create_remote_syslog_appender(const FactoryParams& params)
    {
       std::string name, syslog_name, relayer;
       int facility = -1, port_number = -1;
       params.get_for("remote syslog appender").required("name", name)("syslog_name", syslog_name)("relayer", relayer)
                                               .optional("facility", facility)("port", port_number);
       return std::auto_ptr<Appender>(new RemoteSyslogAppender(name, syslog_name, relayer, facility, port_number));
    }
}
<|endoftext|>


<commit_before>#include <cassert>
#include "SlottedPage.hpp"

#define PAGE_SIZE 8192; // TODO Duplicate to BufferManager
#define SLOT_COUNT 256; // TODO sure about that value?

using namespace std;

struct Header {

};

SlottedPage::SlottedPage(uint64_t pageId)
 : pageId(pageId) {
    header          = this;
    firstSlot       = this + sizeof(Header);
    firstEmptySlot  = firstSlot;
    slotEnd         = firstSlot + SLOT_COUNT * sizeof(Slot);
    end             = this + PAGE_SIZE;
    freeSpace       = end;
}

uint64_t SlottedPage::insert(const Record& r){
    if (this->getFreeSpaceOnPage() < r.getLen()) throw "Insufficient space.";

    Slot* slot = firstEmptySlot;

    assert(firstEmptySlot < slotEnd);

    char* destination = this->freeSpace - r.getLen();
    memcpy(destination, &r, r.getLen());

    uint64_t slotNum = (slot - header) / sizeof(Slot);

    slot->length = r.getLen();
    slot->offset = destination - slot; // Slot::offset is the offset between slot and data
    slot->moved  = false;
    slot->tid    = pageId | slotNum; // TODO

    for (Slot* s = firstEmptySlot; s < slotEnd; s += sizeof(Slot)) {
        firstEmptySlot = s;
        if (s->isEmpty()) break;
    }

    freeSpace -= r.getLen();

    return slot->tid.getTID();
}

void SlottedPage::remove(uint64_t slotNum) {
    Slot* slot = this->getSlot(slotNum);
    slot->length = 0;
    slot->offset = 0;
    slot->moved  = false;

    if (firstEmptySlot > slot) {
        firstEmptySlot = slot;
    }
}

uint64_t SlottedPage::recompress() {
    // TODO
}

Slot* SlottedPage::getSlot(uint64_t slotNum){
    return firstSlot + slotNum * sizeof(Slot);
}

Slot* SlottedPage::getFreeSlot(){
    return firstEmptySlot;
}

Record* SlottedPage::getRecordPtr(uint64_t slotNum){
    Slot* slot = getSlot(slotNum);
    if (slot->isEmpty()) throw "Empty slot doesn't have an associated record.";
    return reinterpret_cast<Record*>(slot + slot->offset);
}

unsigned SlottedPage::getFreeSpaceOnPage(){
    return this->freeSpace - this->slotEnd;
}

SlottedPage::~SlottedPage(){
}
<commit_msg>Fixed a few pointer casts.<commit_after>#include <cassert>
#include "SlottedPage.hpp"

#define PAGE_SIZE 8192 // TODO Duplicate to BufferManager
#define SLOT_COUNT 256 // TODO sure about that value?

using namespace std;

struct Header {

};

SlottedPage::SlottedPage(uint64_t pageId)
 : pageId(pageId) {
    header          = (char*) this;
    firstSlot       = (Slot*) this + sizeof(Header);
    firstEmptySlot  = firstSlot;
    slotEnd         = reinterpret_cast<Slot*>(reinterpret_cast<unsigned>(firstSlot) + SLOT_COUNT * sizeof(Slot));
    end             = (char*) this + PAGE_SIZE;
    freeSpace       = end;
}

uint64_t SlottedPage::insert(const Record& r){
    if (this->getFreeSpaceOnPage() < r.getLen()) throw "Insufficient space.";

    Slot* slot = firstEmptySlot;

    assert(firstEmptySlot < slotEnd);

    char* destination = this->freeSpace - r.getLen();
    memcpy(destination, &r, r.getLen());

    uint64_t slotNum = ((char*) slot - header) / sizeof(Slot);

    slot->length = r.getLen();
    slot->offset = (uint64_t) destination - (uint64_t) slot; // Slot::offset is the offset between slot and data
    slot->moved  = false;
    slot->tid    = pageId | slotNum; // TODO

    for (Slot* s = firstEmptySlot; s < slotEnd; s += sizeof(Slot)) {
        firstEmptySlot = s;
        if (s->isEmpty()) break;
    }

    freeSpace -= r.getLen();

    return slot->tid.getTID();
}

void SlottedPage::remove(uint64_t slotNum) {
    Slot* slot = this->getSlot(slotNum);
    slot->length = 0;
    slot->offset = 0;
    slot->moved  = false;

    if (firstEmptySlot > slot) {
        firstEmptySlot = slot;
    }
}

uint64_t SlottedPage::recompress() {
    // TODO
    return 0;
}

Slot* SlottedPage::getSlot(uint64_t slotNum){
    return firstSlot + slotNum * sizeof(Slot);
}

Slot* SlottedPage::getFreeSlot(){
    return firstEmptySlot;
}

Record* SlottedPage::getRecordPtr(uint64_t slotNum){
    Slot* slot = getSlot(slotNum);
    if (slot->isEmpty()) throw "Empty slot doesn't have an associated record.";
    return reinterpret_cast<Record*>(slot + slot->offset);
}

unsigned SlottedPage::getFreeSpaceOnPage(){
    return ((unsigned) this->freeSpace - (unsigned) this->slotEnd);
}

SlottedPage::~SlottedPage(){
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>

#if defined(_MSC_VER)
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#elif defined(__clang__)
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
#include <SDL2_ttf/SDL_ttf.h>
#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#endif

/*
*  Lesson 6: True Type Fonts with SDL_ttf
*/
//Screen attributes
const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;

/**
* Log an SDL error with some error message to the output stream of our choice
* @param os The output stream to write the message too
* @param msg The error message to write, format will be msg error: SDL_GetError()
*/
void logSDLError(std::ostream &os, const std::string &msg){
	os << msg << " error: " << SDL_GetError() << std::endl;
}
/**
* Loads an image into a texture on the rendering device
* @param file The image file to load
* @param ren The renderer to load the texture onto
* @return the loaded texture, or nullptr if something went wrong.
*/
SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren){
	SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str());
	if (texture == nullptr)
		logSDLError(std::cout, "LoadTexture");
	return texture;
}
/**
* Draw an SDL_Texture to an SDL_Renderer at some destination rect
* taking a clip of the texture if desired
* @param tex The source texture we want to draw
* @param rend The renderer we want to draw too
* @param dst The destination rectangle to render the texture too
* @param clip The sub-section of the texture to draw (clipping rect)
*		default of nullptr draws the entire texture
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, SDL_Rect dst, SDL_Rect *clip = nullptr){
	SDL_RenderCopy(ren, tex, clip, &dst);
}
/**
* Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving
* the texture's width and height and taking a clip of the texture if desired
* If a clip is passed, the clip's width and height will be used instead of the texture's
* @param tex The source texture we want to draw
* @param rend The renderer we want to draw too
* @param x The x coordinate to draw too
* @param y The y coordinate to draw too
* @param clip The sub-section of the texture to draw (clipping rect)
*		default of nullptr draws the entire texture
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, SDL_Rect *clip = nullptr){
	SDL_Rect dst;
	dst.x = x;
	dst.y = y;
	if (clip != nullptr){
		dst.w = clip->w;
		dst.h = clip->h;
	}
	else
		SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);

	renderTexture(tex, ren, dst, clip);
}
/**
* Render the message we want to display to a texture for drawing
* @param message The message we want to display
* @param fontFile The font we want to use to render the text
* @param color The color we want the text to be
* @param fontSize The size we want the font to be
* @param renderer The renderer to load the texture in
* @return An SDL_Texture containing the rendered message, or nullptr if something went wrong
*/
SDL_Texture* renderText(std::string message, std::string fontFile, SDL_Color color,
	int fontSize, SDL_Renderer *renderer)
{
	//Open the font
	TTF_Font *font = TTF_OpenFont(fontFile.c_str(), fontSize);
	if (font == nullptr){
		logSDLError(std::cout, "TTF_OpenFont");
		return nullptr;
	}
	//We need to first render to a surface as that's what TTF_RenderText returns, then
	//load that surface into a texture
	SDL_Surface *surf = TTF_RenderText_Blended(font, message.c_str(), color);
	if (surf == nullptr){
		TTF_CloseFont(font);
		logSDLError(std::cout, "TTF_RenderText");
		return nullptr;
	}
	SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf);
	if (texture == nullptr){
		logSDLError(std::cout, "CreateTexture");
	}
	//Clean up the surface and font
	SDL_FreeSurface(surf);
	TTF_CloseFont(font);
	return texture;
}

int main(int argc, char** argv){
	//Start up SDL and make sure it went ok
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
		logSDLError(std::cout, "SDL_Init");
		return 1;
	}
	//Also need to init SDL_ttf
	if (TTF_Init() != 0){
		logSDLError(std::cout, "TTF_Init");
		return 1;
	}

	//Setup our window and renderer
	SDL_Window *window = SDL_CreateWindow("Lesson 6", SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
	if (window == nullptr){
		logSDLError(std::cout, "CreateWindow");
		return 1;
	}
	SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
	if (renderer == nullptr){
		logSDLError(std::cout, "CreateRenderer");
		return 1;
	}

	//We'll render the string "TTF fonts are cool!" in white
	//Color is in RGB format
	SDL_Color color = { 255, 255, 255 };
	SDL_Texture *image = renderText("TTF fonts are cool!", "../res/Lesson6/sample.ttf", color, 64, renderer);

	//Get the texture w/h so we can center it in the screen
	int iW, iH;
	SDL_QueryTexture(image, NULL, NULL, &iW, &iH);
	int x = SCREEN_WIDTH / 2 - iW / 2;
	int y = SCREEN_HEIGHT / 2 - iH / 2;

	SDL_Event e;
	bool quit = false;
	while (!quit){
		//Event Polling
		while (SDL_PollEvent(&e)){
			if (e.type == SDL_QUIT)
				quit = true;
			if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)
				quit = true;
		}
		SDL_RenderClear(renderer);
		//We can draw our message as we do any other texture, since it's been
		//rendered to a texture
		renderTexture(image, renderer, x, y);
		SDL_RenderPresent(renderer);
	}
	//Clean up
	SDL_DestroyTexture(image);
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	TTF_Quit();
	SDL_Quit();

	return 0;
}
<commit_msg>Take params by const&<commit_after>#include <string>
#include <iostream>

#if defined(_MSC_VER)
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#elif defined(__clang__)
#include <SDL2/SDL.h>
#include <SDL2_image/SDL_image.h>
#include <SDL2_ttf/SDL_ttf.h>
#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#endif

/*
*  Lesson 6: True Type Fonts with SDL_ttf
*/
//Screen attributes
const int SCREEN_WIDTH  = 640;
const int SCREEN_HEIGHT = 480;

/**
* Log an SDL error with some error message to the output stream of our choice
* @param os The output stream to write the message too
* @param msg The error message to write, format will be msg error: SDL_GetError()
*/
void logSDLError(std::ostream &os, const std::string &msg){
	os << msg << " error: " << SDL_GetError() << std::endl;
}
/**
* Loads an image into a texture on the rendering device
* @param file The image file to load
* @param ren The renderer to load the texture onto
* @return the loaded texture, or nullptr if something went wrong.
*/
SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren){
	SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str());
	if (texture == nullptr)
		logSDLError(std::cout, "LoadTexture");
	return texture;
}
/**
* Draw an SDL_Texture to an SDL_Renderer at some destination rect
* taking a clip of the texture if desired
* @param tex The source texture we want to draw
* @param rend The renderer we want to draw too
* @param dst The destination rectangle to render the texture too
* @param clip The sub-section of the texture to draw (clipping rect)
*		default of nullptr draws the entire texture
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, SDL_Rect dst, SDL_Rect *clip = nullptr){
	SDL_RenderCopy(ren, tex, clip, &dst);
}
/**
* Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving
* the texture's width and height and taking a clip of the texture if desired
* If a clip is passed, the clip's width and height will be used instead of the texture's
* @param tex The source texture we want to draw
* @param rend The renderer we want to draw too
* @param x The x coordinate to draw too
* @param y The y coordinate to draw too
* @param clip The sub-section of the texture to draw (clipping rect)
*		default of nullptr draws the entire texture
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, SDL_Rect *clip = nullptr){
	SDL_Rect dst;
	dst.x = x;
	dst.y = y;
	if (clip != nullptr){
		dst.w = clip->w;
		dst.h = clip->h;
	}
	else
		SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);

	renderTexture(tex, ren, dst, clip);
}
/**
* Render the message we want to display to a texture for drawing
* @param message The message we want to display
* @param fontFile The font we want to use to render the text
* @param color The color we want the text to be
* @param fontSize The size we want the font to be
* @param renderer The renderer to load the texture in
* @return An SDL_Texture containing the rendered message, or nullptr if something went wrong
*/
SDL_Texture* renderText(const std::string &message, const std::string &fontFile, SDL_Color color,
	int fontSize, SDL_Renderer *renderer)
{
	//Open the font
	TTF_Font *font = TTF_OpenFont(fontFile.c_str(), fontSize);
	if (font == nullptr){
		logSDLError(std::cout, "TTF_OpenFont");
		return nullptr;
	}
	//We need to first render to a surface as that's what TTF_RenderText returns, then
	//load that surface into a texture
	SDL_Surface *surf = TTF_RenderText_Blended(font, message.c_str(), color);
	if (surf == nullptr){
		TTF_CloseFont(font);
		logSDLError(std::cout, "TTF_RenderText");
		return nullptr;
	}
	SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf);
	if (texture == nullptr){
		logSDLError(std::cout, "CreateTexture");
	}
	//Clean up the surface and font
	SDL_FreeSurface(surf);
	TTF_CloseFont(font);
	return texture;
}

int main(int argc, char** argv){
	//Start up SDL and make sure it went ok
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
		logSDLError(std::cout, "SDL_Init");
		return 1;
	}
	//Also need to init SDL_ttf
	if (TTF_Init() != 0){
		logSDLError(std::cout, "TTF_Init");
		return 1;
	}

	//Setup our window and renderer
	SDL_Window *window = SDL_CreateWindow("Lesson 6", SDL_WINDOWPOS_CENTERED,
		SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
	if (window == nullptr){
		logSDLError(std::cout, "CreateWindow");
		return 1;
	}
	SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
	if (renderer == nullptr){
		logSDLError(std::cout, "CreateRenderer");
		return 1;
	}

	//We'll render the string "TTF fonts are cool!" in white
	//Color is in RGB format
	SDL_Color color = { 255, 255, 255 };
	SDL_Texture *image = renderText("TTF fonts are cool!", "../res/Lesson6/sample.ttf", color, 64, renderer);

	//Get the texture w/h so we can center it in the screen
	int iW, iH;
	SDL_QueryTexture(image, NULL, NULL, &iW, &iH);
	int x = SCREEN_WIDTH / 2 - iW / 2;
	int y = SCREEN_HEIGHT / 2 - iH / 2;

	SDL_Event e;
	bool quit = false;
	while (!quit){
		//Event Polling
		while (SDL_PollEvent(&e)){
			if (e.type == SDL_QUIT)
				quit = true;
			if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)
				quit = true;
		}
		SDL_RenderClear(renderer);
		//We can draw our message as we do any other texture, since it's been
		//rendered to a texture
		renderTexture(image, renderer, x, y);
		SDL_RenderPresent(renderer);
	}
	//Clean up
	SDL_DestroyTexture(image);
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	TTF_Quit();
	SDL_Quit();

	return 0;
}
<|endoftext|>


<commit_before>//===- tools/seec-view/SourceEditor/GlobalCompilerPreferences.cpp ---------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "seec/ICU/Resources.hpp"
#include "seec/wxWidgets/StringConversion.hpp"

#include <wx/config.h>
#include <wx/filepicker.h>
#include <wx/log.h>
#include <wx/msgdlg.h>
#include <wx/sizer.h>
#include <wx/stattext.h>

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Program.h"

#include "GlobalCompilerPreferences.hpp"

using namespace seec;

char const * const cConfigKeyForMinGWGCCPath = "/Compiler/MinGW/GCCPath";

wxFileName getPathForMinGWGCC()
{
  auto const Config = wxConfig::Get();
  wxString GCCPath;
  if (Config->Read(cConfigKeyForMinGWGCCPath, &GCCPath)) {
    return wxFileName{GCCPath};
  }

#if defined(_WIN32)
  auto const GCCName = "gcc.exe";
#else
  auto const GCCName = "gcc";
#endif

  auto SearchEnvPath = llvm::sys::findProgramByName(GCCName);
  if (SearchEnvPath)
    return wxFileName{std::move(*SearchEnvPath)};

  return wxFileName{};
}

namespace {

bool setPathForMinGWGCC(wxFileName const &Path)
{
  auto const Config = wxConfig::Get();
  if (!Config->Write(cConfigKeyForMinGWGCCPath, Path.GetFullPath()))
    return false;
  Config->Flush();
  return true;
}

}

bool GlobalCompilerPreferencesWindow::SaveValuesImpl()
{
  if (m_MinGWGCCPathCtrl) {
    auto const Path = m_MinGWGCCPathCtrl->GetPath();
    if (!llvm::sys::fs::can_execute(Path.ToStdString())) {
      auto const ResText = Resource("TraceViewer")["GlobalCompilerPreferences"];

      wxMessageDialog Dlg(this,
                          towxString(ResText["GCCNotExecutableMessage"]),
                          towxString(ResText["GCCNotExecutableCaption"]));
      Dlg.ShowModal();
      return false;
    }

    if (!setPathForMinGWGCC(m_MinGWGCCPathCtrl->GetPath())) {
      return false;
    }
  }

  return true;
}

void GlobalCompilerPreferencesWindow::CancelChangesImpl() {}

wxString GlobalCompilerPreferencesWindow::GetDisplayNameImpl()
{
  return towxString(Resource("TraceViewer")
                    ["GlobalCompilerPreferences"]["Title"]);
}

GlobalCompilerPreferencesWindow::GlobalCompilerPreferencesWindow()
: m_MinGWGCCPathCtrl(nullptr)
{}

GlobalCompilerPreferencesWindow
::GlobalCompilerPreferencesWindow(wxWindow *Parent)
: GlobalCompilerPreferencesWindow()
{
  Create(Parent);
}

GlobalCompilerPreferencesWindow::~GlobalCompilerPreferencesWindow()
  = default;

bool GlobalCompilerPreferencesWindow::Create(wxWindow *Parent)
{
  if (!wxWindow::Create(Parent, wxID_ANY)) {
    return false;
  }

  auto const Res = Resource("TraceViewer")["GlobalCompilerPreferences"];

  // TODO: only add on MSW
  auto const MinGWGCCFilePickerLabel =
    new wxStaticText(this, wxID_ANY, towxString(Res["MinGWGCCLocationLabel"]));

  // TODO: only add on MSW
  m_MinGWGCCPathCtrl =
    new wxFilePickerCtrl(this, wxID_ANY,
      /* path */ getPathForMinGWGCC().GetFullPath(),
      /* message */ towxString(Res["MinGWGCCLocationPrompt"]),
      wxFileSelectorDefaultWildcardStr,
      wxDefaultPosition,
      wxDefaultSize,
      wxFLP_DEFAULT_STYLE | wxFLP_USE_TEXTCTRL | wxFLP_FILE_MUST_EXIST);

  // Vertical sizer to hold each row of input.
  auto const ParentSizer = new wxBoxSizer(wxVERTICAL);

  int const BorderDir = wxLEFT | wxRIGHT;
  int const BorderSize = 5;

  ParentSizer->AddSpacer(BorderSize);

  // TODO: only add on MSW
  ParentSizer->Add(MinGWGCCFilePickerLabel,
                   wxSizerFlags().Border(BorderDir, BorderSize));

  // TODO: only add on MSW
  ParentSizer->Add(m_MinGWGCCPathCtrl,
                   wxSizerFlags().Expand().Border(BorderDir, BorderSize));

  ParentSizer->AddSpacer(BorderSize);

  SetSizerAndFit(ParentSizer);

  return true;
}
<commit_msg>Only show the MinGW GCC selection option under MSW.<commit_after>//===- tools/seec-view/SourceEditor/GlobalCompilerPreferences.cpp ---------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "seec/ICU/Resources.hpp"
#include "seec/wxWidgets/StringConversion.hpp"

#include <wx/config.h>
#include <wx/filepicker.h>
#include <wx/log.h>
#include <wx/msgdlg.h>
#include <wx/platinfo.h>
#include <wx/sizer.h>
#include <wx/stattext.h>

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Program.h"

#include "GlobalCompilerPreferences.hpp"

using namespace seec;

char const * const cConfigKeyForMinGWGCCPath = "/Compiler/MinGW/GCCPath";

wxFileName getPathForMinGWGCC()
{
  auto const Config = wxConfig::Get();
  wxString GCCPath;
  if (Config->Read(cConfigKeyForMinGWGCCPath, &GCCPath)) {
    return wxFileName{GCCPath};
  }

#if defined(_WIN32)
  auto const GCCName = "gcc.exe";
#else
  auto const GCCName = "gcc";
#endif

  auto SearchEnvPath = llvm::sys::findProgramByName(GCCName);
  if (SearchEnvPath)
    return wxFileName{std::move(*SearchEnvPath)};

  return wxFileName{};
}

namespace {

bool setPathForMinGWGCC(wxFileName const &Path)
{
  auto const Config = wxConfig::Get();
  if (!Config->Write(cConfigKeyForMinGWGCCPath, Path.GetFullPath()))
    return false;
  Config->Flush();
  return true;
}

}

bool GlobalCompilerPreferencesWindow::SaveValuesImpl()
{
  if (m_MinGWGCCPathCtrl) {
    auto const Path = m_MinGWGCCPathCtrl->GetPath();
    if (!llvm::sys::fs::can_execute(Path.ToStdString())) {
      auto const ResText = Resource("TraceViewer")["GlobalCompilerPreferences"];

      wxMessageDialog Dlg(this,
                          towxString(ResText["GCCNotExecutableMessage"]),
                          towxString(ResText["GCCNotExecutableCaption"]));
      Dlg.ShowModal();
      return false;
    }

    if (!setPathForMinGWGCC(m_MinGWGCCPathCtrl->GetPath())) {
      return false;
    }
  }

  return true;
}

void GlobalCompilerPreferencesWindow::CancelChangesImpl() {}

wxString GlobalCompilerPreferencesWindow::GetDisplayNameImpl()
{
  return towxString(Resource("TraceViewer")
                    ["GlobalCompilerPreferences"]["Title"]);
}

GlobalCompilerPreferencesWindow::GlobalCompilerPreferencesWindow()
: m_MinGWGCCPathCtrl(nullptr)
{}

GlobalCompilerPreferencesWindow
::GlobalCompilerPreferencesWindow(wxWindow *Parent)
: GlobalCompilerPreferencesWindow()
{
  Create(Parent);
}

GlobalCompilerPreferencesWindow::~GlobalCompilerPreferencesWindow()
  = default;

bool GlobalCompilerPreferencesWindow::Create(wxWindow *Parent)
{
  if (!wxWindow::Create(Parent, wxID_ANY)) {
    return false;
  }

  auto const Res = Resource("TraceViewer")["GlobalCompilerPreferences"];
  auto const &Platform = wxPlatformInfo::Get();

  // Vertical sizer to hold each row of input.
  auto const ParentSizer = new wxBoxSizer(wxVERTICAL);

  int const BorderDir = wxLEFT | wxRIGHT;
  int const BorderSize = 5;

  if (Platform.GetOperatingSystemId() & wxOS_WINDOWS) {
    auto const MinGWGCCFilePickerLabel =
      new wxStaticText(this, wxID_ANY,
                       towxString(Res["MinGWGCCLocationLabel"]));

    m_MinGWGCCPathCtrl =
      new wxFilePickerCtrl(this, wxID_ANY,
        /* path */ getPathForMinGWGCC().GetFullPath(),
        /* message */ towxString(Res["MinGWGCCLocationPrompt"]),
        wxFileSelectorDefaultWildcardStr,
        wxDefaultPosition,
        wxDefaultSize,
        wxFLP_DEFAULT_STYLE | wxFLP_USE_TEXTCTRL | wxFLP_FILE_MUST_EXIST);

    ParentSizer->AddSpacer(BorderSize);

    ParentSizer->Add(MinGWGCCFilePickerLabel,
                     wxSizerFlags().Border(BorderDir, BorderSize));

    ParentSizer->Add(m_MinGWGCCPathCtrl,
                     wxSizerFlags().Expand().Border(BorderDir, BorderSize));

    ParentSizer->AddSpacer(BorderSize);
  }

  SetSizerAndFit(ParentSizer);

  return true;
}
<|endoftext|>


<commit_before><commit_msg>updates to publish manipulation commands for gas and brake<commit_after><|endoftext|>