zoukankan      html  css  js  c++  java
  • DirectFB 之 通过多Window实现多元素处理

    图像



    设计

        采用多window的方式实现显示,因为每个window可以独立的属性,比如刷新频率,也是我们最关注的


    示例

    /**********************************************
     * Author: younger.liucn@hotmail.com
     * File name: dfbFont.c
     * Description:  dfbFont
     * Version, Desc
     *  1.1    Created
     *  1.2    add config
     **********************************************/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <string.h>
    
    #include <time.h>
    #include <sys/time.h>
    #include <directfb.h>
    
    #include "dfbFont.h"
    
    /* config information */
    #define DFB_LAYERID_USING        0
    #define DFB_FONT_TYPE_1 "/home/younger/DFB/Font/data/decker.ttf"
    
    
    /*********************************************************
     * log flags and func of debug and error infor.[Begin]
     ********************************************************/
    
    
    #ifdef _DFB_DEBUG_
    #define DFB_DEBUG(format, ...)    do {       
        printf("[BootAnimation:%4dL]DEBUG: "format, __LINE__, ##__VA_ARGS__);  
    } while (0)
    #else
    #define DFB_DEBUG(format, ...)    do {} while (0)
    #endif
    
    #define DFB_NOTICE(format, ...)    do {       
        printf("[BootAnimation:%4dL]INFO: "format, __LINE__, ##__VA_ARGS__);  
    } while (0)
    
    #define DFB_ERROR(format, ...)    do {       
        printf("[BootAnimation:%4dL]ERROR: "format, __LINE__, ##__VA_ARGS__);  
    } while (0)
    /*********************************************************
     * log flags and func of debug and error infor.[End]
     ********************************************************/
    
    /*********************************************************
     * Data structure and Global variants [Begin]
     ********************************************************/
    /* 使用directFB画图所需的DFB资源 */
    struct DfbResDsc {
        IDirectFB               *dfb;
        IDirectFBDisplayLayer	*layer;
    };
    static struct DfbResDsc badsc;
    
    struct WinResDsc {
        IDirectFBWindow			*window;
        IDirectFBSurface		*surface;
    };
    static struct WinResDsc winText;
    /* 如果位置值(OFFSET_X或OFFSET_Y)设置为-1,表示居中显示 */
    #define WINDOW_TEXT_LEN_X	(800)
    #define WINDOW_TEXT_LEN_Y	(100)
    #define WINDOW_TEXT_OFFSET_X	(-1)
    #define WINDOW_TEXT_OFFSET_Y	(500)
    static char *testString = "Hello world! This is DirectFB!";
    
    static struct WinResDsc winAnim;
    /* 如果位置值(OFFSET_X或OFFSET_Y)设置为-1,表示居中显示 */
    #define WINDOW_ANIM_LEN_X	(200)
    #define WINDOW_ANIM_LEN_Y	(200)
    #define WINDOW_ANIM_OFFSET_X	(-1)
    #define WINDOW_ANIM_OFFSET_Y	(200)
    
    /* config information */
    #define ANIM_IMAGES_COUNT         48
    /* support png, jpg */
    #define ANIM_IMAGE_FORMAT         "png"
    #define ANIM_FILE_NAME_MAX_SIZE   255
    #define ANIM_IMG_DEFAULT_WIDTH    186
    #define ANIM_IMG_DEFAULT_HEIGHT   186
    #define ANIM_IMG_DEFAULT_FPS      10
    #define ANIM_MAX_RUNNING_MTIME            (20000)
    
    #define ANIM_DEFAULT_LOGO_PATH    "/home/liuyiy/DFB/FontAnim/data/images"
    
    static IDirectFBSurface *imgSfc[ANIM_IMAGES_COUNT];
    /*********************************************************
     * Data structure and Global variants [End]
     ********************************************************/
     
    /* 初始化/释放资源dfb/layer  [Begin] */
    void freeResources()
    {
        /* Release the layer. */
        if (badsc.layer)
            badsc.layer->Release(badsc.layer);
    
        badsc.dfb->Release(badsc.dfb);
    
        return ;
    }
    
    static void initResources(int argc, char **argv)
    {
        DFBResult ret;
        badsc.dfb	    = NULL;
        IDirectFB *dfb  = NULL;
    
    	/* 初始化DirectFB */
        DirectFBInit(&argc, &argv);
        DirectFBCreate(&dfb);
        if (!dfb) {
            DFB_ERROR("directfb interface is NULL
    ");
            return ;
        }
        badsc.dfb = dfb;
    
        /* 初始化 display layer:其中DFB_LAYERID_USING设置为0.*/
        ret = badsc.dfb->GetDisplayLayer(badsc.dfb, DFB_LAYERID_USING, &(badsc.layer));
        if(ret != (DFBResult)DFB_OK) {
            DFB_ERROR("Get layer(%d) failed!
    ", DFB_LAYERID_USING);
            goto fail;
        } else {
            DFB_DEBUG("Get layer(%d) independently.
    ", DFB_LAYERID_USING);
        }
    
        return ;
    fail:
        freeResources();
        return ;
    }
    /* 初始化/释放资源dfb/layer  [End] */
    
    /* 初始化/释放资源WinResDsc  [Begin] */
    static void deinitWinRes(struct WinResDsc *winres)
    {
    
        winres->surface->SetColor(winres->surface, 0, 0, 0, 0);
        winres->surface->Clear(winres->surface, 0, 0, 0, 0);
        winres->surface->Flip(winres->surface, NULL, DSFLIP_WAITFORSYNC);
    	
        /* Release the window's surface. */
        if(winres->surface)
            winres->surface->Release(winres->surface);
        /* Release the window. */
        if (winres->window)
            winres->window->Release(winres->window);
    
        return ;
    }
    
    static void initWinResPercent(struct WinResDsc *winres,
    						int window_offset_x,
    						int window_offset_y,
    						int window_len_x,
    						int window_len_y
    						)
    {
        DFBResult ret;
        IDirectFBWindow			*window		= NULL;
        IDirectFBSurface		*surface	= NULL;
        DFBWindowDescription	desc;
        DFBDisplayLayerConfig	config;
    
        /* 获取display layer的配置,. */
        badsc.layer->GetConfiguration(badsc.layer, &config);
    
        /* 设置window参数,并创建Window */
        desc.flags   = (DFBWindowDescriptionFlags)(DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS | DWDESC_OPTIONS);
        DFB_NOTICE("Layer Screen width %d, height %d !
    ", config.width, config.height);
    	/* 固定window在layer的中位置 */
    	if (-1 == window_offset_x) {
    		desc.posx    = (config.width - window_len_x) / 2;
    	} else {
    		desc.posx    = window_offset_x;
    	}
    	if (-1 == window_offset_y) {
    		desc.posy    = (config.height - window_len_y) / 2;
    	} else {
    		desc.posy    = window_offset_y;
    	}
        desc.width   = window_len_x;
        desc.height  = window_len_y;
        desc.caps    = (DFBWindowCapabilities)(DWCAPS_NODECORATION);
        desc.options = (DFBWindowOptions) (DWOP_GHOST);
        ret = badsc.layer->CreateWindow(badsc.layer, &desc, &window);
        if(ret != (DFBResult)DFB_OK) {
            DFB_ERROR("Create window failed!
    ");
    		return ;
        }
    
    	/* 设置透明度 */
        ret = window->SetOpacity(window, 0xFF);
        if(ret != (DFBResult)DFB_OK) {
            DFB_ERROR("SetOpacity failed!
    ");
            window->Release(window);
    		return ;
        }
    
        /* 获取window的surface. */
        ret = window->GetSurface(window, &surface);
        if(ret != (DFBResult)DFB_OK) {
            DFB_ERROR("GetSurface failed!
    ");
    		return ;
        }
    	/*若不执行clear,则可能出现花屏*/
        surface->SetColor(surface, 0, 0, 0, 0);
        surface->Clear(surface, 0, 0, 0, 0);
        surface->Flip(surface, NULL, DSFLIP_WAITFORSYNC);
    	winres->window = window;
    	winres->surface = surface;
        return ;
    }
    /* 初始化/释放资源WinResDsc  [End] */
    
    /* 绘制字符串 */
    static void flipText(char* str) {
        int width = 0, height = 0;
    	IDirectFBFont* font = NULL;
        DFBFontDescription font_desc;
        IDirectFBSurface *surface = winText.surface;
    
        surface->GetSize(surface, &width, &height);
    
    	/* font init */
        font_desc.flags = DFDESC_HEIGHT;
        font_desc.height = height / 2;
    	badsc.dfb->CreateFont(badsc.dfb, DFB_FONT_TYPE_1, &font_desc, &font);
    
        surface->Clear(surface, 0x0, 0x0, 0x0, 0xff);
        surface->SetFont(surface, font);
    	/* 设置前景颜色 */
        surface->SetColor(surface, 0x00, 0xFF, 0x00, 0xFF);
        surface->DrawString(surface, str, strlen(str), width / 2, height / 2, DSTF_CENTER);
        /* 变换、更新surface buffer */
    	surface->Flip(surface, NULL, DSFLIP_WAITFORSYNC);
    	return ;
    }
    
    
    /* 绘制动画 [Begin] */
    static inline int checkFileExist(const char *filename)
    {
        if((access(filename, R_OK)) != -1)
            return 1;
    
        return 0;
    }
    static int doLoadImg(const char  *filename,
                            IDirectFBSurface      **surface,
                            unsigned int           *width,
                            unsigned int           *height)
    {
        int ret;
        IDirectFB *dfb = badsc.dfb;
        DFBSurfaceDescription img_dsc;
        IDirectFBImageProvider *provider = NULL;
    
        if(NULL == surface || NULL == filename) {
            DFB_ERROR("doLoadImg() failed for %d.
    ", -EINVAL);
            return -EINVAL;
        }
    
        DFB_DEBUG("doLoadImg() entry:%s .
    ", filename);
    	/* 检查图片是否存在 */
        if(!checkFileExist(filename)) {
            DFB_ERROR("file %s does not exist.
    ", filename);
            return -EINVAL;
        }
    
        /* 将要显示的图片及其相关信息保存在一个image provider中 */
        ret = dfb->CreateImageProvider(dfb, filename, &provider);
        if(ret) {
            DFB_ERROR("CreateImageProvider() for %s failed %d.
    ", filename, ret);
            return ret;
        }
    
        /* 将保存在provider中的图片信息提取出来,存于surface description中 */
        ret = provider->GetSurfaceDescription(provider, &img_dsc);
        if(ret) {
            DFB_ERROR("GetSurfaceDescription() for %s failed %d.
    ",
                    filename, ret);
            provider->Release(provider);
            return ret;
        }
    
        /* 根据surface description创建surface,尺寸与图片大小完全一致 */
        ret = dfb->CreateSurface(dfb, &img_dsc, surface);
        if(ret) {
            DFB_ERROR("CreateSurface() for %s failed %d.
    ", filename, ret);
            provider->Release(provider);
            return ret;
        }
    
        /* 将图片呈递给刚才建立的logo平面,如果大小不一致,则进行缩放 */
        ret = provider->RenderTo(provider, *surface, NULL);
        if(ret) {
            DFB_ERROR("RenderTo() for %s failed %d.
    ", filename, ret);
            (*surface)->Release(*surface);
            provider->Release(provider);
            return ret;
        }
    
        /* Return width / height? */
        if(width) {
            *width = img_dsc.width;
        }
        if(height){
            *height  = img_dsc.height;
        }
    
        /* release provider */
        provider->Release(provider);
    
        DFB_DEBUG("doLoadImg() exit.
    ");
        return ret;
    }
    
    /* 释放图片资源 */
    static void deinitImages()
    {
      int i = 0;
      for (i = 0; i < ANIM_IMAGES_COUNT; i++) {
          if (imgSfc[i]) {
              imgSfc[i]->Release(imgSfc[i]);
          } else {
              break;
          }
      }
      return ;
    }
    /* 初始化图片资源 */
    static int initImages()
    {
        int ret = 0, i = 0;
        char filename[ANIM_FILE_NAME_MAX_SIZE];
        IDirectFBSurface *tmp_sfc = NULL;
    
        for (i = 0; i < ANIM_IMAGES_COUNT; i++) {
            imgSfc[i] = NULL;
        }
    
        for (i = 0; i < ANIM_IMAGES_COUNT; i++) {
            tmp_sfc = NULL;
            memset(filename, 0x0, sizeof(filename));
            snprintf(filename, ANIM_FILE_NAME_MAX_SIZE,
    				"%s/%02d.%s", ANIM_DEFAULT_LOGO_PATH, i, ANIM_IMAGE_FORMAT);
            ret = doLoadImg(filename, &tmp_sfc, NULL, NULL);
            if (ret != 0) {
                goto bail;
            }
            imgSfc[i] = tmp_sfc;
        }
    
        return 0;
    bail:
        deinitImages();
        return -1;
    }
    
    
    static void fillDFBSurface(
                            IDirectFBSurface *primary_sfc,
                            IDirectFBSurface *img_sfc,
                            int x, int y)
    {
        primary_sfc->Clear(primary_sfc, 0, 0, 0, 255);
    	/* 
         * blit即将两张位图(即thiz和source)按拉操作的方法组合成一张图片。 
         * 在DirectFB中,其定义的动作也是合理的:将img_sfc blit到primary_sfc上去, 
         * 两个平面上的内容会产生叠加 
         */ 
        primary_sfc->Blit(primary_sfc, img_sfc, NULL, x, y);
    	/* 变换、更新surface buffer */  
        primary_sfc->Flip(primary_sfc, NULL, DSFLIP_WAITFORSYNC);
    
        return ;
    }
    
    /* 获取b与a的时间差,单位:毫秒 */
    static unsigned long deltaMsecs(struct timespec *a,
            struct timespec *b)
    {
        long delta_secs = 0, delta_msecs = 0;
    
        if(a->tv_sec < b->tv_sec ||
                (a->tv_sec == b->tv_sec && a->tv_nsec < b->tv_nsec)) {
            return 0;
        }
    
        delta_secs = a->tv_sec - b->tv_sec;
        delta_msecs = (a->tv_nsec - b->tv_nsec) / 1000000;
        while(delta_msecs < 0) {
            delta_secs--;
            delta_msecs += 1000;
        }
    
        return delta_secs * 1000 + delta_msecs;
    }
    
    static void doAnimation()
    {
        int ret, i;
        struct timespec before_draw, after_draw;
        unsigned long elapsed_msec, total_msec;
        IDirectFBSurface *primary = winAnim.surface;
        unsigned long interval = (1000 / ANIM_IMG_DEFAULT_FPS);
    	
        if (initImages()) {
            DFB_ERROR("Init images failed!
    ");
            return ;
        }
    
        DFB_NOTICE("Animation start ...
    ");
        total_msec = 0;
        i  = 0;
        do {
            if(i >= ANIM_IMAGES_COUNT) {
                i = 0;
            }
    
            clock_gettime(CLOCK_MONOTONIC, &before_draw);
            fillDFBSurface(primary, imgSfc[i],
                    0,0);
            clock_gettime(CLOCK_MONOTONIC, &after_draw);
    		/*
    		 * 获取画图前后两次的时间差elapsed_msec
    		 * 如果elapsed_msec>interval,则不再休眠
    		 * 否则休眠interval-elapsed_msec
    		 */
            elapsed_msec = deltaMsecs(&after_draw, &before_draw);
            if(elapsed_msec < interval) {
                usleep((interval - elapsed_msec) * 1000);
                total_msec += interval;
            } else {
                total_msec += elapsed_msec;
            }
            DFB_DEBUG("elapsed %lu ms 
    ",
                            elapsed_msec < interval ? interval : elapsed_msec);
            if(total_msec >= ANIM_MAX_RUNNING_MTIME) {
                DFB_NOTICE("Stopped by Timeout(%lu).
    ", total_msec);
                break;
            }
    
            i++;
        } while(1);
    
    out:
        DFB_NOTICE("Animation exit with black screen...
    ");
        deinitImages();
    
        return ;
    }
    /* 绘制动画 [End] */
    
    static void doShow()
    {
        DFB_NOTICE("Text start ...
    ");
    	flipText(testString);
    	doAnimation();
    
        return ;
    }
    
    int main(int argc, char **argv)
    {
        DFB_NOTICE("Animation entry.
    ");
        initResources(argc, argv);
    	initWinResPercent(&winText,
    			WINDOW_TEXT_OFFSET_X, WINDOW_TEXT_OFFSET_Y,
    			WINDOW_TEXT_LEN_X, WINDOW_TEXT_LEN_Y);
    	initWinResPercent(&winAnim,
    			WINDOW_ANIM_OFFSET_X, WINDOW_ANIM_OFFSET_Y,
    			WINDOW_ANIM_LEN_X, WINDOW_ANIM_LEN_Y);
        doShow();
    	deinitWinRes(&winText);
    	deinitWinRes(&winAnim);
        freeResources();
    
        DFB_NOTICE("Animation exit.
    ");
        return 0;
    }
    



  • 相关阅读:
    logback使用
    数据库阿里连接池 配置
    expect.js
    shim和polyfill有什么区别
    console.js还有浏览器不支持?
    vue项目如何实现剪切板功能--vue-clipboard2
    跟我一起使用webpack给一个开源项目添加一个运行入口
    Axure之添加点击页面
    Axure之母版窗口
    【react】react-reading-track
  • 原文地址:https://www.cnblogs.com/youngerchina/p/5624446.html
Copyright © 2011-2022 走看看