遗漏的部分
This commit is contained in:
1 parent
84fb370da8
commit
0493383ee8
63 files changed
+28237
-4
No files matched your search
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Area是某个形状上的一个区域,它没有自己的帧缓冲区
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "Drawable.h"
|
||||
namespace qing {
|
||||
class Area: public Drawable {
|
||||
public:
|
||||
/* Phase Plotting Method 相图法 */
|
||||
Area(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize);
|
||||
Color _get(int x, int y) override; /* 实现接口 */
|
||||
void _p(int x, int y, Color &clr) override;
|
||||
virtual void flush(Drawable *n, bool border = false) override;
|
||||
virtual void move(int x, int y);
|
||||
protected:
|
||||
Drawable *d; /* 持有的绘制主体 */
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
namespace qing {
|
||||
|
||||
/*
|
||||
* C++ 的命令行
|
||||
*/
|
||||
|
||||
class Arguments {
|
||||
public:
|
||||
Arguments(int argc, char **argv) {
|
||||
for (int i=1; i<argc; ++i) {
|
||||
std::string item = argv[i];
|
||||
if (item.length() > 1 && item[0] == '-' && item[1] != '-') {
|
||||
for (unsigned long j=1; j<item.length(); ++j) {
|
||||
if (item.length() == 2 && i < argc-1 && argv[i+1][0] != '-') {
|
||||
std::string args = "";
|
||||
while (i < argc-1 && argv[i+1][0] != '-') {
|
||||
args += (args == "") ? "" : " ";
|
||||
args += std::string(argv[++i]);
|
||||
}
|
||||
mc.insert(std::pair(item[j], args));
|
||||
std::cout << item[j] << "=" << args << std::endl;
|
||||
} else {
|
||||
mc.insert(std::pair(item[j], ""));
|
||||
std::cout << item[j] << std::endl;
|
||||
}
|
||||
}
|
||||
} else if (item.length() > 2 && item[0] == '-' && item[1] == '-' && item[2] != '-') {
|
||||
std::string arg = get_long_param_key(item);
|
||||
size_t pos =arg.find('=');
|
||||
if (pos == (long unsigned int)-1) {
|
||||
std::cout << arg << std::endl;
|
||||
m.insert(std::pair<std::string, std::string>(arg, ""));
|
||||
} else {
|
||||
std::string k = arg.substr(0, pos);
|
||||
std::string v = arg.substr(pos+1, arg.length()-pos-1);
|
||||
std::cout << k << "=" << v << std::endl;
|
||||
m.insert(std::pair<std::string, std::string>(k, v));
|
||||
}
|
||||
|
||||
} else {
|
||||
throw WrongArgument(item);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> &get_m() {
|
||||
return m;
|
||||
}
|
||||
std::map<char, std::string> &get_mc() {
|
||||
return mc;
|
||||
}
|
||||
|
||||
class WrongArgument: std::runtime_error { /* 错的参数 */
|
||||
public:
|
||||
WrongArgument(std::string key): std::runtime_error(key) {}
|
||||
};
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> m;
|
||||
std::map<char, std::string> mc;
|
||||
|
||||
std::string get_long_param_key(std::string &s) {
|
||||
return s.substr(2, s.length() -2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "lci/Shape.h"
|
||||
#include "lci/字体绘制器.h"
|
||||
namespace qing {
|
||||
class CharShape: public Shape {
|
||||
public:
|
||||
CharShape(int w, int h, int x, int y, wchar_t wc)
|
||||
: Shape(w, h, x, y), wc(wc), 绘制(w, h) {}
|
||||
|
||||
virtual void Draw(Drawable &d, Color clr) override{
|
||||
int w = getw();
|
||||
int h = geth();
|
||||
int x = getx();
|
||||
int y = gety();
|
||||
绘制.drawvfont(&d, x, y, wc, clr);
|
||||
}
|
||||
|
||||
private:
|
||||
wchar_t wc;
|
||||
字体绘制器 绘制;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "Area.h"
|
||||
#include "InputBox.h"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
namespace qing {
|
||||
/*
|
||||
* CmdArea(命令区域)是一种特殊的Area区域
|
||||
*
|
||||
* 基层绘制方法我们已经在Area中实现了
|
||||
*/
|
||||
class CmdArea: public Area {
|
||||
public:
|
||||
CmdArea(Drawable *d, int w, int h, int x, int y, int rotate =0, int fontsize=18, bool hasBox = false);
|
||||
void Input(char c);
|
||||
void ClearInput();
|
||||
virtual void print(char *utf8, int d=0); /* FIXME: d不知道是什么*/
|
||||
void update_input();
|
||||
void delete_input();
|
||||
void clearBox();
|
||||
std::string get_input_and_clear();
|
||||
private:
|
||||
int x_f=0, y_f=0;
|
||||
std::unique_ptr<InputBox> area;
|
||||
std::mutex lock;
|
||||
std::string input = "";
|
||||
void handle_ansi_code(char *buffer);
|
||||
bool hasBox;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
namespace qing {
|
||||
|
||||
/* 32位色彩和16位色彩 */
|
||||
class Color{
|
||||
public:
|
||||
unsigned char r=0,g=0,b=0;
|
||||
Color(unsigned char r=0, unsigned char g=0, unsigned char b=0) {
|
||||
this->r=r;
|
||||
this->g=g;
|
||||
this->b=b;
|
||||
}
|
||||
};
|
||||
|
||||
extern const Color black;
|
||||
extern const Color white;
|
||||
extern const Color green;
|
||||
extern const Color blue;
|
||||
extern const Color red;
|
||||
|
||||
/* FIXME: 完成这个类定义 */
|
||||
class Color16 {
|
||||
public:
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include "fsm.h"
|
||||
#include "ThreadInterface.h"
|
||||
/*
|
||||
@qing:包含一个简易的多线程控制机制。
|
||||
需要共享内存的变量和函数声明为全局变量(通常需要带锁),
|
||||
线程中单独使用的变量和函数声明到属于它的命名空间中。
|
||||
每个线程的主函数包括了对其的流程控制代码。
|
||||
stop,setup,loop,clean函数中填入每个状态下的执行代码。
|
||||
其中需要用到的函数,又实现在后边。
|
||||
*/
|
||||
|
||||
namespace qing {
|
||||
namespace lci{
|
||||
//线程的主函数
|
||||
//-----------------------------------------------------------
|
||||
/*通常情况下,线程的主函数。*/
|
||||
|
||||
//前向声明脚本类型
|
||||
class CommonThread: public lci::Fsm, ThreadInterface {
|
||||
//一个持有资源线程的状态机类型
|
||||
public:
|
||||
//构造函数.
|
||||
//没有必要输入打印机、脚本、线程的名字,放到全局变量
|
||||
CommonThread(std::string name);
|
||||
//暂时删除复制构造函数
|
||||
CommonThread(CommonThread&) = delete;
|
||||
//如果把析构函数放在这里,将会导致纯虚函数错误
|
||||
virtual ~CommonThread();
|
||||
|
||||
//对线程名字的设置
|
||||
void SetLabel(std::string name);
|
||||
//对线程名字的获取
|
||||
std::string& GetLabel();
|
||||
//-----------------------------------------------------------
|
||||
//等待线程启动完毕
|
||||
//线程启动失败返回失败。线程启动成功或者现程结束返回成功。
|
||||
//
|
||||
//这个函数在某些情况下有可能会一直等待,直到循环结束
|
||||
bool WaitStart(unsigned long n);
|
||||
|
||||
void WaitClose();
|
||||
|
||||
virtual void StopEvent() override;
|
||||
virtual void WakeEvent() override;
|
||||
virtual void LoopEvent() override;
|
||||
virtual void ClearEvent() override;
|
||||
|
||||
void thread_main();
|
||||
|
||||
private:
|
||||
|
||||
//线程的名字
|
||||
std::string label;
|
||||
//用来存放该子线程的标识符。
|
||||
std::thread *thread = NULL;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 这个是个抽象类,子类实现抽象的内部接口后
|
||||
*
|
||||
* 可以调用它已经写好的绘制方法。
|
||||
*/
|
||||
#pragma once
|
||||
#include "Rectangle.h"
|
||||
#include "Color.h"
|
||||
#include <iostream>
|
||||
|
||||
/* 用于文字的绘制
|
||||
* FIXME: 使用类封装 */
|
||||
extern unsigned char ttu[];
|
||||
extern int ttunumber;
|
||||
extern unsigned char zzhi[];
|
||||
extern int zzhinumber;
|
||||
|
||||
namespace qing {
|
||||
class Drawable {
|
||||
public:
|
||||
/* 表示旋转方向 */
|
||||
enum class Rotate: char {
|
||||
R_0 = 0,
|
||||
R_90 = 1,
|
||||
R_180 = 2,
|
||||
R_270 = 3
|
||||
};
|
||||
|
||||
/* 非法的旋转模式 */
|
||||
class InvalidRotateMode: std::runtime_error {
|
||||
public:
|
||||
InvalidRotateMode(): std::runtime_error("Invalid rotate mode.") {}
|
||||
};
|
||||
|
||||
/*====== attr 属性区(访问器) ======*/
|
||||
Drawable(int w, int h, int x, int y, int rotate, int fontsize);
|
||||
virtual Rectangle get_size();
|
||||
virtual Rectangle get_pos();
|
||||
virtual void set_pos(Rectangle rect);
|
||||
virtual Color get_color(int x, int y);
|
||||
virtual void set_color(Color &color);
|
||||
void FontSize(int fontsize);
|
||||
int FontSize_get();
|
||||
virtual Color& getFontsColor();
|
||||
/*------ basic 基本 ------
|
||||
* 这些类需要由子类分别进行实现,但是子类不直接调用,
|
||||
* 而是由抽象基类中实现的方法调用 */
|
||||
virtual Color _get(int x, int y) = 0; /* 获取像素点像素 */
|
||||
virtual void _p(int x, int y, Color &clr) = 0; /* 绘制像素点像素 */
|
||||
//virtual void _up(int x, int y, int w, int h, int level) = 0; /* FIXME: 不使用屏幕移动函数 */
|
||||
//virtual void _down(int x, int y, int w, int h, int level) = 0;
|
||||
//virtual void _left(int x, int y, int w, int h, int level) = 0;
|
||||
//virtual void _right(int x, int y, int w, int h, int level) = 0;
|
||||
//virtual void _clear(int x, int y, int w, int h) = 0; /* FIXME: 实现该方法 */
|
||||
/*====== drawer 绘制 ======
|
||||
* 提供给子类和外部的绘制方法 */
|
||||
virtual void point(int x, int y, Color &clr);
|
||||
virtual void line(int x1, int y1, int x2, int y2, Color &clr);
|
||||
virtual void rectangle(int x, int y, int w, int h, Color &clr);
|
||||
virtual void rectangle_fill(int x, int y, int w, int h, Color &clr);
|
||||
virtual void flush(Drawable *n, bool border) = 0;
|
||||
//virtual void clear(); /* 对于区域来说,清理可能较为复杂 */
|
||||
/*------ printer 打印 ------
|
||||
* 打印文字
|
||||
*
|
||||
* 只实现了打印文字的基本方法 */
|
||||
void drawvfont(int x, int y, unsigned short z, Color &clr);
|
||||
/*------ test 测试 ------
|
||||
* 绘制测试图案 */
|
||||
virtual void test(); /* 颜色测试 */
|
||||
|
||||
protected:
|
||||
/*------ window ------
|
||||
* 窗口属性 */
|
||||
int w, h, x, y, rotate=0;
|
||||
/*------ fonts lib ------
|
||||
* 文字库 */
|
||||
int font_w, font_h;
|
||||
unsigned short *chss = (unsigned short *)zzhi;
|
||||
unsigned char *vec = ttu;
|
||||
int zn;
|
||||
int vennum;
|
||||
/* 绘制文字 */
|
||||
unsigned char *drawvect(int x, int y, unsigned char *vect, int width, int high, Color &clr);
|
||||
/*------ printer ------*/
|
||||
Color clr = green;
|
||||
//Color clr = white;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include "Rectangle.h"
|
||||
#include "Color.h"
|
||||
#include "Drawable.h"
|
||||
#include <iostream>
|
||||
#include <linux/fb.h>
|
||||
namespace qing{
|
||||
/* FIXME: 这个类的绘制点方法可能过于复杂 */
|
||||
class FrameBuf: public Drawable { /* 帧缓冲区类 */
|
||||
public:
|
||||
FrameBuf(const char *path, int rotate, int fontsize);
|
||||
FrameBuf(const FrameBuf&) = delete; /* 持有fd */
|
||||
~FrameBuf();
|
||||
int get_bpp(); /* bits_per_pixel 像素比特 */
|
||||
virtual Color _get(int x, int y) override;
|
||||
virtual void _p(int x, int y, Color &color) override;
|
||||
virtual void flush(Drawable *d, bool border = false) override;
|
||||
void clear(); /* FIXME: 也许把这个方法加到抽象父类中? */
|
||||
|
||||
class UnknowBPP: std::runtime_error { /* 未知标准的像素比特 */
|
||||
public:
|
||||
UnknowBPP(): std::runtime_error("Unknow the number of Bits Per Pixel.") {}
|
||||
};
|
||||
static const int _HEAD_LEN = 8;
|
||||
|
||||
private:
|
||||
int d = -1;
|
||||
struct fb_var_screeninfo var_info; /* 可变参数 */
|
||||
struct fb_fix_screeninfo fix_info; /* 固定参数 */
|
||||
int x_over = 0; /* 横轴过量 */
|
||||
int line_jump = 0; /* 行跳 */
|
||||
char *buf = nullptr; /* 缓冲区指针 */
|
||||
|
||||
/* 根据像素比特的不同分情况讨论 */
|
||||
Color get16(__u32 x, __u32 y);
|
||||
Color get32(__u32 x, __u32 y);
|
||||
void p32(__u32 x, __u32 y, Color &color);
|
||||
void p16(__u32 x, __u32 y, Color &color);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "Area.h"
|
||||
namespace qing {
|
||||
class InputBox: public Area { /* 输入框 */
|
||||
public:
|
||||
InputBox(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize);
|
||||
virtual void print(char *utf8, int line);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <linux/input.h>
|
||||
//#define MAX 64 /* FIXME: 这个是不是没用了 */
|
||||
namespace qing {
|
||||
class KeyboardEvent{
|
||||
public:
|
||||
KeyboardEvent();
|
||||
~KeyboardEvent();
|
||||
struct input_event get(); /* 获取键盘事件 */
|
||||
class NoEvent: std::runtime_error{ /* 键盘无事件异常 */
|
||||
public:
|
||||
NoEvent(std::string s): std::runtime_error(s){}
|
||||
};
|
||||
private:
|
||||
std::map<std::string, int> pool;
|
||||
static bool is_event_with_number(const char *filename);
|
||||
static void set_noblocking(int d);
|
||||
int maxd();
|
||||
static void print(struct input_event ev);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 控件池区域
|
||||
*
|
||||
* 能够容纳别的控件,不需要重写flush()方法
|
||||
*/
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include "lci/Area.h"
|
||||
#include "lci/Drawable.h"
|
||||
namespace qing {
|
||||
class PoolArea: public Area{
|
||||
public:
|
||||
PoolArea(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize)
|
||||
:Area(d, w, h, x, y, rotate, fontsize) {};
|
||||
void add(const std::string& name, const std::shared_ptr<Area>& item) {
|
||||
umap.insert({name, item});
|
||||
}
|
||||
|
||||
/* 访问控件 */
|
||||
std::shared_ptr<Area>& operator[](const std::string& key) {
|
||||
return umap.at(key);
|
||||
}
|
||||
|
||||
/* 访问控件 - const */
|
||||
const std::shared_ptr<Area>& operator[](const std::string& key) const {
|
||||
return umap.at(key);
|
||||
}
|
||||
|
||||
/* 安全访问 - 不抛异常 */
|
||||
//std::shard_ptr<Area> get(const std::string& key) const {}
|
||||
|
||||
/* 检查是否存在 */
|
||||
bool contains(const std::string& key) const {
|
||||
return umap.find(key) != umap.end();
|
||||
}
|
||||
|
||||
/* 获取控件数量 */
|
||||
size_t size() const { return umap.size(); }
|
||||
|
||||
/* 迭代器支持 - 范围for循环 */
|
||||
std::unordered_map<std::string, std::shared_ptr<Area>>::iterator begin() { return umap.begin(); }
|
||||
std::unordered_map<std::string, std::shared_ptr<Area>>::iterator end() { return umap.end(); }
|
||||
|
||||
/* 迭代器支持 - const版本 */
|
||||
std::unordered_map<std::string, std::shared_ptr<Area>>::const_iterator begin() const { return umap.begin(); }
|
||||
std::unordered_map<std::string, std::shared_ptr<Area>>::const_iterator end() const { return umap.end(); }
|
||||
|
||||
/* FIXME: cbegin/cend 支持 */
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<Area>> umap;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
namespace qing{
|
||||
class Rectangle{ /* 矩形类 */
|
||||
public:
|
||||
int w=0; /* width */
|
||||
int h=0; /* height */
|
||||
int b=0; /* ? */
|
||||
Rectangle(int w=0, int h=0, int b=0) {
|
||||
this->w=w;
|
||||
this->h=h;
|
||||
this->b=b;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
#include "lci/Drawable.h"
|
||||
#include "lci/Color.h"
|
||||
namespace qing {
|
||||
/* 【形状】
|
||||
* 抽象基类 */
|
||||
class Shape {
|
||||
public:
|
||||
Shape(int w, int h, int x, int y)
|
||||
: w(w), h(h), x(x), y(y) {}
|
||||
virtual void Draw(Drawable &d, Color clr) = 0;
|
||||
int getw() {
|
||||
return w;
|
||||
}
|
||||
void setw(int w) {
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
int geth() {
|
||||
return h;
|
||||
}
|
||||
void seth(int h) {
|
||||
this->h = h;
|
||||
}
|
||||
|
||||
int getx() {
|
||||
return x;
|
||||
}
|
||||
void setx(int x) {
|
||||
this->x = x;
|
||||
}
|
||||
|
||||
int gety() {
|
||||
return y;
|
||||
}
|
||||
void sety(int y) {
|
||||
this->y = y;
|
||||
}
|
||||
private:
|
||||
int w, h;
|
||||
int x, y;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
/*
|
||||
* 形状区域
|
||||
*/
|
||||
#include "lci/Area.h"
|
||||
#include "lci/Shape.h"
|
||||
#include "vector"
|
||||
#include "memory"
|
||||
namespace qing {
|
||||
class ShapeArea: public Area {
|
||||
public:
|
||||
ShapeArea(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize)
|
||||
: Area(d, w, h, x, y, rotate, fontsize){}
|
||||
size_t size() const { return list.size(); }
|
||||
void add(const std::shared_ptr<Shape>& item) {
|
||||
list.push_back(item);
|
||||
}
|
||||
Shape& operator[](const size_t idx) {
|
||||
return *(list[idx]);
|
||||
}
|
||||
const Shape& operator[](const size_t idx) const {
|
||||
return *(list[idx]);
|
||||
}
|
||||
std::vector<std::shared_ptr<Shape>>::iterator begin() { return list.begin(); }
|
||||
std::vector<std::shared_ptr<Shape>>::iterator end() { return list.end(); }
|
||||
|
||||
std::vector<std::shared_ptr<Shape>>::const_iterator begin() const { return list.begin(); }
|
||||
std::vector<std::shared_ptr<Shape>>::const_iterator end() const { return list.end(); }
|
||||
private:
|
||||
std::vector<std::shared_ptr<Shape>> list;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
namespace qing {
|
||||
class Term {
|
||||
public:
|
||||
/* 需要输入当前的控制台号(源头tty) */
|
||||
Term(int target_tty, int origin_tty) {
|
||||
this->origin_tty = origin_tty;
|
||||
chvt(target_tty);
|
||||
HideCursor(target_tty);
|
||||
}
|
||||
~Term(){ /* 切回源tty */
|
||||
chvt(origin_tty);
|
||||
}
|
||||
private:
|
||||
int origin_tty;
|
||||
static int open_tty(int num) {
|
||||
char path[16] = {'\0'};
|
||||
snprintf(path, sizeof(path), "/dev/tty%d", num);
|
||||
int d = open(path, O_WRONLY);
|
||||
if (d == -1)
|
||||
throw std::runtime_error(path);
|
||||
else
|
||||
return d;
|
||||
}
|
||||
static void HideCursor(int id) {
|
||||
int d = open_tty(id);
|
||||
const char *hide = "\033[?25l";
|
||||
if (write(d, hide, strlen(hide)) == -1){
|
||||
close(d);
|
||||
throw std::runtime_error("term writting");
|
||||
}
|
||||
close(d);
|
||||
}
|
||||
static void chvt(int id) {
|
||||
char cmd[16] = {'\0'};
|
||||
snprintf(cmd, sizeof(cmd), "chvt %d", id);
|
||||
int err = system(cmd);
|
||||
if (err)
|
||||
throw std::runtime_error("chvt");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
namespace qing {
|
||||
|
||||
class ThreadInterface {
|
||||
|
||||
public:
|
||||
|
||||
//---------------------------------------------
|
||||
//程序睡眠阶段的操作函数。
|
||||
virtual void StopEvent() = 0;
|
||||
//程序设置阶段的操作函数。
|
||||
virtual void WakeEvent() = 0;
|
||||
//程序运行阶段的操作函数。
|
||||
virtual void LoopEvent() = 0;
|
||||
//程序清理阶段的操作函数。
|
||||
virtual void ClearEvent() = 0;
|
||||
|
||||
//可以将操作函数作为一种事件,可以从外界传入写好的事件函数,
|
||||
//那么就需要将操作函数设定为静态函数
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <cstddef>
|
||||
namespace qing {
|
||||
/* ANSI是WINDOWS操作系统默认的编码格式。 */
|
||||
class ansi{
|
||||
public:
|
||||
static int size_gb18030(unsigned char *c, size_t maxLen);
|
||||
static int size_gb2312(unsigned char first_byte);
|
||||
class WrongLength: public std::runtime_error { /* 非法的长度 */
|
||||
public:
|
||||
WrongLength(): std::runtime_error("") {}
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include<mutex>
|
||||
#include<condition_variable>
|
||||
namespace qing{
|
||||
namespace lci{
|
||||
//用来存储状态的枚举类型
|
||||
enum Stat{
|
||||
SSHUT = -1,
|
||||
SSTOP = 0,
|
||||
SSTART = 1,
|
||||
SRUNNING = 2
|
||||
};//Status
|
||||
|
||||
class Fsm {//FiniteStateMachine有限状态机
|
||||
public:
|
||||
//构造函数
|
||||
Fsm();
|
||||
//检查状态
|
||||
enum Stat chk();
|
||||
//改变状态
|
||||
void wake();
|
||||
void stop();
|
||||
void shut();
|
||||
void run();
|
||||
//protected:
|
||||
//等待事件唤醒
|
||||
void suspend();
|
||||
private:
|
||||
//锁类型,确保状态机线程安全
|
||||
std::mutex lock;
|
||||
//条件变量,用来执行等待或者唤醒
|
||||
std::condition_variable cv;
|
||||
//存放状态机的状态
|
||||
enum Stat stat;
|
||||
};//StateMachine
|
||||
}//lci
|
||||
}//qing
|
||||
@@ -0,0 +1,160 @@
|
||||
#pragma once
|
||||
#include "Area.h"
|
||||
#include "CmdArea.h"
|
||||
#include "CommonThread.h"
|
||||
namespace qing {
|
||||
namespace lci{
|
||||
/* PrintThread 打印线程 */
|
||||
class p_th: public CommonThread {
|
||||
public:
|
||||
/**
|
||||
* 构造函数 传入要读取的控制台设备文件描述符,背景画布,以及命令行区域
|
||||
*/
|
||||
p_th(std::string name, int masterfd, Drawable *back, CmdArea *font)
|
||||
: CommonThread(name) {
|
||||
this->masterfd = masterfd;
|
||||
this->back = back;
|
||||
this->font = font;
|
||||
}
|
||||
|
||||
/**
|
||||
* 析构函数 关闭线程
|
||||
*
|
||||
* 我在可控制线程中主要遇到的问题便是线程的自主终止,
|
||||
*
|
||||
* 在 Python 中似乎是只能实现可控制线程的手动退出的,
|
||||
*
|
||||
* 我在想是不是在cpp中也做成那样。
|
||||
*
|
||||
*
|
||||
* FIXME(20260108): 啥意思不懂
|
||||
*/
|
||||
~p_th(){
|
||||
|
||||
/* 使线程自主关闭 */
|
||||
if (this->chk() != lci::SSHUT){
|
||||
this->shut();
|
||||
}
|
||||
|
||||
/* 等待线程退出 */
|
||||
this->WaitClose();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂时删除复制构造函数,因为复制出一个与原来线程无关的空白线程似乎没有什么作用
|
||||
*
|
||||
* 如果让两个变量引用同一个线程,会使得它们在结束的时候出现错误。
|
||||
*/
|
||||
p_th(p_th&) = delete;
|
||||
|
||||
|
||||
/**
|
||||
* 线程睡眠阶段的操作函数,线程等待。
|
||||
*
|
||||
* suspend() 方法似乎不太稳定,我还得再测试测试。
|
||||
*/
|
||||
void StopEvent() override {
|
||||
this->suspend();
|
||||
}
|
||||
|
||||
/**
|
||||
* 线程苏醒之后执行的操作,线程启动。
|
||||
*
|
||||
* 我不知道为什么要等待1秒。
|
||||
*/
|
||||
void WakeEvent() {
|
||||
|
||||
/* 将文件描述符集合清零 */
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
/* 清空缓存字符串 */
|
||||
output = "";
|
||||
|
||||
/* 设置完毕,线程进入运行态 */
|
||||
this->run();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 线程运行阶段的循环体,线程运行。
|
||||
*
|
||||
* 使用 SELECT 进行缓冲区的探测。
|
||||
*/
|
||||
void LoopEvent() {
|
||||
|
||||
/* 对可读集合进行清零 */
|
||||
//FD_ZERO(&read_fds);
|
||||
|
||||
/* 设置可读集合 */
|
||||
//FD_SET(masterfd, &read_fds);
|
||||
|
||||
/**
|
||||
* 仅在集合中不存在控制台描述符时,才往其中添加该描述符
|
||||
*
|
||||
* 在这个集合中,应该只会存在这一个文件描述符吧
|
||||
*/
|
||||
if (!FD_ISSET(masterfd, &read_fds))
|
||||
FD_SET(masterfd, &read_fds);
|
||||
|
||||
/* 设置超时时间 */
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 10000;
|
||||
|
||||
int ret = select(masterfd + 1, &read_fds, NULL, NULL, &timeout);
|
||||
if (ret == -1) {
|
||||
//throw std::runtime_error("select");
|
||||
//this->stop();
|
||||
return; /* qing(20260108): 为什么不停止 */
|
||||
} else if (ret == 0) { /* No data to read 无值可读 */
|
||||
if (output == "") return; /* 在空闲时进行打印*/
|
||||
font->print((char*)output.c_str(), 0); /* 按次为单位进行刷新应该可以提高效率 20260108(qing): ?*/
|
||||
back->flush(font, false);
|
||||
output = "";
|
||||
} else {
|
||||
if (FD_ISSET(masterfd, &read_fds)) { /* 有值可读 */
|
||||
nread = read(masterfd, buffer, sizeof(buffer));
|
||||
if (nread > 0) {
|
||||
buffer[nread] = '\0';
|
||||
output += buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 线程执行过后的清理函数,清理资源。
|
||||
*
|
||||
* 什么也不做。我们在唤醒时并未申请资源。
|
||||
*/
|
||||
void ClearEvent() {
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int masterfd; /* 对象中存储的要读取的控制台设备文件描述符。 */
|
||||
|
||||
Drawable *back; /* 对象中存储的背景画布指针 */
|
||||
|
||||
CmdArea *font; /* 对象中存储的命令行区域指针 */
|
||||
|
||||
std::string output; /* 从终端设备中读取的进程输出 */
|
||||
|
||||
//--------------------------------------------
|
||||
/* 下面的变量是为了提高速度,避免重复申请 */
|
||||
|
||||
fd_set read_fds; /* 文件描述符集合,用于存储 SELECT 返回的可读区域 */
|
||||
|
||||
struct timeval timeout; /* 时间结构体 用于传入 SELECT 函数的超时时间 */
|
||||
|
||||
ssize_t nread; /* 这一次从控制台中所读取大小 */
|
||||
|
||||
char buffer[1024]; /* 存储从控制台中读取字符的缓冲区,一次最多读这么多 */
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
namespace qing {
|
||||
class utf8{ /* */
|
||||
public:
|
||||
static int size(const unsigned char c);
|
||||
static char *to_ansi(char *s);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/* 图层区域是能够绘制图片的区域类型 */
|
||||
#define cimg_display 0
|
||||
#define cimg_use_jpeg
|
||||
#define cimg_use_png
|
||||
#include <CImg.h>
|
||||
#include "cn/中文化.hpp"
|
||||
#include "lci/Area.h"
|
||||
使用 命名空间 cimg_library;
|
||||
命名空间 qing {
|
||||
类 图层区域: 公开的 Area { /* 图层区域 */
|
||||
公开的:
|
||||
图层区域(Drawable *d, int w, int h, int x, int y, int rotate, int fontsize, CImg<unsigned char>& img)
|
||||
: Area(d, w, h, x, y, rotate, fontsize) {
|
||||
/* 储存图片,需要调用图片的构造函数 */
|
||||
this->img = img;
|
||||
}
|
||||
空类型 涂写图像() {
|
||||
单精度小数 区域长宽比 = (float)w / h;
|
||||
单精度小数 图片长宽比 = (float)img.width() / img.height();
|
||||
/* 长宽比越大,代表图片越横向细长
|
||||
* 长宽比越小,代表图片越竖向细长
|
||||
* 长宽比为1时,图片为正方形
|
||||
*
|
||||
* 图片长宽比较大时,取区域长
|
||||
* 图片长宽比较小时,取区域高 */
|
||||
逻辑型 长为标准 = 图片长宽比 > 区域长宽比;
|
||||
如果(长为标准) {
|
||||
auto fixed = scaleByWidth(this->img, this->w);
|
||||
CImg<unsigned char> gray = 转灰度图(fixed);
|
||||
auto start = (int)(this->h - gray.height()) / 2;
|
||||
for (int y = 0; y < gray.height(); ++y) {
|
||||
for (int x = 0; x < gray.width(); ++x){
|
||||
auto xx = x;
|
||||
auto yy = y + start;
|
||||
auto clr1 = 颜色转换(gray(x, y), this->clr);
|
||||
this->point(xx, yy, clr1);
|
||||
}
|
||||
}
|
||||
}
|
||||
否则{ /* 以宽为标准 */
|
||||
auto fixed = scaleByHeight(this->img, this->h);
|
||||
auto gray = 转灰度图(fixed);
|
||||
auto start = (int)(this->w - gray.width()) / 2;
|
||||
for (int y = 0; y < gray.height(); ++y) {
|
||||
for (int x = 0; x < gray.width(); ++x){
|
||||
auto xx = x + start;
|
||||
auto yy = y;
|
||||
auto clr1 = 颜色转换(gray(x, y), this->clr);
|
||||
this->point(xx, yy, clr1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
私有的:
|
||||
CImg<unsigned char> img;
|
||||
/* 以长为标准缩放 */
|
||||
static CImg<unsigned char> scaleByWidth(const CImg<unsigned char>& src, int newWidth) {
|
||||
/* 计算缩放比例 */
|
||||
float ratio = (float)newWidth / src.width();
|
||||
int newHeight = (int)(src.height() * ratio);
|
||||
|
||||
/* 使用_resize方法进行缩放 */
|
||||
return src.get_resize(newWidth, newHeight, -100, -100, 5);
|
||||
}
|
||||
/* 以高为标准缩放 */
|
||||
static CImg<unsigned char> scaleByHeight(const CImg<unsigned char>& src, int newHeight) {
|
||||
/* 计算缩放比例 */
|
||||
float ratio = (float)newHeight / src.height();
|
||||
int newWidth = (int)(src.width() * ratio);
|
||||
|
||||
/* 计算_resize方法进行缩放 */
|
||||
return src.get_resize(newWidth, newHeight, -100, -100, 5);
|
||||
}
|
||||
/* 将灰度颜色转换为我们目前画笔的颜色 */
|
||||
静态的 Color 颜色转换(无符号 字符 灰度, Color clr) {
|
||||
单精度小数 红 = (单精度小数)clr.r / 255;
|
||||
单精度小数 绿 = (单精度小数)clr.g / 255;
|
||||
单精度小数 蓝 = (单精度小数)clr.b / 255;
|
||||
自动的 结果 = Color(红* 灰度*255, 绿*灰度*255, 蓝*灰度*255);
|
||||
返回 结果;
|
||||
}
|
||||
|
||||
/* 将CImg对象转为灰度图 */
|
||||
静态的 CImg<unsigned char> 转灰度图(CImg<unsigned char>& img) {
|
||||
|
||||
if (img.spectrum() == 3) {
|
||||
return img.get_normalize(0, 255).get_RGBtoXYZ().get_channel(1);
|
||||
}
|
||||
else if (img.spectrum() ==4) {
|
||||
|
||||
auto rgb_img = t_4_to_3(img);
|
||||
return rgb_img.get_RGBtoXYZ().get_channel(1);
|
||||
}
|
||||
else {
|
||||
抛出异常 std::runtime_error("没有对应通道数的算法");
|
||||
}
|
||||
}
|
||||
|
||||
/* 将4通道图片转为3通道 */
|
||||
静态的 CImg<unsigned char> t_4_to_3(CImg<unsigned char>& img) {
|
||||
// 创建RGB图像(3通道)
|
||||
CImg<unsigned char> rgb_img(img.width(), img.height(), 1, 3);
|
||||
|
||||
cimg_forXY(rgb_img, x, y) {
|
||||
rgb_img(x, y, 0, 0) = img(x, y, 0, 0); // R
|
||||
rgb_img(x, y, 0, 1) = img(x, y, 0, 1); // G
|
||||
rgb_img(x, y, 0, 2) = img(x, y, 0, 2); // B
|
||||
// 忽略alpha通道 img(x, y, 0, 3)
|
||||
}
|
||||
|
||||
return rgb_img;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 用于在可绘制对象上绘制中文文字
|
||||
*
|
||||
* 绘制时将对象作为参数传入
|
||||
*/
|
||||
|
||||
#include "cn/中文化.hpp"
|
||||
#include "lci/Drawable.h"
|
||||
/* 用于文字的绘制,只要不动就线程安全 */
|
||||
extern unsigned char ttu[];
|
||||
extern int ttunumber;
|
||||
extern unsigned char zzhi[];
|
||||
extern int zzhinumber;
|
||||
|
||||
命名空间 qing {
|
||||
类 字体绘制器 {
|
||||
私有的:
|
||||
/*------ fonts lib ------
|
||||
* 文字库 */
|
||||
int font_w, font_h;
|
||||
unsigned short *chss = (unsigned short *)zzhi;
|
||||
unsigned char *vec = ttu;
|
||||
int zn = zzhinumber;
|
||||
int vennum = ttunumber;
|
||||
|
||||
unsigned char *drawvect(Drawable* d, int x, int y, unsigned char *vect, int width, int high, Color &clr)
|
||||
// x, y是左上角坐标,vect指向矢量图数据,width和high分别代表要绘制的图的宽和高(好像宽需要=高)
|
||||
{
|
||||
if (!vect) return nullptr;
|
||||
int i = 0, j = 1; // 指向第一对数字
|
||||
unsigned char ix, iy; // 从数组取出的第一对坐标放在这
|
||||
double x1, y1;//, x2, y2; // 绘制直线的实数的坐标
|
||||
if (high == 0) high = width; // 调节高宽
|
||||
int ii1, jj1, ii2, jj2; // 最后算出的绘制直线的坐标
|
||||
int isend = 0; //是否到达曲线尾
|
||||
int isallend = 0; // 是否结束整个图像
|
||||
do {
|
||||
ix = vect[i];
|
||||
iy = vect[j];
|
||||
isend = ix & 1; // 奇数代表曲线尾
|
||||
isallend = iy & 1; // 奇数代表整个图像结束
|
||||
if (isallend) {
|
||||
i += 2;
|
||||
break; // 整个图像结束返回
|
||||
}
|
||||
if (isend) { // 如果这里曲线结束什么也不画进到下一条曲线
|
||||
i += 2;
|
||||
j += 2;
|
||||
continue;
|
||||
}
|
||||
ix /= 2;
|
||||
iy /= 2;
|
||||
x1 = ix;
|
||||
y1 = iy;
|
||||
x1 = width * x1 / 128.0;
|
||||
y1 = high * y1 / 128.0;
|
||||
ii1 = (int)(x1 + x);
|
||||
jj1 = (int)(y1 + y);
|
||||
int k;
|
||||
for (k = 0; k < 100000; k++) {
|
||||
//x2 = x1;
|
||||
//y2 = y1;
|
||||
ii2 = ii1;
|
||||
jj2 = jj1;
|
||||
i += 2;
|
||||
j += 2;
|
||||
ix = vect[i];
|
||||
iy = vect[j];
|
||||
isend = ix & 1; //奇数代表曲线尾
|
||||
isallend = iy & 1; //奇数代表整个图像结束
|
||||
ix /= 2;
|
||||
iy /= 2;
|
||||
x1 = ix;
|
||||
y1 = iy;
|
||||
x1 = width * x1 / 128.0;
|
||||
y1 = high * y1 / 128.0;
|
||||
ii1 = (int)(x1 + x);
|
||||
jj1 = (int)(y1 + y);
|
||||
d->line(ii1, jj1, ii2, jj2, clr);
|
||||
if (isend || isallend)
|
||||
break;
|
||||
}
|
||||
i += 2; //指向下一条曲线
|
||||
j += 2;
|
||||
} while (!isallend);
|
||||
return vect + i;
|
||||
}
|
||||
|
||||
公开的:
|
||||
字体绘制器(const int font_w, const int font_h)
|
||||
: font_w(font_w), font_h(font_h) {}
|
||||
|
||||
/* 绘制文字 */
|
||||
void drawvfont(Drawable* d, int x, int y, unsigned short z, Color &clr) {
|
||||
int i, j, k, ii;
|
||||
j = -1;
|
||||
for (i = 0; i < zn; i++) {
|
||||
if (chss[i] == z) {
|
||||
j = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j < 0) return;
|
||||
k = 0;
|
||||
for (i = 0; i < vennum; i++) {
|
||||
if (k == j)
|
||||
break;
|
||||
for (ii =i; ii <vennum; ii++) {
|
||||
if (vec[2*ii + 1] & 1) {
|
||||
k++;
|
||||
i = ii;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (k < j) return;
|
||||
drawvect(d, x, y, vec + 2 * i, font_w, font_h, clr);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user