Skip to content

Instantly share code, notes, and snippets.

@dc1394
Last active August 29, 2015 14:07
Show Gist options
  • Save dc1394/6aa6b33ef55653dadca6 to your computer and use it in GitHub Desktop.
Save dc1394/6aa6b33ef55653dadca6 to your computer and use it in GitHub Desktop.
カレンダープログラミングのソースコード
// Myoga S. Tomonaka 様の「14セグメントのドットマトリックスで日付を表示するカレンダー」
// ( https://gist.github.com/Myoga1012/8e56f44ecd710555a06c )
// を、DirectWriteに移植してみました。
// Kenny Kerr 様の
// 「DirectX プログラミング用の最新 C++ ライブラリ」
// ( http://msdn.microsoft.com/ja-jp/magazine/dn201741.aspx )
// を使用させて頂いています。また、このライブラリのサンプルコード
// ( http://dx.codeplex.com/SourceControl/latest )
// を参考にさせて頂いています。
// 例によってC++11とBoostも使用しています。
#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "user32.lib")
#pragma warning(disable: 4706)
#include <algorithm> // for std::transform
#include <array> // for std::array
#include <cctype> // for std::toupper
#include <cstdint> // for std::int32_t, std::uint16_t, std::uint32_t
#include <memory> // for std::unique_ptr
#include <stdexcept> // for std::runtime_error
#include <string> // for std::string
#include <boost/date_time/gregorian/gregorian.hpp> // for boost::gregorian
#include <boost/format.hpp> // for boost::format
#include <boost/range/algorithm.hpp> // for boost::find
#include "dx.h"
namespace {
using namespace boost::gregorian;
using namespace KennyKerr;
using namespace KennyKerr::Direct2D;
using namespace KennyKerr::DirectWrite;
static auto constexpr Height = 600;
static auto constexpr Width = 1140;
static auto const today = day_clock::local_day();
class MyCalendar14seqDirectWrite final {
typedef std::array<bool, 14> segctype;
static auto constexpr DotSize = 7.0f; // ドットのサイズ
static auto constexpr SegMargin = 3.0f; // セグメントのマージン
static auto constexpr SegSizeX = DotSize * 7.0f; // 1セグメント当たりのサイズ
static auto constexpr SegSizeY = DotSize * 9.0f;
SolidColorBrush brush;
std::uint16_t const d = gregorian_calendar::end_of_month_day(today.year(), today.month());
Direct2D::Factory1 factory = Direct2D::CreateFactory();
DirectWrite::Factory2 factory2 = DirectWrite::CreateFactory();
std::int32_t const firstdow = static_cast<std::int32_t>(date(today.year(), today.month(), 1).day_of_week().as_number());
std::string month = today.month().as_long_string();
std::array<std::array<bool, 7>, 9> seg14dmt;
Dxgi::SwapChain1 swapChain;
DeviceContext target = nullptr;
public:
explicit MyCalendar14seqDirectWrite(HWND window)
{
std::transform(month.begin(), month.end(), month.begin(), std::toupper);
Initialize(window);
}
private:
// sourceの値が、argのリストのいずれかとマッチするかどうかを判別します。
bool AnyOneOfMatch(char source, std::vector<char> const & charvec) const
{
return charvec.end() != boost::find(charvec, source);
}
// 14セグメント符号から7×9のドットマトリックスを構成します。
void Convert14segToDotMatrix(segctype const & seg14)
{
for (auto & v : seg14dmt)
for (auto & val : v)
val = false;
// 水平1
for (auto i = 1; i < 6; i++) {
seg14dmt[0][i] = seg14[0];
seg14dmt[8][i] = seg14[3];
}
// 水平
for (auto i = 1; i < 3; i++) {
seg14dmt[0][i] = seg14dmt[0][i + 3] = seg14[0];
seg14dmt[8][i] = seg14dmt[8][i + 3] = seg14[3];
seg14dmt[4][i] = seg14[6];
seg14dmt[4][i + 3] = seg14[7];
}
// 垂直
for (auto i = 1; i < 4; i++) {
seg14dmt[i][0] = seg14[5];
seg14dmt[i][3] = seg14[8];
seg14dmt[i][6] = seg14[1];
seg14dmt[i + 4][0] = seg14[4];
seg14dmt[i + 4][3] = seg14[9];
seg14dmt[i + 4][6] = seg14[2];
}
// ナナメ
seg14dmt[1][1] = seg14[10];
seg14dmt[1][5] = seg14[11];
seg14dmt[7][5] = seg14[12];
seg14dmt[7][1] = seg14[13];
for (auto i = 2; i < 4; i++) {
seg14dmt[i][2] = seg14[10];
seg14dmt[i][4] = seg14[11];
seg14dmt[i + 3][4] = seg14[12];
seg14dmt[i + 3][2] = seg14[13];
}
// クロスポイント
seg14dmt[0][0] = seg14[0] || seg14[5] || seg14[10];
seg14dmt[0][3] = seg14[0] || seg14[8];
seg14dmt[0][6] = seg14[0] || seg14[1] || seg14[11];
seg14dmt[4][6] = seg14[1] || seg14[2] || seg14[7];
seg14dmt[8][6] = seg14[2] || seg14[3] || seg14[12];
seg14dmt[8][3] = seg14[3] || seg14[9];
seg14dmt[8][0] = seg14[3] || seg14[4] || seg14[13];
seg14dmt[4][0] = seg14[4] || seg14[5] || seg14[6];
seg14dmt[4][3] = seg14[6] || seg14[7] || seg14[8] || seg14[9] || seg14[10] || seg14[11] || seg14[12] || seg14[13];
}
void CreateDeviceResources()
{
brush = target.CreateSolidColorBrush(Color());
}
void CreateDeviceSwapChainBitmap()
{
auto const props = BitmapProperties1(
BitmapOptions::Target | BitmapOptions::CannotDraw,
PixelFormat(Dxgi::Format::B8G8R8A8_UNORM, AlphaMode::Ignore));
target.SetTarget(
target.CreateBitmapFromDxgiSurface(
swapChain,
props));
}
// 数値 -> 14セグメント符号
segctype DecodeFor14seg(char dec) const
{
if (!(dec >= '0' && dec <= '9' || dec >= 'A' && dec <= 'Z' || dec == ' '))
{
throw std::runtime_error("対応していない文字が関数DecodeFor14segの引数decに渡されました");
}
return segctype{{
!AnyOneOfMatch(dec, { '1', '4', 'H', 'J', 'K', 'L', 'M', 'N', 'U', 'V', 'W', 'X', 'Y', ' ' }),
!AnyOneOfMatch(dec, { '5', '6', 'C', 'E', 'F', 'G', 'I', 'K', 'L', 'S', 'T', 'V', 'X', 'Z', ' ' }),
!AnyOneOfMatch(dec, { '2', 'C', 'E', 'F', 'I', 'K', 'L', 'P', 'R', 'T', 'V', 'X', 'Y', 'Z', ' ' }),
!AnyOneOfMatch(dec, { '1', '4', '7', 'A', 'F', 'H', 'K', 'M', 'N', 'P', 'R', 'T', 'V', 'W', 'X', 'Y', ' ' }),
!AnyOneOfMatch(dec, { '1', '3', '4', '5', '7', '9', 'B', 'D', 'I', 'S', 'T', 'X', 'Y', 'Z', ' ' }),
!AnyOneOfMatch(dec, { '1', '2', '3', '7', 'B', 'D', 'I', 'J', 'T', 'X', 'Z', ' ' }),
AnyOneOfMatch(dec, { '2', '3', '4', '5', '6', '8', '9', 'A', 'E', 'F', 'H', 'K', 'P', 'R', 'S', 'Y' }),
AnyOneOfMatch(dec, { '2', '3', '4', '5', '6', '8', '9', 'A', 'B', 'E', 'F', 'G', 'H', 'P', 'R', 'S', 'Y' }),
AnyOneOfMatch(dec, { 'B', 'D', 'I', 'T' }),
AnyOneOfMatch(dec, { 'B', 'D', 'I', 'T', 'Y' }),
AnyOneOfMatch(dec, { 'M', 'N', 'X' }),
AnyOneOfMatch(dec, { '0', 'K', 'M', 'V', 'X', 'Z' }),
AnyOneOfMatch(dec, { 'K', 'N', 'Q', 'R', 'W', 'X' }),
AnyOneOfMatch(dec, { '0', 'V', 'W', 'X', 'Z' })
}};
}
public:
void Draw()
{
target.Clear(Color(1.0f, 1.0f, 1.0f));
// 年月を描画します
DrawString(
0.0f,
0.0f,
(boost::format("%s %4d") % month % today.year()).str(),
Color(0.5f, 1.0f, 0.5f),
Color(0.0f, 1.0f, 0.0f),
10.0f,
10.0f);
for (auto i = 1, seq = firstdow; i <= d; i++, seq++) {
auto const dow = seq % 7;
DrawDate(
static_cast<float>(dow),
static_cast<float>(seq / 7 + 1),
i,
dow ? (dow == 6 ? Color(0.0f, 1.0f, 1.0f) : Color(1.0f, 1.0f, 1.0f)) : Color(1.0f, 0.5f, 0.937f),
dow ? (dow == 6 ? Color(0.141f, 0.392f, 1.0f) : Color(0.667f, 0.667f, 0.667f)) : Color(1.0f, 0.0f, 1.0f),
10.0f,
40.0f);
}
}
private:
void DrawDate(float x, float y, std::uint32_t day, Color fillColor, Color edgeColor = Color(0.0f, 0.0f, 0.0f), float xoff = 0.0f, float yoff = 0.0f)
{
if (day >= 1 && day <= 31) {
auto const ten = static_cast<char>(day / 10), one = static_cast<char>(day % 10);
DrawNumAlpha(
x * 3.0f,
y,
ten ? ten + '0' : ' ',
fillColor,
edgeColor,
xoff,
yoff);
DrawNumAlpha(
x * 3.0f + 1.0f,
y,
one + '0',
fillColor,
edgeColor,
xoff,
yoff);
}
else {
throw std::runtime_error("引数dayの日付が1日未満か32日以上です");
}
}
void DrawNumAlpha(float x, float y, char na, Color fillColor, Color edgeColor = Color(0.0f, 0.0f, 0.0f), float xoff = 0.0f, float yoff = 0.0f)
{
if (!(na >= '0' && na <= '9' || na >= 'A' && na <= 'Z' || na == ' '))
{
throw std::runtime_error("対応していない文字が関数DrawNumAlphaの引数naに渡されました");
}
Convert14segToDotMatrix(DecodeFor14seg(na));
// ドットマトリックスを表示します。
for (auto i = 0; i < 9; i++) {
for (auto j = 0; j < 7; j++) {
if (seg14dmt[i][j]) {
auto const ii = static_cast<float>(i);
auto const jj = static_cast<float>(j);
auto const rect1 = RectF(
DotSize * jj + x * (SegSizeX + SegMargin * 2.0f) + SegMargin + xoff, // x1
DotSize * ii + y * (SegSizeY + SegMargin * 2.0f) + SegMargin + yoff, // y1
DotSize * (jj + 1.0f) + x * (SegSizeX + SegMargin * 2.0f) + SegMargin + xoff, // x2
DotSize * (ii + 1.0f) + y * (SegSizeY + SegMargin * 2.0f) + SegMargin + yoff); // y2
brush.Reset();
brush = target.CreateSolidColorBrush(edgeColor);
target.DrawRectangle(rect1, brush);
auto const rect2 = RectF(
DotSize * jj + x * (SegSizeX + SegMargin * 2.0f) + SegMargin + 1.0f + xoff, // x1
DotSize * ii + y * (SegSizeY + SegMargin * 2.0f) + SegMargin + 1.0f + yoff, // y2
DotSize * (jj + 1.0f) + x * (SegSizeX + SegMargin * 2.0f) + SegMargin - 1.0f + xoff, // x2
DotSize * (ii + 1.0f) + y * (SegSizeY + SegMargin * 2.0f) + SegMargin - 1.0f + yoff); // y2
brush.Reset();
brush = target.CreateSolidColorBrush(fillColor);
target.DrawRectangle(rect2, brush);
}
}
}
}
void DrawString(float x, float y, std::string const & num, Color fillColor, Color edgeColor = Color(0.0f, 0.0f, 0.0f), float xoff = 0.0f, float yoff = 0.0f)
{
auto const len = num.length();
for (std::uint32_t i = 0; i < len; i++)
DrawNumAlpha(x + static_cast<float>(i), y, num[i], fillColor, edgeColor, xoff, yoff);
}
public:
Direct2D::Factory1 & GetFactory()
{
return factory;
}
DeviceContext const & GetTarget() const
{
return target;
}
private:
void Initialize(HWND window)
{
auto const device = Direct3D::CreateDevice();
target = factory.CreateDevice(device).CreateDeviceContext();
auto dxgi = device.GetDxgiFactory();
Dxgi::SwapChainDescription1 description;
description.SwapEffect = Dxgi::SwapEffect::Discard;
swapChain =
dxgi.CreateSwapChainForHwnd(
device,
window,
description);
CreateDeviceSwapChainBitmap();
auto const dpi = factory.GetDesktopDpi();
target.SetDpi(dpi, dpi);
CreateDeviceResources();
}
public:
void ReleaseDevice()
{
target.Reset();
swapChain.Reset();
brush.Reset();
}
void Render(HWND window)
{
if (!target)
{
Initialize(window);
}
target.BeginDraw();
Draw();
target.EndDraw();
auto const hr = swapChain.Present();
if (S_OK != hr && DXGI_STATUS_OCCLUDED != hr)
{
ReleaseDevice();
}
}
void ResizeSwapChainBitmap()
{
target.SetTarget();
if (S_OK == swapChain.ResizeBuffers()) {
CreateDeviceSwapChainBitmap();
}
else {
ReleaseDevice();
}
}
private:
MyCalendar14seqDirectWrite() = delete;
MyCalendar14seqDirectWrite(MyCalendar14seqDirectWrite const &) = delete;
MyCalendar14seqDirectWrite & operator=(MyCalendar14seqDirectWrite const &) = delete;
};
}
int __stdcall wWinMain(HINSTANCE module, HINSTANCE, PWSTR, int)
{
WNDCLASS wc = {};
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hInstance = module;
wc.lpszClassName = L"CalendarProgramming";
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = [] (HWND window, UINT message, WPARAM wparam, LPARAM lparam) -> LRESULT
{
static auto const deleter = [](MyCalendar14seqDirectWrite * pmc14seqdw)
{
pmc14seqdw->ReleaseDevice();
pmc14seqdw->GetFactory().Reset();
delete pmc14seqdw;
};
static std::unique_ptr<MyCalendar14seqDirectWrite, decltype(deleter)> mc14seq(
new MyCalendar14seqDirectWrite(window));
switch (message) {
case WM_PAINT:
{
PAINTSTRUCT ps;
VERIFY(BeginPaint(window, &ps));
mc14seq->Render(window);
EndPaint(window, &ps);
return 0;
}
case WM_SIZE:
if (mc14seq->GetTarget() && SIZE_MINIMIZED != wparam) {
mc14seq->ResizeSwapChainBitmap();
mc14seq->Render(window);
}
return 0;
case WM_DISPLAYCHANGE:
mc14seq->Render(window);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(window, message, wparam, lparam);
}
};
RegisterClass(&wc);
auto const title = (boost::wformat(L"カレンダー - %4d年%02d月") % today.year() % today.month().as_number()).str();
::CreateWindow(
wc.lpszClassName,
title.c_str(),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
Width,
Height,
nullptr,
nullptr,
module,
nullptr);
MSG message;
while (auto result = GetMessage(&message, 0, 0, 0)) {
if (-1 != result)
DispatchMessage(&message);
}
return 0;
}
// Myoga S. Tomonaka 様の「14セグメントのドットマトリックスで日付を表示するカレンダー」
// ( https://gist.github.com/Myoga1012/8e56f44ecd710555a06c )
// を、mrdagonn様が制作されている「SDXFramework」
// ( http://sourceforge.jp/projects/dxframework/ )
// に移植してみました
// C++11とBoostも使用しています
#include <algorithm> // for std::transform
#include <array> // for std::array
#include <cctype> // for std::toupper
#include <cstdint> // for std::int32_t, std::uint16_t, std::uint32_t
#include <stdexcept> // for std::runtime_error
#include <string> // for std::string
#include <boost/date_time/gregorian/gregorian.hpp> // for boost::gregorian
#include <boost/format.hpp> // for boost::format
#include <boost/range/algorithm.hpp> // for boost::find
#include <SDXFramework.h>
#include <Multimedia/SDXafx.h>
namespace {
using namespace boost::gregorian;
using namespace SDX;
class MyCalendar14seqSDX final {
typedef std::array<bool, 14> segctype;
static auto const DotSize = 7; // ドットのサイズ
static auto const SegMargin = 3; // セグメントのマージン
static auto const SegSizeX = DotSize * 7; // 1セグメント当たりのサイズ
static auto const SegSizeY = DotSize * 9;
std::array<std::array<bool, 7>, 9> seg14dmt;
date const today = day_clock::local_day();
std::uint16_t const d = gregorian_calendar::end_of_month_day(today.year(), today.month());
std::int32_t const firstdow = static_cast<std::int32_t>(date(today.year(), today.month(), 1).day_of_week().as_number());
public:
MyCalendar14seqSDX()
{
System::Initialise(
(boost::format("カレンダー - %4d年%02d月") % today.year() % today.month().as_number()).str().c_str(),
1200,
600);
Screen::SetBackColor(Color(255, 255, 255));
}
~MyCalendar14seqSDX()
{
System::End();
}
private:
// sourceの値が、targetのリストのいずれかとマッチするかどうかを判別します。
bool AnyOneOfMatch(char source, std::vector<char> const & target) const
{
return target.end() != boost::find(target, source);
}
// 14セグメント符号から7×9のドットマトリックスを構成します。
void Convert14segToDotMatrix(segctype const & seg14)
{
for (auto & v : seg14dmt)
for (auto & val : v)
val = false;
// 水平1
for (auto i = 1; i < 6; i++) {
seg14dmt[0][i] = seg14[0];
seg14dmt[8][i] = seg14[3];
}
// 水平
for (auto i = 1; i < 3; i++) {
seg14dmt[0][i] = seg14dmt[0][i + 3] = seg14[0];
seg14dmt[8][i] = seg14dmt[8][i + 3] = seg14[3];
seg14dmt[4][i] = seg14[6];
seg14dmt[4][i + 3] = seg14[7];
}
// 垂直
for (auto i = 1; i < 4; i++) {
seg14dmt[i][0] = seg14[5];
seg14dmt[i][3] = seg14[8];
seg14dmt[i][6] = seg14[1];
seg14dmt[i + 4][0] = seg14[4];
seg14dmt[i + 4][3] = seg14[9];
seg14dmt[i + 4][6] = seg14[2];
}
// ナナメ
seg14dmt[1][1] = seg14[10];
seg14dmt[1][5] = seg14[11];
seg14dmt[7][5] = seg14[12];
seg14dmt[7][1] = seg14[13];
for (auto i = 2; i < 4; i++) {
seg14dmt[i][2] = seg14[10];
seg14dmt[i][4] = seg14[11];
seg14dmt[i + 3][4] = seg14[12];
seg14dmt[i + 3][2] = seg14[13];
}
// クロスポイント
seg14dmt[0][0] = seg14[0] || seg14[5] || seg14[10];
seg14dmt[0][3] = seg14[0] || seg14[8];
seg14dmt[0][6] = seg14[0] || seg14[1] || seg14[11];
seg14dmt[4][6] = seg14[1] || seg14[2] || seg14[7];
seg14dmt[8][6] = seg14[2] || seg14[3] || seg14[12];
seg14dmt[8][3] = seg14[3] || seg14[9];
seg14dmt[8][0] = seg14[3] || seg14[4] || seg14[13];
seg14dmt[4][0] = seg14[4] || seg14[5] || seg14[6];
seg14dmt[4][3] = seg14[6] || seg14[7] || seg14[8] || seg14[9] || seg14[10] || seg14[11] || seg14[12] || seg14[13];
}
// 数値 -> 14セグメント符号
segctype DecodeFor14seg(char dec) const
{
if (!(dec >= '0' && dec <= '9' || dec >= 'A' && dec <= 'Z' || dec == ' '))
throw std::runtime_error("対応していない文字が関数DecodeFor14segの引数decに渡されました");
return segctype{{
!AnyOneOfMatch(dec, { '1', '4', 'H', 'J', 'K', 'L', 'M', 'N', 'U', 'V', 'W', 'X', 'Y', ' ' }),
!AnyOneOfMatch(dec, { '5', '6', 'C', 'E', 'F', 'G', 'I', 'K', 'L', 'S', 'T', 'V', 'X', 'Z', ' ' }),
!AnyOneOfMatch(dec, { '2', 'C', 'E', 'F', 'I', 'K', 'L', 'P', 'R', 'T', 'V', 'X', 'Y', 'Z', ' ' }),
!AnyOneOfMatch(dec, { '1', '4', '7', 'A', 'F', 'H', 'K', 'M', 'N', 'P', 'R', 'T', 'V', 'W', 'X', 'Y', ' ' }),
!AnyOneOfMatch(dec, { '1', '3', '4', '5', '7', '9', 'B', 'D', 'I', 'S', 'T', 'X', 'Y', 'Z', ' ' }),
!AnyOneOfMatch(dec, { '1', '2', '3', '7', 'B', 'D', 'I', 'J', 'T', 'X', 'Z', ' ' }),
AnyOneOfMatch(dec, { '2', '3', '4', '5', '6', '8', '9', 'A', 'E', 'F', 'H', 'K', 'P', 'R', 'S', 'Y' }),
AnyOneOfMatch(dec, { '2', '3', '4', '5', '6', '8', '9', 'A', 'B', 'E', 'F', 'G', 'H', 'P', 'R', 'S', 'Y' }),
AnyOneOfMatch(dec, { 'B', 'D', 'I', 'T' }),
AnyOneOfMatch(dec, { 'B', 'D', 'I', 'T', 'Y' }),
AnyOneOfMatch(dec, { 'M', 'N', 'X' }),
AnyOneOfMatch(dec, { '0', 'K', 'M', 'V', 'X', 'Z' }),
AnyOneOfMatch(dec, { 'K', 'N', 'Q', 'R', 'W', 'X' }),
AnyOneOfMatch(dec, { '0', 'V', 'W', 'X', 'Z' })
}};
}
public:
void Draw()
{
auto month(today.month().as_long_string());
std::transform(month.begin(), month.end(), month.begin(), std::toupper);
while (System::Update()) {
// 年月を描画します
DrawString(
0,
0,
(boost::format("%s %4d") % month % today.year()).str(),
Color(128, 255, 128),
Color(0, 255, 0),
10,
10);
// 日付を描画します。
for (auto i = 1, seq = firstdow; i <= d; i++, seq++) {
auto const dow = seq % 7;
DrawDate(
dow,
seq / 7 + 1,
i,
dow ? (dow == 6 ? Color(0, 255, 255) : Color(255, 255, 255)) : Color(255, 128, 239),
dow ? (dow == 6 ? Color(36, 100, 255) : Color(170, 170, 170)) : Color(255, 0, 255),
10,
40);
}
// Enterで終了
if (Input::key.Return.on)
break;
}
}
private:
void DrawDate(std::uint32_t x, std::uint32_t y, std::uint32_t day, Color fillColor, Color edgeColor = Color(0, 0, 0), std::uint32_t xoff = 0, std::uint32_t yoff = 0)
{
if (day >= 1 && day <= 31) {
auto const ten = static_cast<char>(day / 10), one = static_cast<char>(day % 10);
DrawNumAlpha(
x * 3,
y,
ten ? ten + '0' : ' ',
fillColor,
edgeColor,
xoff,
yoff);
DrawNumAlpha(
x * 3 + 1,
y,
one + '0',
fillColor,
edgeColor,
xoff,
yoff);
}
else {
throw std::runtime_error("引数dayの日付が1日未満か32日以上です");
}
}
void DrawNumAlpha(std::uint32_t x, std::uint32_t y, char na, Color fillColor, Color edgeColor = Color(0, 0, 0), std::uint32_t xoff = 0, std::uint32_t yoff = 0)
{
if (!(na >= '0' && na <= '9' || na >= 'A' && na <= 'Z' || na == ' '))
throw std::runtime_error("対応していない文字が関数DrawNumAlphaの引数naに渡されました");
Convert14segToDotMatrix(DecodeFor14seg(na));
// ドットマトリックスを表示します。
for (auto i = 0; i < 9; i++) {
for (auto j = 0; j < 7; j++) {
if (seg14dmt[i][j]) {
Rect(
DotSize * j + x * (SegSizeX + SegMargin * 2) + SegMargin + xoff, // x
DotSize * i + y * (SegSizeY + SegMargin * 2) + SegMargin + yoff, // y
DotSize, // 高さ
DotSize) // 幅
.Draw(edgeColor, 255);
Rect(
DotSize * j + x * (SegSizeX + SegMargin * 2) + SegMargin + 1 + xoff, // x
DotSize * i + y * (SegSizeY + SegMargin * 2) + SegMargin + 1 + yoff, // y
DotSize - 2, // 高さ
DotSize - 2) // 幅
.Draw(fillColor, 255);
}
}
}
}
void DrawString(std::uint32_t x, std::uint32_t y, std::string const & num, Color fillColor, Color edgeColor = Color(0, 0, 0), std::uint32_t xoff = 0, std::uint32_t yoff = 0)
{
auto const len = num.length();
for (std::uint32_t i = 0; i < len; i++)
DrawNumAlpha(x + i, y, num[i], fillColor, edgeColor, xoff, yoff);
}
MyCalendar14seqSDX(MyCalendar14seqSDX const &) = delete;
MyCalendar14seqSDX & operator=(MyCalendar14seqSDX const &) = delete;
};
}
int main(int argc, char* argv[])
{
MyCalendar14seqSDX().Draw();
return EXIT_SUCCESS;
}
// C++14でTemplateとconstexprを使って書いたコード(Sproutライブラリ使用)
// 参考にさせて頂いたソースコード
// Sprout でコンパイル時 FizzBuzz - C++でゲームプログラミング(osyo-manga様)
// http://d.hatena.ne.jp/osyo-manga/20111207/1323187352
#define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION
#include <iostream>
#include <sprout/algorithm/transform.hpp>
#include <sprout/array.hpp>
#include <sprout/operation.hpp>
#include <sprout/string.hpp>
namespace {
template <typename Char>
constexpr sprout::basic_string<Char, 1>
to_string(Char c) {
return sprout::push_front(sprout::to_string(""), c);
}
template <typename T, typename Result = sprout::string<16>>
constexpr Result
itoa_impl(T n) {
return n < 10 ? sprout::realign_to<Result>(::to_string(char('0' + n)))
: sprout::realign_to<Result>(itoa_impl(n / 10) + ::to_string(char('0' + n % 10)));
}
template <typename T, typename Result = sprout::string<16>>
constexpr Result
itoa(T n) {
return n > 9 ? sprout::realign_to<Result>(itoa_impl(n))
: sprout::realign_to<Result>((" " + itoa_impl(n)));
}
template <int dow, int eom_day>
struct calendar {
typedef sprout::string<3> result_type;
constexpr result_type
operator ()(int i) const {
if (i - dow > eom_day) {
return sprout::realign_to<result_type>("");
}
else if (i > dow) {
return !(i % 7) || (i - dow) == eom_day ? sprout::realign_to<result_type>(itoa(i - dow) + "\n")
: sprout::realign_to<result_type>(itoa(i - dow) + "\t");
}
else {
return sprout::realign_to<result_type>("\t");
}
}
};
constexpr auto isleapyear(int year)
{
return year % 400 ? (year % 100 ? !(year % 4) : false) : true;
}
constexpr auto getdayofmonth(int year, int month)
{
switch (month) {
case 2:
return isleapyear(year) ? 29 : 28;
case 4:
case 6:
case 9:
case 11:
return 30;
default:
return 31;
}
}
template <int y, int m>
constexpr auto getfirstdayofweek()
{
// Zellerの公式
if (m <= 2) {
constexpr auto Y = (y - 1) % 100;
constexpr auto C = (y - 1) / 100;
return (26 * (m + 12 + 1) / 10 + Y + Y / 4 - 2 * C + C / 4) % 7;
}
else {
constexpr auto Y = y % 100;
constexpr auto C = y / 100;
return (26 * (m + 1) / 10 + Y + Y / 4 - 2 * C + C / 4) % 7;
}
}
// 現在の年月をコンパイル時に取得することはできないので、
// 定数としてコードに埋め込む
static auto constexpr YEAR = 2014; // 年
static auto constexpr MONTH = 10; // 月
}
int main()
{
auto constexpr dow = getfirstdayofweek<YEAR, MONTH>();
typedef calendar<dow, getdayofmonth(YEAR, MONTH)>::result_type string;
// 値を定義
auto constexpr source = sprout::make_common_array(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37
);
// 値から出力へ変換
auto constexpr result =
sprout::transform(
source.begin(),
source.end(),
sprout::array<string, 37>{},
calendar<dow, getdayofmonth(YEAR, MONTH)>());
// 出力処理(実行時に行う処理はこれだけ)
for (auto&& str : result){
std::cout << str;
}
}
// C++14でTemplateとconstexprを使って書いたコードその2
// Sproutライブラリに加えてBoost.Preprocessorまで使って書いてみた
// 参考にさせて頂いたソースコード
// Sprout でコンパイル時 FizzBuzz - C++でゲームプログラミング(osyo-manga様)
// http://d.hatena.ne.jp/osyo-manga/20111207/1323187352
#define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION
#include <iostream>
#include <boost/preprocessor/repetition/enum_shifted.hpp>
#include <sprout/algorithm/transform.hpp>
#include <sprout/array.hpp>
#include <sprout/operation.hpp>
#include <sprout/string.hpp>
#define DECL(z, n, text) n
#define MAXPP 38
namespace {
template <typename Char>
constexpr sprout::basic_string<Char, 1>
to_string(Char c) {
return sprout::push_front(sprout::to_string(""), c);
}
template <typename T, typename Result = sprout::string<16>>
constexpr Result
itoa_impl(T n) {
return n < 10 ? sprout::realign_to<Result>(::to_string(char('0' + n)))
: sprout::realign_to<Result>(itoa_impl(n / 10) + ::to_string(char('0' + n % 10)));
}
template <typename T, typename Result = sprout::string<16>>
constexpr Result
itoa(T n) {
return n > 9 ? sprout::realign_to<Result>(itoa_impl(n))
: sprout::realign_to<Result>((" " + itoa_impl(n)));
}
template <int dow, int eom_day>
struct calendar {
typedef sprout::string<3> result_type;
constexpr result_type
operator ()(int i) const {
if (i - dow > eom_day) {
return sprout::realign_to<result_type>("");
}
else if (i > dow) {
return !(i % 7) || (i - dow) == eom_day ? sprout::realign_to<result_type>(itoa(i - dow) + "\n")
: sprout::realign_to<result_type>(itoa(i - dow) + "\t");
}
else {
return sprout::realign_to<result_type>("\t");
}
}
};
constexpr auto isleapyear(int year)
{
return year % 400 ? (year % 100 ? !(year % 4) : false) : true;
}
constexpr auto getdayofmonth(int year, int month)
{
switch (month) {
case 2:
return isleapyear(year) ? 29 : 28;
case 4:
case 6:
case 9:
case 11:
return 30;
default:
return 31;
}
}
template <int y, int m>
constexpr auto getfirstdayofweek()
{
// Zellerの公式
if (m <= 2) {
auto constexpr Y = (y - 1) % 100;
auto constexpr C = (y - 1) / 100;
return (26 * (m + 12 + 1) / 10 + Y + Y / 4 - 2 * C + C / 4) % 7;
}
else {
auto constexpr Y = y % 100;
auto constexpr C = y / 100;
return (26 * (m + 1) / 10 + Y + Y / 4 - 2 * C + C / 4) % 7;
}
}
// 現在の年月をコンパイル時に取得することはできないので、
// 定数としてコードに埋め込む
static auto constexpr YEAR = 2014; // 年
static auto constexpr MONTH = 10; // 月
}
int main()
{
auto constexpr dow = getfirstdayofweek<YEAR, MONTH>();
typedef calendar<dow, getdayofmonth(YEAR, MONTH)>::result_type string;
// 値を定義
auto constexpr source = sprout::make_common_array(
BOOST_PP_ENUM_SHIFTED(MAXPP, DECL, nil)
);
// 値から出力へ変換
auto constexpr result =
sprout::transform(
source.begin(),
source.end(),
sprout::array<string, MAXPP - 1>{},
calendar<dow, getdayofmonth(YEAR, MONTH)>());
// 出力処理(実行時に行う処理はこれだけ)
for (auto&& str : result){
std::cout << str;
}
}
// DirectWriteを使って書いたコード
// Kenny Kerr 様の
// 「DirectX プログラミング用の最新 C++ ライブラリ」
// ( http://msdn.microsoft.com/ja-jp/magazine/dn201741.aspx )
// を使用させて頂いています。また、このライブラリのサンプルコード
// ( http://dx.codeplex.com/SourceControl/latest )
// を参考にさせて頂いています。
// 例によってC++11とBoostも使用しています。
#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "user32.lib")
#pragma warning(disable: 4706)
#include <string>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/format.hpp>
#include "dx.h"
namespace {
using namespace boost::gregorian;
using namespace KennyKerr;
using namespace KennyKerr::Direct2D;
static SolidColorBrush brush;
auto const COLOR_BLACK = Color(0.0f, 0.0f, 0.0f);
auto const COLOR_BLUE = Color(0.26f, 0.56f, 0.87f);
auto const COLOR_RED = Color(1.0f, 0.0f, 0.0f);
auto const COLOR_WHITE = Color(1.0f, 1.0f, 1.0f);
static Factory1 factory;
static DirectWrite::Factory2 factory2;
static DirectWrite::TextFormat format;
static auto height = 480;
static Dxgi::SwapChain1 swapChain;
static DeviceContext target;
static DirectWrite::TextLayout textLayout;
static auto const today = day_clock::local_day();
static auto const firstdow = date(today.year(), today.month(), 1).day_of_week().as_number();
static auto const d = gregorian_calendar::end_of_month_day(today.year(), today.month());
static auto const wdays = { L'日', L'月', L'火', L'水', L'木', L'金', L'土' };
static auto width = 640;
void CreateDeviceIndependentResources()
{
using namespace KennyKerr::DirectWrite;
factory2 = DirectWrite::CreateFactory();
format = factory2.CreateTextFormat(
L"Candara",
40.0f);
format.SetTextAlignment(TextAlignment::Leading);
format.SetParagraphAlignment(ParagraphAlignment::Near);
}
void CreateDeviceResources()
{
brush = target.CreateSolidColorBrush(COLOR_BLACK);
}
void CreateDeviceSwapChainBitmap()
{
auto const props = BitmapProperties1(
BitmapOptions::Target | BitmapOptions::CannotDraw,
PixelFormat(Dxgi::Format::B8G8R8A8_UNORM, AlphaMode::Ignore));
target.SetTarget(
target.CreateBitmapFromDxgiSurface(
swapChain,
props));
}
void Draw()
{
target.Clear(COLOR_WHITE);
auto const size = target.GetSize();
auto const text = (boost::wformat(L"%d年 %d月") % today.year() % today.month().as_number()).str();
textLayout = factory2.CreateTextLayout(
text.c_str(),
text.length(),
format,
size.Width,
size.Height);
target.DrawTextLayout(
Point2F(140.0f, 20.0f),
textLayout,
brush);
for (std::size_t i = 0; i < wdays.size(); i++) {
auto const youbi = std::wstring(1, *(wdays.begin() + i));
textLayout = factory2.CreateTextLayout(
youbi.c_str(),
youbi.length(),
format,
size.Width,
size.Height);
target.DrawTextLayout(
Point2F(static_cast<float>(i)* 60.0f + 30.0f, 65.0f),
textLayout,
brush);
}
for (auto i = static_cast<int>(firstdow), sw = 1; sw <= d; i++, sw++) {
auto const str = (boost::wformat(L"%2d") % sw).str();
auto const dow = i % 7;
switch (dow) {
case 0:
brush = target.CreateSolidColorBrush(COLOR_RED);
break;
case 6:
brush = target.CreateSolidColorBrush(COLOR_BLUE);
break;
default:
brush = target.CreateSolidColorBrush(COLOR_BLACK);
break;
}
textLayout = factory2.CreateTextLayout(
str.c_str(),
str.length(),
format,
size.Width,
size.Height);
target.DrawTextLayout(
Point2F(dow * 60.0f + 30.0f, static_cast<float>(i / 7) * 45.0f + 110.0f),
textLayout,
brush);
}
}
void ReleaseDevice()
{
target.Reset();
swapChain.Reset();
brush.Reset();
}
void Render(HWND window)
{
if (!target)
{
auto device = Direct3D::CreateDevice();
target = factory.CreateDevice(device).CreateDeviceContext();
auto dxgi = device.GetDxgiFactory();
Dxgi::SwapChainDescription1 description;
description.SwapEffect = Dxgi::SwapEffect::Discard;
swapChain = dxgi.CreateSwapChainForHwnd(device,
window,
description);
CreateDeviceSwapChainBitmap();
auto const dpi = factory.GetDesktopDpi();
target.SetDpi(dpi, dpi);
CreateDeviceResources();
}
target.BeginDraw();
Draw();
target.EndDraw();
auto const hr = swapChain.Present();
if (S_OK != hr && DXGI_STATUS_OCCLUDED != hr)
{
ReleaseDevice();
}
}
void ResizeSwapChainBitmap()
{
target.SetTarget();
if (S_OK == swapChain.ResizeBuffers()) {
CreateDeviceSwapChainBitmap();
}
else {
ReleaseDevice();
}
}
}
int __stdcall wWinMain(HINSTANCE module, HINSTANCE, PWSTR, int)
{
factory = CreateFactory();
CreateDeviceIndependentResources();
WNDCLASS wc = {};
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hInstance = module;
wc.lpszClassName = L"CalendarProgramming";
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = [] (HWND window, UINT message, WPARAM wparam, LPARAM lparam) -> LRESULT
{
switch (message) {
case WM_PAINT:
{
PAINTSTRUCT ps;
VERIFY(BeginPaint(window, &ps));
Render(window);
EndPaint(window, &ps);
return 0;
}
case WM_SIZE:
if (target && SIZE_MINIMIZED != wparam) {
ResizeSwapChainBitmap();
Render(window);
}
return 0;
case WM_DISPLAYCHANGE:
Render(window);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(window, message, wparam, lparam);
}
};
RegisterClass(&wc);
::CreateWindow(
wc.lpszClassName,
L"カレンダープログラミング",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
nullptr,
nullptr,
module,
nullptr);
MSG message;
while (auto result = GetMessage(&message, 0, 0, 0)) {
if (-1 != result)
DispatchMessage(&message);
}
ReleaseDevice();
factory.Reset();
return 0;
}
// OpenGL (GLUT)を使って書いたコード
// Pocol 様の
//「日本語フォント」- Project ASURA
// ( http://asura.iaigiri.com/OpenGL/gl58.html )
// を参考にさせて頂きました。
// 例によってC++11とBoostも使用しています。
#include <cstdlib>
#include <memory>
#include <string>
#include <type_traits>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/format.hpp>
#include <boost/optional.hpp>
#include <GL/glut.h>
#include <windows.h>
namespace {
using namespace boost::gregorian;
static auto const deleter = [](HFONT p)
{
if (p) {
::DeleteObject(p);
p = nullptr;
}
};
void destruct(boost::optional<int> & listBaseU, boost::optional<int> & strLength)
{
glDeleteLists(*listBaseU, *strLength);
listBaseU = boost::none;
strLength = boost::none;
}
class BitmapFont final {
std::unique_ptr<std::remove_pointer<HFONT>::type, decltype(deleter)> fontU;
HDC hDC;
boost::optional<int> listBaseU = boost::none;
boost::optional<int> strLength = boost::none;
public:
BitmapFont() {}
~BitmapFont()
{
if (listBaseU)
destruct(listBaseU, strLength);
}
bool CreateW(std::wstring const & fontname, int size)
{
fontU = std::unique_ptr<std::remove_pointer<HFONT>::type, decltype(deleter)>(
::CreateFontW(
size, // フォント高さ.
0, // 文字幅.
0, // テキストの角度.
0, // ベースラインとx軸との角度.
FW_REGULAR, // フォントの重さ(太さ).
FALSE, // イタリック体.
FALSE, // アンダーライン.
FALSE, // 打ち消し線.
SHIFTJIS_CHARSET, // 文字セット.
OUT_DEFAULT_PRECIS, // 出力精度.
CLIP_DEFAULT_PRECIS, // クリッピング精度.
ANTIALIASED_QUALITY, // 出力品質.
FIXED_PITCH | FF_MODERN, // ピッチとファミリー.
fontname.c_str()), // 書体名.
deleter);
if (!fontU)
return false;
hDC = wglGetCurrentDC();
::SelectObject(hDC, fontU.get());
return true;
}
void DrawStringW(std::wstring const & str)
{
// 以前のディスプレイリストがある場合は削除.
if (listBaseU)
destruct(listBaseU, strLength);
// ディスプレイリスト作成.
strLength = static_cast<int>(str.length());
listBaseU = glGenLists(*strLength);
::SelectObject(hDC, fontU.get());
for (auto i = 0; i < strLength; i++) {
//ディスプレイリストに格納.
auto const result =
::wglUseFontBitmapsW(
hDC,
str[i],
1,
*listBaseU + static_cast<DWORD>(i));
// 格納失敗時.
if (!result) {
destruct(listBaseU, strLength);
return;
}
}
// ディスプレイリストで描画.
for (auto i = 0; i < strLength; i++)
glCallList(*listBaseU + i);
// ディスプレイリスト破棄.
destruct(listBaseU, strLength);
}
BitmapFont(BitmapFont const &) = delete;
BitmapFont & operator=(BitmapFont const &) = delete;
};
// 日本語フォント表示用
static BitmapFont font;
static auto height = 480;
static auto const today = day_clock::local_day();
static auto const firstdow = date(today.year(), today.month(), 1).day_of_week().as_number();
static auto const d = gregorian_calendar::end_of_month_day(today.year(), today.month());
static auto const wdays = { L'日', L'月', L'火', L'水', L'木', L'金', L'土' };
static auto width = 640;
bool InitializeFunc()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
return font.CreateW(L"MS ゴシック", 24);
}
void Render2D()
{
// 3D → 2D
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, width, height, 0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
//
// 文字列描画.
//
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
glRasterPos2i(185, 20);
font.DrawStringW((boost::wformat(L"%d年 %d月") % today.year() % today.month().as_number()).str());
for (std::size_t i = 0; i < wdays.size(); i++) {
glRasterPos2i(i * 60 + 30, 40);
font.DrawStringW(std::wstring(1, *(wdays.begin() + i)));
}
for (auto i = static_cast<int>(firstdow), sw = 1; sw <= d; i++, sw++) {
auto const str = (boost::wformat(L"%2d") % sw).str();
auto const dow = i % 7;
switch (dow) {
case 0:
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
break;
case 6:
glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
break;
default:
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
break;
}
glRasterPos2i(dow * 60 + 30, i / 7 * 20 + 60);
font.DrawStringW(str);
}
// 2D → 3D
glPopMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
}
int main(int argc, char** argv)
{
__glutInitWithExit(&argc, argv, [](int code) { std::exit(code); });
glutInitWindowSize(width, height);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow("カレンダープログラミング");
glutDisplayFunc([]()
{
// バックバッファをクリア.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 2Dシーンの描画.
Render2D();
// ダブルバッファ.
glutSwapBuffers();
});
glutIdleFunc([]() { glutPostRedisplay(); });
glutReshapeFunc([](int w, int h)
{
width = w;
height = h;
auto const aspectRatio = static_cast<double>(w) / static_cast<double>(h);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, aspectRatio, 0.1, 1000.0);
});
if (!InitializeFunc())
return EXIT_FAILURE;
glutMainLoop();
return EXIT_SUCCESS;
}
// C++14で書いたコードは本質的にこのコードと同じだったりします
#include <iostream>
static auto constexpr result =
{ "\t", "\t", "\t", " 1\t", " 2\t", " 3\t", " 4\n",
" 5\t", " 6\t", " 7\t", " 8\t", " 9\t", "10\t", "11\n",
"12\t", "13\t", "14\t", "15\t", "16\t", "17\t", "18\n",
"19\t", "20\t", "21\t", "22\t", "23\t", "24\t", "25\n",
"26\t", "27\t", "28\t", "29\t", "30\t", "31\n", "",
"", ""
};
int main()
{
for (auto&& str : result) {
std::cout << str;
}
}
// 「PSPSDK」と「DXライブラリPortable v0.5.7 UTF-8」を使って書いたコード
// PlayStation Portable (PSP)上でカレンダーを表示します。
// 猫山猫宗 様のブログ「PSP xvi」
// ( http://nekoyama2gillien.blog36.fc2.com/ )
// が大変参考になりました(「DXライブラリPortable v0.5.7 UTF-8」も、上記のサイト
// にて配布されていたものを使わせて頂きました)。
// このコードは、上記サイトにて配布されている「DXLibPortable v0.5.7用 ひながた」
// を改変して利用させて頂いています。以下は、そのコードのコメントの引用となりま
// す。
//------------------------------------------------------------------------------
// 正規PSP開発も可能 DXライブラリPortable v0.5.7 プログラミング 雛形
//
// 前回公開した物が正規PSPでは動作しないコードだったので見直し
// ヒープサイズの容量指定とスタックサイズの容量指定を追加したらうまくいった
//
// なにもしませんが、PSP君はやる気になっていますので
// 画像表示命令とかを Action関数に書いてみて下さい
//
// イントラフォントはUTF8コードのみ、みたいです。シフトJISは廃止っぽい(?)
//
// これは BSDライセンスとします
//------------------------------------------------------------------------------
#include <dxlibp.h>
namespace {
int getfirstdayofweek(int year, int month)
{
// Zellerの公式
if (month > 2) {
int const Y = year % 100;
int const C = year / 100;
return (26 * (month + 1) / 10 + Y + Y / 4 - 2 * C + C / 4) % 7;
}
else {
return getfirstdayofweek(year - 1, month + 12);
}
}
class MyCalendarPSP {
static int const FONTSIZE = 12;
static int const DAYS[];
static char const WDAYS[7][4];
int firstdow_;
int month_;
int year_;
public:
MyCalendarPSP()
{
DATEDATA ddata;
GetDateTime(&ddata);
firstdow_ = getfirstdayofweek(ddata.Year, ddata.Mon);
month_ = ddata.Mon;
year_ = ddata.Year;
DxLib_Init();
ScreenSettings();
ChangeFontType(DX_FONTTYPE_NORMAL); // エッジ無しノーマル文字にする(IntraFont)
}
~MyCalendarPSP()
{
DxLib_End();
}
private:
void ScreenSettings()
{
SetDisplayFormat(DXP_FMT_8888); // 画面のピクセルフォーマットを32Bit色モードに
SetWaitVSyncFlag(TRUE); // 画面更新の際、垂直同期待ちをしてから行なう様に
SetDrawArea(0, 0, 480, 272); // 描画可能領域を全領域に設定
SetDrawMode(DX_DRAWMODE_NEAREST); // 描画モードを高速なNEARESTにセットする
SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0); // 描画の際のブレンドモードを、標準モードに
SetDrawBright(255, 255, 255); // 描画する色の輝度を最大に
SetGraphMode(480, 272, DXP_FMT_8888); // フル画面サイズ & 32Bit色モード
ClearDrawScreen(); // 描画先のグラフィックスをクリアする
DrawBox(0, 0, 480, 272, DXP_COLOR_WHITE, TRUE); // 画面を白色で塗りつぶし
}
public:
void ShowDisplay()
{
SetFontSize(FONTSIZE); // フォントサイズ設定
ChangeFontType(DX_FONTTYPE_NORMAL); // エッジ無しフォント
DrawFormatString(185, FONTSIZE, DXP_COLOR_BLACK, "%d年 %d月", year_, month_);
for (int i = 0; i < 7; i++) {
DrawFormatString(
i * 60 + 40,
static_cast<int>(static_cast<double>(FONTSIZE) * 2.5),
DXP_COLOR_BLACK,
WDAYS[i]);
}
int d = DAYS[month_ - 1];
if ((!(year_ % 400) || (year_ % 100 && !(year_ % 4))) && month_ == 2)
d++;
for (int i = firstdow_, sw = 1; sw <= d; i++, sw++) {
int const dow = i % 7;
int const xpos = sw > 9 ? dow * 60 + 30 : dow * 60 + 41;
switch (dow) {
case 0:
DrawFormatString(xpos, (i / 7 + 4) * FONTSIZE, DXP_COLOR_RED, "%d", sw);
break;
case 6:
DrawFormatString(xpos, (i / 7 + 4) * FONTSIZE, DXP_COLOR_BLUE, "%d", sw);
break;
default:
DrawFormatString(xpos, (i / 7 + 4) * FONTSIZE, DXP_COLOR_BLACK, "%d", sw);
break;
}
}
ScreenFlip(); // 画面表示
do { // 何かボタンが押されるまで待つ処理
ProcessMessage();
} while (!CheckHitKeyAll());
}
};
int const MyCalendarPSP::DAYS[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char const MyCalendarPSP::WDAYS[7][4] = { "日", "月", "火", "水", "木", "金", "土" };
}
// モジュール情報 / メインコードはユーザモード
PSP_MODULE_INFO("HINAGATA_DXP_02", PSP_MODULE_USER, 1, 0);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
PSP_HEAP_SIZE_KB(16 * 1024);
PSP_MAIN_THREAD_STACK_SIZE_KB(512);
int main()
{
MyCalendarPSP mc;
mc.ShowDisplay();
return 0;
}
// mrdagonn様が制作されている「SDXFramework」を使って書いたコード
// ( http://sourceforge.jp/projects/dxframework/ )
// C++11とBoostも使用しています
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/format.hpp>
#include <SDXFramework.h>
#include <Multimedia/SDXafx.h>
int main(int argc, char* argv[])
{
using namespace boost::gregorian;
using namespace SDX;
static auto const wdays = { "日", "月", "火", "水", "木", "金", "土" };
auto const today = day_clock::local_day();
auto const firstdow = date(today.year(), today.month(), 1).day_of_week().as_number();
auto const d = gregorian_calendar::end_of_month_day(today.year(), today.month());
System::Initialise("カレンダープログラミング", 640, 480);
Screen::SetBackColor(Color::White);
while (System::Update()) {
Drawing::String(
{ 185, 20 },
Color::Black,
(boost::format("%d年 %d月") % today.year() % today.month().as_number()).str());
for (std::size_t i = 0; i < wdays.size(); i++)
Drawing::String({ i * 60 + 30, 40 }, Color::Black, *(wdays.begin() + i));
for (auto i = static_cast<int>(firstdow), sw = 1; sw <= d; i++, sw++) {
auto const str = (boost::format("%2d") % sw).str();
auto const dow = i % 7;
switch (dow) {
case 0:
Drawing::String({ dow * 60 + 30, i / 7 * 20 + 60 }, Color::Red, str);
break;
case 6:
Drawing::String({ dow * 60 + 30, i / 7 * 20 + 60 }, Color::Aqua, str);
break;
default:
Drawing::String({ dow * 60 + 30, i / 7 * 20 + 60 }, Color::Black, str);
break;
}
}
// Enterで終了
if (Input::key.Return.on)
break;
}
System::End();
return EXIT_SUCCESS;
}
//-----------------------------------------------------------------------
// <copyright file="MyCalendarSharpDX.cs" company="dc1394's software">
// Copyright © 2014 @dc1394 All Rights Reserved.
// </copyright>
//
// C#のDirectXラッパーであるSharpDXライブラリ
// ( http://sharpdx.org/ )
// を使って書いてみたコード。以下のURLにて公開されているSharpDXライブラリのサ
// ンプルコード
// ( https://github.com/sharpdx/SharpDX-Samples )
// のうちの「DisplayFontApp」プロジェクト
// ( https://github.com/sharpdx/SharpDX-Samples/tree/master/WindowsDesktop/Direct3D9/DisplayFontApp )
// のコードを改変して利用させて頂いています。以下は、そのプロジェクトのソース
// ファイルのコメントの引用となります。
//
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//-----------------------------------------------------------------------
namespace MyCalendarSharpDX
{
using System;
using SharpDX;
using SharpDX.Direct3D9;
using SharpDX.Windows;
/// <summary>
/// Direct3D9 Font Sample
/// </summary>
internal sealed class MyCalendarSharpDX
{
#region フィールド
/// <summary>
/// 曜日の文字の配列
/// </summary>
private static readonly Char[] WDAYS = { '日', '月', '火', '水', '木', '金', '土' };
/// <summary>
/// Direct3D9デバイス
/// </summary>
private Device device;
/// <summary>
/// 現在月の初日の曜日
/// </summary>
private Int32 firstdow;
/// <summary>
/// 文字を描画するためのフォント
/// </summary>
private Font font;
/// <summary>
/// 描画対象のフォーム
/// </summary>
private RenderForm form;
/// <summary>
/// 月
/// </summary>
private Int32 month;
/// <summary>
/// 年
/// </summary>
private Int32 year;
#endregion フィールド
#region 構築
/// <summary>
/// コンストラクタ
/// </summary>
internal MyCalendarSharpDX()
{
this.firstdow = (Int32)new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).DayOfWeek;
this.form = new RenderForm("カレンダープログラミング");
var pp = new PresentParameters(this.form.ClientSize.Width, this.form.ClientSize.Height)
{
PresentationInterval = PresentInterval.One
};
this.device = new Device(
new Direct3D(),
0,
DeviceType.Hardware,
this.form.Handle,
CreateFlags.HardwareVertexProcessing,
pp);
// Initialize the Font
var fontDescription = new FontDescription()
{
Height = 30,
Italic = false,
CharacterSet = FontCharacterSet.Ansi,
FaceName = "MS ゴシック",
MipLevels = 0,
OutputPrecision = FontPrecision.TrueType,
PitchAndFamily = FontPitchAndFamily.Default,
Quality = FontQuality.ClearType
};
this.font = new Font(this.device, fontDescription);
this.month = DateTime.Now.Month;
this.year = DateTime.Now.Year;
}
#endregion 構築
#region メソッド
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
internal static void Main()
{
new MyCalendarSharpDX().Draw();
}
/// <summary>
/// フォームに描画する
/// </summary>
internal void Draw()
{
RenderLoop.Run(
this.form,
() =>
{
device.Clear(ClearFlags.Target, Color.White, 1.0f, 0);
device.BeginScene();
this.DrawString(
Color.Black,
String.Format("{0}年{1}月", this.year, this.month),
185,
20);
for (var i = 0; i < MyCalendarSharpDX.WDAYS.Length; i++)
{
this.DrawString(
Color.Black,
MyCalendarSharpDX.WDAYS[i].ToString(),
(i * 60) + 30,
50);
}
for (Int32 i = this.firstdow, sw = 1; sw <= DateTime.DaysInMonth(this.year, this.month); i++, sw++)
{
var dow = i % 7;
var xpos = sw > 9 ? (dow * 60) + 30 : (dow * 60) + 45;
switch (dow)
{
case 0:
this.DrawString(
Color.Red,
sw.ToString(),
xpos,
(i / 7 * 25) + 80);
break;
case 6:
this.DrawString(
Color.Cyan,
sw.ToString(),
xpos,
(i / 7 * 25) + 80);
break;
default:
this.DrawString(
Color.Black,
sw.ToString(),
xpos,
(i / 7 * 25) + 80);
break;
}
}
device.EndScene();
device.Present();
});
}
/// <summary>
/// 文字を描画する
/// </summary>
/// <param name="color">文字色</param>
/// <param name="displayText">描画対象の文字列</param>
/// <param name="x">文字を描画する位置(x座標)</param>
/// <param name="y">文字を描画する位置(y座標)</param>
private void DrawString(ColorBGRA color, String displayText, Int32 x, Int32 y)
{
// Measure the text to display
var fontDimension = this.font.MeasureText(
null,
displayText,
new Rectangle(x, y, this.form.ClientSize.Width, this.form.ClientSize.Height),
FontDrawFlags.Left | FontDrawFlags.Top);
// Draw the text
this.font.DrawText(null, displayText, fontDimension, FontDrawFlags.Left | FontDrawFlags.Top, color);
}
#endregion メソッド
}
}
//-----------------------------------------------------------------------
// <copyright file="MyCalendarSlimDX.cs" company="dc1394's software">
// Copyright © 2014 @dc1394 All Rights Reserved.
// </copyright>
//
// C#のDirectXラッパーである、SlimDXライブラリを使って書いてみたコード
// 参考にさせて頂いたソースコード
// 「SlimDX-DirectX機能による文字描画」 - csharpgamedev @ ウィキ
// ( http://www21.atwiki.jp/csharpgamedev/pages/41.html )
//-----------------------------------------------------------------------
namespace MyCalendarSlimDX
{
using System;
using System.Drawing;
using SlimDX;
using SlimDX.Direct3D9;
using SlimDX.SampleFramework;
/// <summary>
/// カレンダーを表示するクラス
/// </summary>
internal sealed class MyCalendarSlimDX : Sample
{
#region フィールド
/// <summary>
/// 曜日の文字の配列
/// </summary>
private static readonly Char[] WDAYS = { '日', '月', '火', '水', '木', '金', '土' };
/// <summary>
/// 現在月の初日の曜日
/// </summary>
private Int32 firstdow;
/// <summary>
/// SlimDXフォント
/// </summary>
private SlimDX.Direct3D9.Font font;
/// <summary>
/// 月
/// </summary>
private Int32 month;
/// <summary>
/// スプライト
/// </summary>
private Sprite sprite;
/// <summary>
/// 年
/// </summary>
private Int32 year;
#endregion フィールド
#region 構築
/// <summary>
/// コンストラクタ
/// </summary>
internal MyCalendarSlimDX()
{
this.firstdow = (Int32)new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).DayOfWeek;
this.month = DateTime.Now.Month;
this.year = DateTime.Now.Year;
}
#endregion 構築
#region プロパティ
/// <summary>
/// デバイスの取得
/// </summary>
private Device Device
{
get { return this.Context9.Device; }
}
#endregion プロパティ
#region 破棄
/// <summary>
/// Dispose
/// </summary>
/// <param name="disposeManagedResources">フォントとスプライトをDisposeするかどうか</param>
protected override void Dispose(bool disposeManagedResources)
{
if (disposeManagedResources)
{
this.font.Dispose();
this.sprite.Dispose();
}
base.Dispose(disposeManagedResources);
}
#endregion 破棄
#region メソッド
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
internal static void Main()
{
using (var mcsd = new MyCalendarSlimDX())
{
mcsd.Run();
}
}
/// <summary>
/// ウィンドウの要素を設定して、それを返す
/// </summary>
/// <returns>ウィンドウの要素</returns>
protected override SampleConfiguration OnConfigure()
{
var config = new SampleConfiguration()
{
WindowTitle = "カレンダープログラミング",
WindowWidth = 640,
WindowHeight = 480
};
return config;
}
/// <summary>
/// 初期化
/// </summary>
protected override void OnInitialize()
{
var settings = new DeviceSettings9
{
AdapterOrdinal = 0,
CreationFlags = CreateFlags.HardwareVertexProcessing,
Width = WindowWidth,
Height = WindowHeight
};
this.InitializeDevice(settings);
// SlimDXフォントを作成
this.font = new SlimDX.Direct3D9.Font(this.Device, new System.Drawing.Font("MS ゴシック", 20, FontStyle.Regular));
this.sprite = new Sprite(this.Device);
}
/// <summary>
/// 描画
/// </summary>
protected override void OnRender()
{
// 文字を描画
this.sprite.Begin(SpriteFlags.AlphaBlend);
this.font.DrawString(
this.sprite,
String.Format("{0}年{1}月", this.year, this.month),
185,
20,
new Color4(Color.Black));
for (var i = 0; i < MyCalendarSlimDX.WDAYS.Length; i++)
{
this.font.DrawString(
this.sprite,
MyCalendarSlimDX.WDAYS[i].ToString(),
(i * 60) + 30,
50,
new Color4(Color.Black));
}
for (Int32 i = this.firstdow, sw = 1; sw <= DateTime.DaysInMonth(this.year, this.month); i++, sw++)
{
var dow = i % 7;
var xpos = sw > 9 ? (dow * 60) + 30 : (dow * 60) + 45;
switch (dow)
{
case 0:
this.font.DrawString(
this.sprite,
sw.ToString(),
xpos,
(i / 7 * 25) + 80,
new Color4(Color.Red));
break;
case 6:
this.font.DrawString(
this.sprite,
sw.ToString(),
xpos,
(i / 7 * 25) + 80,
new Color4(Color.Cyan));
break;
default:
this.font.DrawString(
this.sprite,
sw.ToString(),
xpos,
(i / 7 * 25) + 80,
new Color4(Color.Black));
break;
}
}
this.sprite.End();
}
/// <summary>
/// 描画の前準備
/// </summary>
protected override void OnRenderBegin()
{
Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, new Color4(1.0f, 1.0f, 1.0f), 1.0f, 0);
Device.BeginScene();
}
/// <summary>
/// 描画の後処理
/// </summary>
protected override void OnRenderEnd()
{
Device.EndScene();
Device.Present();
}
/// <summary>
/// リソースの構築。初期化やデバイスロスト後などに呼ばれる
/// </summary>
protected override void OnResourceLoad()
{
// ここでOnResetDeviceを呼ぶ必要がある
this.font.OnResetDevice();
this.sprite.OnResetDevice();
}
/// <summary>
/// デバイスロスト時などに呼ばれる
/// </summary>
protected override void OnResourceUnload()
{
// ここでOnLostDeviceを呼ぶ必要がある
this.font.OnLostDevice();
this.sprite.OnLostDevice();
}
#endregion メソッド
}
}
#include <iostream>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/format.hpp>
int main()
{
using namespace boost::gregorian;
auto const today = day_clock::local_day();
auto const dow = date(today.year(), today.month(), 1).day_of_week();
auto const d = gregorian_calendar::end_of_month_day(today.year(), today.month());
for (auto sw = 0, i = 1; sw < d; i++) {
if (i > dow)
std::cout << boost::format("%2d") % ++sw;
std::cout << (i % 7 && sw != d ? '\t' : '\n');
}
}
/* WonderWitchで書いたコード
猪木貴裕 様の
「内蔵フォントを、スクリーン2とスプライトを使って19行表示するライブラリ」
( http://www.wonderwitch.com/freedata/s005/string12.zip )
のソースコード、「string12.c」を参考にさせて頂きました。
コンパイラオプションは以下のようにしました:
lcc86 -o MyCalendarWW.bin MyCalendarWW.c c:\WWitch\lib\libwwc.lib
*/
#include <sys/bios.h>
#include <sys/libwwc.h>
#include <sys/timer.h>
#include <stdio.h>
#define BUFSIZE 16
#define ST_BASE 1
#define SP_BASE 0
static unsigned long bmp_clear[] =
{
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000,
};
static int const days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static unsigned int const pal_string[] =
{
0xfff, 0x844, 0x484, 0x448, 0xf88, 0x8f8, 0x88f, 0xccf, 0xfcc, 0xf00,
0x0f0, 0x00f, 0xff0, 0xf0f, 0x0ff, 0x000,
};
/* 偶数がスクリーン2のY、奇数がスプライトのY */
static int const sy12[] = { 0, 12, 3, 36, 6, 60, 9, 84, 12, 108, 15, 132 };
static char const wdays[7][3] = { "日", "月", "火", "水", "木", "金", "土" };
int gSP_total = SP_BASE;
int gST_total = ST_BASE;
void color_text_put_string(int sx, int sy, int surfacecolor, int backcolor, int scpal, int sppal, const char far c_string[]);
void screendraw(int screen, int x, int y, int w, int h, int pal, int charno);
void spritedraw(int spno, int x, int y, int w, int h);
void spriteinit(int spno, int fonno, int w, int h, int pr, int pal);
int main()
{
char buf[BUFSIZE];
datetime_t dt;
int i, y, m, a, firstdow, d, sw, dow;
wwc_set_color_mode(COLOR_MODE_16COLOR);
display_control(DCM_SCR1 + DCM_SCR2 + DCM_SPR);
wwc_clear_font();
lcd_set_segments(0x04);
for (i = 0; i < 16; i++) {
wwc_palette_set_color(0, i, pal_string[i]);
wwc_palette_set_color(8, i, pal_string[i]);
}
wwc_font_set_colordata(0, 1, bmp_clear);
screen_fill_char(SCREEN1, 0, 0, 28, 18, 0x0000);
screen_fill_char(SCREEN2, 0, 0, 28, 18, 0x0000);
rtc_get_datetime_struct(&dt);
y = dt.year + 2000;
m = dt.month;
a = dt.day_of_week - (dt.date - 1) % 7;
firstdow = a >= 0 ? a : a + 7;
d = days[m - 1];
if ((!(y % 400) || (y % 100 && !(y % 4))) && m == 2)
d++;
sprintf(buf, "%d年 %d月", y, m);
color_text_put_string(10, 1, 15, 0, 0, 8, buf);
for (i = 0; i < 7; i++)
color_text_put_string(i * 4 + 2, 2, 15, 0, 0, 8, wdays[i]);
for (i = firstdow, sw = 1; sw <= d; i++, sw++) {
sprintf(buf, "%3d", sw);
dow = i % 7;
switch (dow) {
case 0:
color_text_put_string(dow * 4, i / 7 + 3, 9, 0, 0, 8, buf);
break;
case 6:
color_text_put_string(dow * 4, i / 7 + 3, 11, 0, 0, 8, buf);
break;
default:
color_text_put_string(dow * 4, i / 7 + 3, 15, 0, 0, 8, buf);
break;
}
}
while (key_press_check() != KEY_START);
return 0;
}
/*******************************************************************************
内蔵フォントを、スクリーン2とスプライトを使って12行表示するライブラリ
16色カラー、横プレイバージョン
Takahiro Igi (Nov 29 2003)
dc1394が改変 (Oct 24 2014)
*******************************************************************************/
/*******************************************************************************
↓カラーモードで文章を表示する
引数
sx :表示する文字列の先頭のX座標(0から27まで)
sy :表示する文字列のY座標(0から11まで)
surfacecolor :文字を表示するパレット内の色番号(0から15まで)
backcolor :文字ではない部分を表示するパレット内の色番号(0から15まで)
scpal :スクリーンに表示する文字列のパレット番号(0から15まで)
sppal :スプライトに表示する文字列のパレット番号(8から15まで)
c_string[] :表示する文字列
戻り値 :なし
*******************************************************************************/
void color_text_put_string(int sx, int sy, int surfacecolor, int backcolor, int scpal, int sppal, const char far c_string[])
{
/* 表示する文字の数 */
int char_num = 0;
/* フォントデータをカラー化するためのマスクビット配列 */
unsigned char fs[4], fb[4];
{
/* フォントデータをカラー化するためのマスクビットを入れる */
int a;
for (a = 0; a < 4; a++) {
fs[a] = (((surfacecolor >> a) & 0x01) != 0) ? 0xff: 0x00;
fb[a] = (((backcolor >> a) & 0x01) != 0) ? 0xff: 0x00;
}
}
{
int c = 0, c_length;
/* 内蔵されているフォントデータ(モノクロ)を入れる配列 */
unsigned char font_data[8];
/* カラー化したフォントデータ(16色カラー)を入れる配列 */
unsigned char colordata[32];
{
/* 文字列の長さをstrlen()を使わず求める */
int j = 0;
while (c_string[j] != '\0') j++;
c_length = j;
}
while (c < c_length) {
{
/* 文字のコード番号を取得する */
unsigned char const bytecode = (unsigned char)(c_string[c]);
unsigned int sjis_code = 0; /* 1文字のコード番号 */
if (bytecode >= 0x81 &&
(bytecode <= 0x9f ||
(bytecode >= 0xe0 && bytecode <= 0xfc))) {
sjis_code = ((unsigned int)(bytecode) << 8);
sjis_code +=
(unsigned int)((unsigned char)(c_string[c + 1]));
c += 2;
}
else {
sjis_code = (unsigned int)(bytecode);
c++;
}
/* フォントデータを取得する */
text_get_fontdata(sjis_code, font_data);
}
{
/* フォントデータを16色カラーに変換する */
int i, j, k;
for (i = 0, j = 0; i < 8; i++, j += 4){
for (k = 0; k < 4; k++) {
colordata[j + k] = 0;
colordata[j + k] =
(fs[k] & font_data[i]) | (fb[k] & ~font_data[i]);
}
}
}
/* キャラクタデータを定義 */
wwc_font_set_colordata(gST_total + char_num, 1, colordata);
char_num++;
if (sx + char_num > 27) {
break;
}
}
{
if (sy & 1) {
/* スプライトで表示 */
spriteinit(gSP_total, gST_total, char_num, 1, 1, sppal);
spritedraw(gSP_total, (sx << 3), sy12[sy], char_num, 1);
gSP_total += char_num;
sprite_set_range(0, gSP_total);
}
else {
/* スクリーンに描画 */
screendraw(
SCREEN2,
sx,
sy12[sy],
char_num,
1,
scpal,
gST_total);
}
}
gST_total += char_num;
}
}
/*******************************************************************************
↓スクリーン描画関数
引数
screen :描画するスクリーン(SCREEN1 or SCREEN2)
x :表示する文字列の先頭のX座標
y :表示する文字列の先頭のY座標
w :表示する領域の幅
h :表示する領域の高さ
pal :表示する文字列のパレット番号(0から15まで)
charno :表示するキャラクタ番号の先頭の値
戻り値 :なし
*******************************************************************************/
void screendraw(int screen, int x, int y, int w, int h, int pal, int charno)
{
/* 初期値をあらかじめ入れておく */
int const wvbase = 0, wvid = 1, hwbase = 0, hwid = w;
/* パレット値やキャラクタ番号の初期値 */
unsigned int const attr = (pal << 9) + charno;
{
/* スクリーンに描画 */
int hi, hw, wi, wv;
for (hi = 0, hw = hwbase; hi < h; hi++, hw += hwid) {
for (wi = 0, wv = wvbase + hw; wi < w; wi++, wv += wvid) {
screen_fill_char(
screen,
x + wi,
y + hi,
1,
1,
(attr + (unsigned int)(wv)));
}
}
}
}
/*******************************************************************************
↓スプライトを表示する関数
引数
spno :表示するスプライト番号の先頭の値
x :表示する領域の左上のX座標
y :表示する領域の左上のY座標
w :表示する領域の幅
h :表示する領域の高さ
戻り値 :なし
*******************************************************************************/
void spritedraw(int spno, int x, int y, int w, int h)
{
int dx, dy;
int const dxm = w * 8;
int const dym = h * 8;
for (dy = 0; dy < dym; dy += 8) {
for (dx = 0; dx < dxm; dx += 8) {
sprite_set_location(spno++, x + dx, y + dy);
}
}
}
/*******************************************************************************
↓スプライトを定義する関数(スクリーン優先度対応)
引数
spno :表示するスプライト番号の先頭の値
fonno :表示するキャラクタ番号の先頭の値
w :表示する領域の幅
h :表示する領域の高さ
pr :スクリーン2に対する優先度(0:低い、1:高い)
pal :表示する文字列のパレット番号(8から15まで)
戻り値 :なし
*******************************************************************************/
void spriteinit(int spno, int fonno, int w, int h, int pr, int pal)
{
/* 初期値をあらかじめ入れておく */
int const wvbase = 0, wvid = 1, hwbase = 0, hwid = w;
/* パレット値やキャラクタ番号の初期値 */
unsigned int const attr = (pr << 13) + ((pal - 8) << 9) + fonno;
{
/* スクリーンに描画 */
int hi, hw, wi, wv;
for (hi = 0, hw = hwbase; hi < h; hi++, hw += hwid) {
for (wi = 0, wv = wvbase + hw; wi < w; wi++, wv += wvid) {
sprite_set_char(spno++, (attr + (unsigned int)(wv)));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment