Linux基础项目开发1:量产工具——改进优化(八)

简介: Linux基础项目开发1:量产工具——改进优化(八)

一、改进:按钮文字

按钮文字大小不一,没有严格居中,太小看不清

根据配置文件的各项确定最长的名字,确定字符大小:每个按钮中文字大小都一样

修改disp_manager.c中的DrawTextInRegionCentral

1.freetype.c

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <wchar.h>
#include <sys/ioctl.h>
#include <font_manager.h>
 
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
 
 
static FT_Face g_tFace;
static int g_iDefaultFontSize = 12;
 
 
static int FreetypeGetStringRegionCar(char *str, PRegionCartesian ptRegionCar)
{
    int i;
    int error;
    FT_BBox bbox;
    FT_BBox glyph_bbox;
    FT_Vector pen;
    FT_Glyph  glyph;
    FT_GlyphSlot slot = g_tFace->glyph;
 
    /* 初始化 */
    bbox.xMin = bbox.yMin = 32000;
    bbox.xMax = bbox.yMax = -32000;
 
    /* 指定原点为(0, 0) */
    pen.x = 0;
    pen.y = 0;
 
    /* 计算每个字符的bounding box */
    /* 先translate, 再load char, 就可以得到它的外框了 */
    for (i = 0; i < strlen(str); i++)
    {
        /* 转换:transformation */
        FT_Set_Transform(g_tFace, 0, &pen);
 
        /* 加载位图: load glyph image into the slot (erase previous one) */
        error = FT_Load_Char(g_tFace, str[i], FT_LOAD_RENDER);
        if (error)
        {
            printf("FT_Load_Char error\n");
            return -1;
        }
 
        /* 取出glyph */
        error = FT_Get_Glyph(g_tFace->glyph, &glyph);
        if (error)
        {
            printf("FT_Get_Glyph error!\n");
            return -1;
        }
        
        /* 从glyph得到外框: bbox */
        FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox);
 
        /* 更新外框 */
        if ( glyph_bbox.xMin < bbox.xMin )
            bbox.xMin = glyph_bbox.xMin;
 
        if ( glyph_bbox.yMin < bbox.yMin )
            bbox.yMin = glyph_bbox.yMin;
 
        if ( glyph_bbox.xMax > bbox.xMax )
            bbox.xMax = glyph_bbox.xMax;
 
        if ( glyph_bbox.yMax > bbox.yMax )
            bbox.yMax = glyph_bbox.yMax;
        
        /* 计算下一个字符的原点: increment pen position */
        pen.x += slot->advance.x;
        pen.y += slot->advance.y;
    }
 
    /* return string bbox */
    //*abbox = bbox;
    ptRegionCar->iLeftUpX = bbox.xMin;
    ptRegionCar->iLeftUpY = bbox.yMax;
    ptRegionCar->iWidth     = bbox.xMax - bbox.xMin + 1;
    ptRegionCar->iHeigh     = bbox.yMax - bbox.yMin + 1;
 
  return 0; 
}
 
 
static int FreeTypeFontInit(char *aFineName)
{
    FT_Library    library;
    int error;
 
    error = FT_Init_FreeType( &library );                 /* initialize library */    
  if (error)
  {
    printf("FT_Init_FreeType err\n");
    return -1;
  }
  
    error = FT_New_Face(library, aFineName, 0, &g_tFace ); /* create face object */
  if (error)
  {
    printf("FT_New_Face err\n");
    return -1;
  }
 
    FT_Set_Pixel_Sizes(g_tFace, g_iDefaultFontSize, 0);
 
  return 0;
}
 
static int FreeTypeSetFontSize(int iFontSize)
{
    FT_Set_Pixel_Sizes(g_tFace, iFontSize, 0);
  return 0;
}
 
static int FreeTypeGetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap)
{
  int error;
    FT_Vector pen;
    FT_GlyphSlot slot = g_tFace->glyph;
 
    pen.x = ptFontBitMap->iCurOriginX * 64; /* 单位: 1/64像素 */
    pen.y = ptFontBitMap->iCurOriginY * 64; /* 单位: 1/64像素 */
 
  /* 转换:transformation */
  FT_Set_Transform(g_tFace, 0, &pen);
 
  /* 加载位图: load glyph image into the slot (erase previous one) */
  error = FT_Load_Char(g_tFace, dwCode, FT_LOAD_RENDER);
  if (error)
  {
    printf("FT_Load_Char error\n");
    return -1;
  }
 
  ptFontBitMap->pucBuffer = slot->bitmap.buffer;
 
  ptFontBitMap->tRegion.iLeftUpX = slot->bitmap_left;
  ptFontBitMap->tRegion.iLeftUpY = ptFontBitMap->iCurOriginY*2 - slot->bitmap_top;
  ptFontBitMap->tRegion.iWidth   = slot->bitmap.width;
  ptFontBitMap->tRegion.iHeigh   = slot->bitmap.rows;
  ptFontBitMap->iNextOriginX = ptFontBitMap->iCurOriginX + slot->advance.x / 64;
  ptFontBitMap->iNextOriginY = ptFontBitMap->iCurOriginY;
 
  return 0;
}
 
 
static FontOpr g_tFreetypeOpr = {
  .name          = "freetype",
  .FontInit      = FreeTypeFontInit,
  .SetFontSize   = FreeTypeSetFontSize,
  .GetFontBitMap = FreeTypeGetFontBitMap,
  .GetStringRegionCar = FreetypeGetStringRegionCar,
};
 
void FreetypeRegister(void)
{
  RegisterFont(&g_tFreetypeOpr);
}
 
static int FreetypeGetStringRegionCar(char *str, PRegionCartesian ptRegionCar)

第23行:将外框保存在笛卡坐标系里面

2.font_manager.h

#ifndef _FONT_MANAGER_H
#define _FONT_MANAGER_H
 
#include <common.h>
 
typedef struct FontBitMap {
  Region tRegion;
  int iCurOriginX;
  int iCurOriginY;
  int iNextOriginX;
  int iNextOriginY;
  unsigned char *pucBuffer;
}FontBitMap, *PFontBitMap;
 
typedef struct FontOpr {
  char *name;
  int (*FontInit)(char *aFineName);
  int (*SetFontSize)(int iFontSize);
  int (*GetFontBitMap)(unsigned int dwCode, PFontBitMap ptFontBitMap);
  int (*GetStringRegionCar)(char *str, PRegionCartesian ptRegionCar);
  struct FontOpr *ptNext;
}FontOpr, *PFontOpr;
 
void RegisterFont(PFontOpr ptFontOpr);
 
void FontsRegister(void);
 
int SelectAndInitFont(char *aFontOprName, char *aFontFileName);
int SetFontSize(int iFontSize);
int GetFontBitMap(unsigned int dwCode, PFontBitMap ptFontBitMap);
int GetStringRegionCar(char *str, PRegionCartesian ptRegionCar);
 
 
#endif

第20行:添加 GetStringRegionCar 函数指针

第31行:在头文件里将这个函数声明出来

3.font_manager.c

调用你所选择的字库操作函数里面对应的函数

 
int GetStringRegionCar(char *str, PRegionCartesian ptRegionCar)
{
  return g_ptDefaulFontOpr->GetStringRegionCar(str, ptRegionCar);
}

4.common.h

构建笛卡坐标系计算外框

 
 
#ifndef _COMMON_H
#define _COMMON_H
 
#ifndef NULL
#define NULL (void *)0
#endif
 
typedef struct Region {
  int iLeftUpX;
  int iLeftUpY;
  int iWidth;
  int iHeigh;
}Region, *PRegion;
 
typedef struct RegionCartesian {
  int iLeftUpX;
  int iLeftUpY;
  int iWidth;
  int iHeigh;
}RegionCartesian, *PRegionCartesian;
 
 
#endif
 

5.main_page.c

对边框进行计算得出文字大小

 
static int GetFontSizeForAllButton(void)
{
  int i;
  int max_len = -1;
  int max_index = 0;
  int len;
  RegionCartesian tRegionCar;
  float k, kx, ky;
  
  /* 1. 找出name最长的Button */
  for (i = 0; i < g_tButtonCnt; i++)
  {
    len = strlen(g_tButtons[i].name);
    if (len > max_len)
    {
      max_len = len;
      max_index = i;
    }
  }
 
  /* 2. 以font_size =100, 算出它的外框 */
  SetFontSize(100);
  GetStringRegionCar(g_tButtons[max_index].name, &tRegionCar);
 
  /* 3. 把文字的外框缩放为Button的外框 */
  kx = (float)g_tButtons[max_index].tRegion.iWidth / tRegionCar.iWidth;
  ky = (float)g_tButtons[max_index].tRegion.iHeigh / tRegionCar.iHeigh;
  
  if (kx < ky)
    k = kx;
  else
    k = ky;
 
  //printf("font size = %d\n", (int)(k*100));
  /* 4. 反算出font size, 只取0.80, 避免文字过于接近边界 */
  return k * 100 * 0.8;
}

6.disp_manager.c

DrawTextInRegionCentral绘制函数中

/* 计算字符串的外框 */
GetStringRegionCar(name, &tRegionCar);
/* 算出第一个字符的origin */
iOriginX = ptRegion->iLeftUpX + (ptRegion->iWidth - tRegionCar.iWidth)/2 - tRegionCar.iLeftUpX;
iOriginY = ptRegion->iLeftUpY + (ptRegion->iHeigh - tRegionCar.iHeigh)/2 + tRegionCar.iLeftUpY;Car.iLeftUpY;

7.上板效果:

二、改进:接口函数名优化

显示系统、输入系统中,有多个init函数,让人难以分辨。

如下图修改:

main.c

 
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdlib.h>
 
#include <disp_manager.h>
#include <font_manager.h>
#include <input_manager.h>
#include <page_manager.h>
 
 
int main(int argc, char **argv)
{
  int error;
 
  if (argc != 2)
  {
    printf("Usage: %s <font_file>\n", argv[0]);
    return -1;
  }
  
  /* 初始化显示系统 */   
  DisplaySystemRegister();  /* 以前是: DisplayInit(); */
 
  SelectDefaultDisplay("fb");
 
  InitDefaultDisplay();
 
  /* 初始化输入系统 */   
  InputSystemRegister(); /* 以前是: InputInit(); */
  IntpuDeviceInit();
 
 
  /* 初始化文字系统 */   
  FontSystemRegister(); /* 以前是: FontsRegister(); */
  
  error = SelectAndInitFont("freetype", argv[1]);
  if (error)
  {
    printf("SelectAndInitFont err\n");
    return -1;
  }
 
  /* 初始化页面系统 */   
  PageSystemRegister(); /* 以前是: PagesRegister(); */
 
  /* 运行业务系统的主页面 */
  Page("main")->Run(NULL);
  
  return 0; 
}

三、改进:支持配置文件中的command

1.main_page.c:

在按钮的OnPressed函数中,用system函数运行command

 
#include <config.h>
#include <stdio.h>
#include <ui.h>
#include <page_manager.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
 
#define X_GAP 5
#define Y_GAP 5
 
static Button g_tButtons[ITEMCFG_MAX_NUM];
static int g_tButtonCnt;
 
static int MainPageOnPressed(struct Button *ptButton, PDispBuff ptDispBuff, PInputEvent ptInputEvent)
{
  unsigned int dwColor = BUTTON_DEFAULT_COLOR;
  char name[100];
  char status[100];
  char *strButton;
  char *command_status[3] = {"err", "ok", "percent"};
  int command_status_index = 0;
  char command[1000];
  PItemCfg ptItemCfg;
 
  strButton = ptButton->name;
  
  /* 1. 对于触摸屏事件 */
  if (ptInputEvent->iType == INPUT_TYPE_TOUCH)
  {
    /* 1.1 分辨能否被点击 */
    if (GetItemCfgByName(ptButton->name)->bCanBeTouched == 0)
      return -1;
 
    /* 1.2 修改颜色 */
    ptButton->status = !ptButton->status;
    if (ptButton->status)
    {
      dwColor = BUTTON_PRESSED_COLOR;
      command_status_index = 1;
    }
  }
  else if (ptInputEvent->iType == INPUT_TYPE_NET)
  {
    /* 2. 对于网络事件 */
    
    /* 根据传入的字符串修改颜色 : wifi ok, wifi err, burn 70 */
    sscanf(ptInputEvent->str, "%s %s", name, status);
    if (strcmp(status, "ok") == 0)
    {
      command_status_index = 1;
      dwColor = BUTTON_PRESSED_COLOR;
    }
    else if (strcmp(status, "err") == 0)
    {
      command_status_index = 0;
      dwColor = BUTTON_DEFAULT_COLOR;
    }
    else if (status[0] >= '0' && status[0] <= '9')
    {     
      command_status_index = 2;
      dwColor = BUTTON_PERCENT_COLOR;
      strButton = status;     
    }
    else
      return -1;
  }
  else
  {
    return -1;
  }
 
  /* 绘制底色 */
  DrawRegion(&ptButton->tRegion, dwColor);
 
  /* 居中写文字 */
  DrawTextInRegionCentral(strButton, &ptButton->tRegion, BUTTON_TEXT_COLOR);
 
  /* flush to lcd/web */
  FlushDisplayRegion(&ptButton->tRegion, ptDispBuff);
 
  /* 执行command */
  ptItemCfg = GetItemCfgByName(ptButton->name);
  if (ptItemCfg->command[0] != '\0')
  {
    sprintf(command, "%s %s", ptItemCfg->command, command_status[command_status_index]);
    system(command);
  }
  
  return 0;
}
 
static int GetFontSizeForAllButton(void)
{
  int i;
  int max_len = -1;
  int max_index = 0;
  int len;
  RegionCartesian tRegionCar;
  float k, kx, ky;
  
  /* 1. 找出name最长的Button */
  for (i = 0; i < g_tButtonCnt; i++)
  {
    len = strlen(g_tButtons[i].name);
    if (len > max_len)
    {
      max_len = len;
      max_index = i;
    }
  }
 
  /* 2. 以font_size =100, 算出它的外框 */
  SetFontSize(100);
  GetStringRegionCar(g_tButtons[max_index].name, &tRegionCar);
 
  /* 3. 把文字的外框缩放为Button的外框 */
  kx = (float)g_tButtons[max_index].tRegion.iWidth / tRegionCar.iWidth;
  ky = (float)g_tButtons[max_index].tRegion.iHeigh / tRegionCar.iHeigh;
  //printf("button width / str width   = %d/%d = %f\n", g_tButtons[max_index].tRegion.iWidth, tRegionCar.iWidth, kx);
  //printf("button height / str height = %d/%d = %f\n", g_tButtons[max_index].tRegion.iHeigh, tRegionCar.iHeigh, ky);
  if (kx < ky)
    k = kx;
  else
    k = ky;
 
  //printf("font size = %d\n", (int)(k*100));
  /* 4. 反算出font size, 只取0.80, 避免文字过于接近边界 */
  return k * 100 * 0.8;
}
 
static void GenerateButtons(void)
{
  int width, height;
  int n_per_line;
  int row, rows;
  int col;
  int n;
  PDispBuff pDispBuff;
  int xres, yres;
  int start_x, start_y;
  int pre_start_x, pre_start_y;
  PButton pButton;
  int i = 0;
  int iFontSize;
  
  /* 算出单个按钮的width/height */
  g_tButtonCnt = n = GetItemCfgCount();
  
  pDispBuff = GetDisplayBuffer();
  xres = pDispBuff->iXres;
  yres = pDispBuff->iYres;
  width = sqrt(1.0/0.618 *xres * yres / n);
  n_per_line = xres / width + 1;
  width  = xres / n_per_line;
  height = 0.618 * width; 
 
  /* 居中显示:  计算每个按钮的region  */
  start_x = (xres - width * n_per_line) / 2;
  rows    = n / n_per_line;
  if (rows * n_per_line < n)
    rows++;
  
  start_y = (yres - rows*height)/2;
 
  /* 计算每个按钮的region */
  for (row = 0; (row < rows) && (i < n); row++)
  {
    pre_start_y = start_y + row * height;
    pre_start_x = start_x - width;
    for (col = 0; (col < n_per_line) && (i < n); col++)
    {
      pButton = &g_tButtons[i];
      pButton->tRegion.iLeftUpX = pre_start_x + width;
      pButton->tRegion.iLeftUpY = pre_start_y;
      pButton->tRegion.iWidth   = width - X_GAP;
      pButton->tRegion.iHeigh   = height - Y_GAP;
      pre_start_x = pButton->tRegion.iLeftUpX;
 
      /* InitButton */
      InitButton(pButton, GetItemCfgByIndex(i)->name, NULL, NULL, MainPageOnPressed);
      i++;
    }
  }
 
  iFontSize = GetFontSizeForAllButton();
  //SetFontSize(iFontSize);
 
  /* OnDraw */
  for (i = 0; i < n; i++)
  {
    g_tButtons[i].iFontSize = iFontSize;
    g_tButtons[i].OnDraw(&g_tButtons[i], pDispBuff);
  }
}
 
static int isTouchPointInRegion(int iX, int iY, PRegion ptRegion)
{
  if (iX < ptRegion->iLeftUpX || iX >= ptRegion->iLeftUpX + ptRegion->iWidth)
    return 0;
 
  if (iY < ptRegion->iLeftUpY || iY >= ptRegion->iLeftUpY + ptRegion->iHeigh)
    return 0;
 
  return 1;
}
 
 
static PButton GetButtonByName(char *name)
{
  int i;
  
  for (i = 0; i < g_tButtonCnt; i++)
  {
    if (strcmp(name, g_tButtons[i].name) == 0)
      return &g_tButtons[i];
  }
 
  return NULL;
}
 
 
static PButton GetButtonByInputEvent(PInputEvent ptInputEvent)
{
  int i;
  char name[100];
  
  if (ptInputEvent->iType == INPUT_TYPE_TOUCH)
  {
    for (i = 0; i < g_tButtonCnt; i++)
    {
      if (isTouchPointInRegion(ptInputEvent->iX, ptInputEvent->iY, &g_tButtons[i].tRegion))
        return &g_tButtons[i];
    }
  }
  else if (ptInputEvent->iType == INPUT_TYPE_NET)
  {
    sscanf(ptInputEvent->str, "%s", name);
    return GetButtonByName(name);
  }
  else
  {
    return NULL;
  }
  return NULL;
}
 
 
static void MainPageRun(void *pParams)
{
  int error;
  InputEvent tInputEvent;
  PButton ptButton;
  PDispBuff ptDispBuff = GetDisplayBuffer();
  
  /* 读取配置文件 */
  error = ParseConfigFile();
  if (error)
    return ;
 
  /* 根据配置文件生成按钮、界面 */
  GenerateButtons();
 
  while (1)
  {
    /* 读取输入事件 */
    error = GetInputEvent(&tInputEvent);
    if (error)
      continue;
 
    /* 根据输入事件找到按钮 */
    ptButton = GetButtonByInputEvent(&tInputEvent);
    if (!ptButton)
      continue;
 
    /* 调用按钮的OnPressed函数 */
    ptButton->OnPressed(ptButton, ptDispBuff, &tInputEvent);
  }
}
 
static PageAction g_tMainPage = {
  .name = "main",
  .Run  = MainPageRun,
};
 
void MainPageRegister(void)
{
  PageRegister(&g_tMainPage);
}
 
 

第22行:状态存储

第23行:默认状态为err,并且用command_status_index标记状态

第84~89行:执行command

       第84行:根据名字找到配置项

       第85行:查看是否查找到配置项

       第86行:打印出命令和命令的状态

       第87行:执行命令

2.执行命令后所执行的脚本

led.sh

#!/bin/sh
status=$1
if [ "$status" = "ok" ]
then
echo "led has been tested, it is ok"
fi
 
if [ "$status" = "err" ]
then
echo "led has been tested, it is fail"
fi

test_sleep_key.sh

#!/bin/sh
status=$1
if [ "$status" = "processing" ]
then
wakeup_count=$(cat /sys/power/wakeup_count)
echo standby > /sys/power/state
 
wakeup_count_new=$(cat /sys/power/wakeup_count)
while [ $wakeup_count_new -eq $wakeup_count ]
do
  wakeup_count_new=$(cat /sys/power/wakeup_count)
done
 
count=0
while [ $count -le 1 ]
do
  detect_dev 127.0.0.1 "ALL ok" > /dev/null 2>&1  
  sleep 1
        let count++
done
 
fi

3.ubuntu上:

book@100ask:~/31_improve_command$ dos2unix led.sh
dos2unix: converting file led.sh to Unix format...

4.开发板上:

[root@100ask:/mnt/31_improve_command]# cp led.sh /bin/
[root@100ask:/mnt/31_improve_command]# chmod +x /bin/led.sh
[root@100ask:/mnt/31_improve_command]# led.sh ok
led has been tested, it is ok
[root@100ask:/mnt/31_improve_command]# led.sh err
led has been tested, it is fail
[root@100ask:/mnt/31_improve_command]#

当点击开发板上的LED时会运行led.sh这个脚本


目录
相关文章
|
8天前
|
缓存 监控 关系型数据库
《Linux 简易速速上手小册》第10章: 性能监控与优化(2024 最新版)
《Linux 简易速速上手小册》第10章: 性能监控与优化(2024 最新版)
14 0
|
18天前
|
监控 Unix Linux
Linux操作系统调优相关工具(四)查看Network运行状态 和系统整体运行状态
Linux操作系统调优相关工具(四)查看Network运行状态 和系统整体运行状态
31 0
|
25天前
|
存储 前端开发 Linux
Linux系统之部署ToDoList任务管理工具
【4月更文挑战第1天】Linux系统之部署ToDoList任务管理工具
63 1
|
27天前
|
存储 传感器 运维
linux系统资源统计工具
【4月更文挑战第1天】Linux系统监控工具如dstat、htop、glances、vmstat、top、iostat、mpstat、sar和atop,用于跟踪CPU、内存、磁盘I/O、网络和进程性能。这些工具提供实时、交互式和历史数据分析,助力管理员优化系统性能和故障排查。例如,dstat是vmstat等工具的增强版,htop提供彩色界面的进程管理,而atop则结合了多种功能并记录历史数据。
28 5
linux系统资源统计工具
|
18天前
|
Linux
Linux操作系统调优相关工具(三)查看IO运行状态相关工具 查看哪个磁盘或分区最繁忙?
Linux操作系统调优相关工具(三)查看IO运行状态相关工具 查看哪个磁盘或分区最繁忙?
21 0
|
3天前
|
JSON Unix Linux
Linux系统之jq工具的基本使用
Linux系统之jq工具的基本使用
32 2
|
4天前
|
监控 安全 Linux
Linux系统之安装ServerBee服务器监控工具
【4月更文挑战第22天】Linux系统之安装ServerBee服务器监控工具
43 2
|
4天前
|
编解码 Linux 数据安全/隐私保护
linux工具之curl与wget高级使用
linux工具之curl与wget高级使用
|
23天前
|
负载均衡 算法 Linux
深度解析:Linux内核调度器的演变与优化策略
【4月更文挑战第5天】 在本文中,我们将深入探讨Linux操作系统的核心组成部分——内核调度器。文章将首先回顾Linux内核调度器的发展历程,从早期的简单轮转调度(Round Robin)到现代的完全公平调度器(Completely Fair Scheduler, CFS)。接着,分析当前CFS面临的挑战以及社区提出的各种优化方案,最后提出未来可能的发展趋势和研究方向。通过本文,读者将对Linux调度器的原理、实现及其优化有一个全面的认识。
|
24天前
|
资源调度 JavaScript 安全
Linux系统之部署web-check网站分析工具
【4月更文挑战第3天】Linux系统之部署web-check网站分析工具
70 9