mirror of
https://github.com/tuxbox-neutrino/neutrino.git
synced 2025-08-28 16:01:20 +02:00
"using namespace std" in headers is considered bad practice, so move it either into the respective cpp files or (for files which have lots of other std::xxx usage anyway) just write it out explicitly. Looking at the headers and the affected cpp files, one can actually see why it is bad practice, as it's spreading very far ;-)
869 lines
27 KiB
C++
869 lines
27 KiB
C++
/*
|
|
Based up Neutrino-GUI - Tuxbox-Project
|
|
Copyright (C) 2001 by Steffen Hehn 'McClean'
|
|
|
|
Classes for generic GUI-related components.
|
|
Copyright (C) 2012-2017, Thilo Graf 'dbt'
|
|
Copyright (C) 2012, Michael Liebmann 'micha-bbg'
|
|
|
|
License: GPL
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <global.h>
|
|
#include <neutrino.h>
|
|
#include "cc_draw.h"
|
|
#include "cc_timer.h"
|
|
#include <cs_api.h>
|
|
#include <driver/pictureviewer/pictureviewer.h>
|
|
#include <system/debug.h>
|
|
extern CPictureViewer * g_PicViewer;
|
|
|
|
CCDraw::CCDraw() : COSDFader(g_settings.theme.menu_Content_alpha)
|
|
{
|
|
frameBuffer = CFrameBuffer::getInstance();
|
|
|
|
x = cc_xr = cc_xr_old = x_old = 0;
|
|
y = cc_yr = cc_yr_old = y_old = 0;
|
|
height = height_old = CC_HEIGHT_MIN;
|
|
width = width_old = CC_WIDTH_MIN;
|
|
|
|
col_body = col_body_old = COL_MENUCONTENT_PLUS_0;
|
|
col_shadow = col_shadow_old = COL_SHADOW_PLUS_0;
|
|
col_frame = col_frame_old = COL_FRAME_PLUS_0;
|
|
col_shadow_clean = 0;
|
|
|
|
cc_body_image = cc_body_image_old = std::string();
|
|
|
|
fr_thickness = fr_thickness_old = 0;
|
|
|
|
corner_type = corner_type_old = CORNER_NONE;
|
|
corner_rad = corner_rad_old = 0;
|
|
|
|
shadow = CC_SHADOW_OFF;
|
|
shadow_w = shadow_w_old = OFFSET_SHADOW;
|
|
shadow_force = false;
|
|
|
|
cc_paint_cache = false;
|
|
cc_scrdata.pixbuf = NULL;
|
|
cc_save_bg = false;
|
|
firstPaint = true;
|
|
is_painted = false;
|
|
force_paint_bg = false;
|
|
paint_bg = true;
|
|
cc_allow_paint = true;
|
|
cc_enable_frame = true;
|
|
|
|
cc_body_gradient_enable = cc_body_gradient_enable_old = CC_COLGRAD_OFF;
|
|
cc_body_gradient_2nd_col = cc_body_gradient_2nd_col_old = COL_MENUCONTENT_PLUS_0;
|
|
|
|
cc_body_gradient_mode = CColorGradient::gradientLight2Dark;
|
|
cc_body_gradient_intensity = CColorGradient::light;
|
|
cc_body_gradient_intensity_v_min = 0x40;
|
|
cc_body_gradient_intensity_v_max = 0xE0;
|
|
cc_body_gradient_saturation = 0xC0;
|
|
cc_body_gradient_direction = cc_body_gradient_direction_old = CFrameBuffer::gradientVertical;
|
|
|
|
cc_draw_timer = NULL;
|
|
cc_draw_trigger_slot = sigc::mem_fun0(*this, &CCDraw::paintTrigger);
|
|
|
|
cc_gradient_bg_cleanup = true;
|
|
|
|
v_fbdata.clear();
|
|
}
|
|
|
|
CCDraw::~CCDraw()
|
|
{
|
|
if(cc_draw_timer){
|
|
delete cc_draw_timer; cc_draw_timer = NULL;
|
|
}
|
|
clearFbData();
|
|
}
|
|
|
|
inline bool CCDraw::applyPosChanges()
|
|
{
|
|
bool ret = false;
|
|
if (x != x_old || cc_xr != cc_xr_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], Pos changes x %d != x_old %d... [cc_xr = %d cc_xr_old = %d]\033[0m\n", __func__, __LINE__, x, x_old, cc_xr, cc_xr_old);
|
|
x_old = x;
|
|
cc_xr_old = cc_xr;
|
|
ret = true;
|
|
}
|
|
if (y != y_old || cc_yr != cc_yr_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], Pos changes y %d != y_old %d... [cc_yr = %d cc_yr_old = %d]\033[0m\n", __func__, __LINE__, y, y_old, cc_yr, cc_yr_old);
|
|
y_old = y;
|
|
cc_yr_old = cc_yr;
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
inline bool CCDraw::applyDimChanges()
|
|
{
|
|
bool ret = false;
|
|
if (height != height_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], dim changes height %d != height_old %d...\033[0m\n", __func__, __LINE__, height, height_old);
|
|
height_old = height;
|
|
ret = true;
|
|
}
|
|
if (width != width_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], dim changes width %d != width_old %d...\033[0m\n", __func__, __LINE__, width, width_old);
|
|
width_old = width;
|
|
ret = true;
|
|
}
|
|
if (fr_thickness != fr_thickness_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], dim changes fr_thickness %d != fr_thickness_old %d...\033[0m\n", __func__, __LINE__, fr_thickness, fr_thickness_old);
|
|
fr_thickness_old = fr_thickness;
|
|
ret = true;
|
|
}
|
|
if (shadow_w != shadow_w_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], dim changes shadow_w_sel %d != shadow_w_old %d...\033[0m\n", __func__, __LINE__, shadow_w, shadow_w_old);
|
|
shadow_w_old = shadow_w;
|
|
ret = true;
|
|
}
|
|
if (corner_rad != corner_rad_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], dim changes corner_rad %d != corner_rad_old %d...\033[0m\n", __func__, __LINE__, corner_rad, corner_rad_old);
|
|
corner_rad_old = corner_rad;
|
|
ret = true;
|
|
}
|
|
if (corner_type != corner_type_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], dim changes corner_type %d != corner_type_old %d...\033[0m\n", __func__, __LINE__, corner_type, corner_type_old);
|
|
corner_type_old = corner_type;
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
inline bool CCDraw::applyColChanges()
|
|
{
|
|
bool ret = false;
|
|
if (col_body != col_body_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], col changes col_body %d != col_body_old %d...\033[0m\n", __func__, __LINE__, col_body, col_body_old);
|
|
col_body_old = col_body;
|
|
ret = true;
|
|
}
|
|
if (col_shadow != col_shadow_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], col changes col_shadow %d != col_shadow_old %d...\033[0m\n", __func__, __LINE__, col_shadow, col_shadow_old);
|
|
col_shadow_old = col_shadow;
|
|
ret = true;
|
|
}
|
|
if (col_frame != col_frame_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], col changes col_frame %d != col_frame_old %d...\033[0m\n", __func__, __LINE__, col_frame, col_frame_old);
|
|
col_frame_old = col_frame;
|
|
ret = true;
|
|
}
|
|
if (cc_body_gradient_enable != cc_body_gradient_enable_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], col changes cc_body_gradient_enable %d != cc_body_gradient_enable_old %d...\033[0m\n", __func__, __LINE__, cc_body_gradient_enable, cc_body_gradient_enable_old);
|
|
cc_body_gradient_enable_old = cc_body_gradient_enable;
|
|
ret = true;
|
|
}
|
|
if (cc_body_gradient_2nd_col != cc_body_gradient_2nd_col_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], col changes cc_body_gradient_2nd_col %d != cc_body_gradient_2nd_col_old %d...\033[0m\n", __func__, __LINE__, cc_body_gradient_2nd_col, cc_body_gradient_2nd_col_old);
|
|
cc_body_gradient_2nd_col_old = cc_body_gradient_2nd_col;
|
|
ret = true;
|
|
}
|
|
if (cc_body_gradient_direction != cc_body_gradient_direction_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], col changes cc_body_gradient_direction %d != cc_body_gradient_direction_old %d...\033[0m\n", __func__, __LINE__, cc_body_gradient_direction, cc_body_gradient_direction_old);
|
|
cc_body_gradient_direction_old = cc_body_gradient_direction;
|
|
ret = true;
|
|
}
|
|
if (cc_body_image != cc_body_image_old){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], col changes cc_body_image %s != cc_body_image_old %s...\033[0m\n", __func__, __LINE__, cc_body_image.c_str(), cc_body_image_old.c_str());
|
|
cc_body_image_old = cc_body_image;
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
inline bool CCDraw::hasChanges()
|
|
{
|
|
if (applyPosChanges() || applyDimChanges() || applyColChanges())
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
inline void CCDraw::setXPos(const int& xpos)
|
|
{
|
|
if (x == xpos)
|
|
return;
|
|
x = xpos;
|
|
}
|
|
|
|
inline void CCDraw::setYPos(const int& ypos)
|
|
{
|
|
if (y == ypos)
|
|
return;
|
|
y = ypos;
|
|
}
|
|
|
|
inline void CCDraw::setHeight(const int& h)
|
|
{
|
|
if (height == h)
|
|
return;
|
|
height = h;
|
|
}
|
|
|
|
inline void CCDraw::setWidth(const int& w)
|
|
{
|
|
if (width == w)
|
|
return;
|
|
width = w;
|
|
}
|
|
|
|
void CCDraw::setFrameThickness(const int& thickness)
|
|
{
|
|
fr_thickness = thickness;
|
|
|
|
//ensure enabled frame if frame width > 0
|
|
cc_enable_frame = false;
|
|
if (fr_thickness)
|
|
cc_enable_frame = true;
|
|
}
|
|
|
|
bool CCDraw::enableColBodyGradient(const int& enable_mode, const fb_pixel_t& sec_color, const int& direction)
|
|
{
|
|
if (cc_body_gradient_enable == enable_mode && cc_body_gradient_direction == direction)
|
|
return false;
|
|
dprintf(DEBUG_DEBUG, "\033[33m[CCDraw]\t[%s - %d], change gradient mode: current=[%d] new=[%d] direction=[%d]\033[0m\n", __func__, __LINE__, cc_body_gradient_enable, enable_mode, direction);
|
|
bool ret = false;
|
|
if ((cc_body_gradient_enable != enable_mode) || (cc_body_gradient_enable == CC_COLGRAD_OFF)){
|
|
clearScreenBuffer();
|
|
cc_body_gradient_enable = enable_mode;
|
|
ret = true;
|
|
}
|
|
if (cc_body_gradient_enable == CC_COLGRAD_COL_A_2_COL_B || cc_body_gradient_enable == CC_COLGRAD_COL_B_2_COL_A)
|
|
set2ndColor(sec_color);
|
|
|
|
//handle direction
|
|
if (cc_body_gradient_direction != direction){
|
|
cc_body_gradient_direction = direction;
|
|
ret = true;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
inline void CCDraw::setCornerType(const int& type)
|
|
{
|
|
if (corner_type == type)
|
|
return;
|
|
corner_type = type;
|
|
}
|
|
|
|
inline void CCDraw::setCorner(const int& radius, const int& type)
|
|
{
|
|
setCornerType(type);
|
|
if (corner_rad == radius)
|
|
return;
|
|
corner_rad = radius;
|
|
}
|
|
|
|
gradientData_t* CCDraw::getGradientData()
|
|
{
|
|
if (cc_body_gradient_enable == CC_COLGRAD_OFF)
|
|
return NULL;
|
|
|
|
gradientData_t* gdata = new gradientData_t;
|
|
gdata->gradientBuf = NULL;
|
|
gdata->boxBuf = NULL;
|
|
gdata->direction = cc_body_gradient_direction;
|
|
gdata->mode = CFrameBuffer::pbrg_noFree;
|
|
CColorGradient ccGradient;
|
|
int gsize = cc_body_gradient_direction == CFrameBuffer::gradientVertical ? height : width;
|
|
//TODO: add modes for direction and intensity
|
|
switch (cc_body_gradient_enable){
|
|
case CC_COLGRAD_LIGHT_2_DARK:
|
|
cc_body_gradient_mode = CColorGradient::gradientLight2Dark;
|
|
break;
|
|
case CC_COLGRAD_DARK_2_LIGHT:
|
|
cc_body_gradient_mode = CColorGradient::gradientDark2Light;
|
|
break;
|
|
case CC_COLGRAD_COL_A_2_COL_B:
|
|
cc_body_gradient_mode = CColorGradient::gradientLight2Dark;
|
|
break;
|
|
case CC_COLGRAD_COL_B_2_COL_A:
|
|
cc_body_gradient_mode = CColorGradient::gradientDark2Light;
|
|
break;
|
|
case CC_COLGRAD_COL_LIGHT_DARK_LIGHT:
|
|
cc_body_gradient_mode = CColorGradient::gradientLight2Dark2Light;
|
|
break;
|
|
case CC_COLGRAD_COL_DARK_LIGHT_DARK:
|
|
cc_body_gradient_mode = CColorGradient::gradientDark2Light2Dark;
|
|
break;
|
|
}
|
|
|
|
if (cc_body_gradient_enable == CC_COLGRAD_COL_A_2_COL_B || cc_body_gradient_enable == CC_COLGRAD_COL_B_2_COL_A){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], init gradient c2c)...\033[0m\n", __func__, __LINE__);
|
|
gdata->gradientBuf = ccGradient.gradientColorToColor(col_body,
|
|
cc_body_gradient_2nd_col,
|
|
NULL,
|
|
gsize,
|
|
cc_body_gradient_mode,
|
|
cc_body_gradient_intensity);
|
|
}else{
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], init gradient single color)...\033[0m\n", __func__, __LINE__);
|
|
gdata->gradientBuf = ccGradient.gradientOneColor(col_body,
|
|
NULL,
|
|
gsize,
|
|
cc_body_gradient_mode,
|
|
cc_body_gradient_intensity,
|
|
cc_body_gradient_intensity_v_min,
|
|
cc_body_gradient_intensity_v_max,
|
|
cc_body_gradient_saturation);
|
|
}
|
|
|
|
return gdata;
|
|
}
|
|
|
|
bool CCDraw::clearSavedScreen()
|
|
{
|
|
/* Here we clean only screen buffers from background layers.
|
|
* Paint cache and gradient are not touched.
|
|
*/
|
|
bool ret = false;
|
|
for(size_t i =0; i< v_fbdata.size() ;i++) {
|
|
if (v_fbdata[i].fbdata_type == CC_FBDATA_TYPE_BGSCREEN){
|
|
if (v_fbdata[i].pixbuf){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], cleanup bg...\033[0m\n", __func__, __LINE__);
|
|
delete[] v_fbdata[i].pixbuf;
|
|
v_fbdata[i].pixbuf = NULL;
|
|
ret = true;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool CCDraw::clearPaintCache()
|
|
{
|
|
/* Here we clean only the paint cache from foreground layers.
|
|
* BG layer is not touched.
|
|
*/
|
|
bool ret = false;
|
|
for(size_t i =0; i< v_fbdata.size() ;i++) {
|
|
if (v_fbdata[i].fbdata_type != CC_FBDATA_TYPE_BGSCREEN){
|
|
if (v_fbdata[i].pixbuf){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], cleanup paint cache layer...\033[0m\n", __func__, __LINE__);
|
|
delete[] v_fbdata[i].pixbuf;
|
|
v_fbdata[i].pixbuf = NULL;
|
|
ret = true;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//clean old gradient buffer
|
|
bool CCDraw::clearFbGradientData()
|
|
{
|
|
bool ret = false;
|
|
for(size_t i =0; i< v_fbdata.size() ;i++) {
|
|
if (v_fbdata[i].gradient_data){
|
|
if (v_fbdata[i].gradient_data->gradientBuf){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], clean up gradientBuf \t %p...\033[0m\n", __func__, __LINE__, v_fbdata[i].gradient_data->gradientBuf);
|
|
free(v_fbdata[i].gradient_data->gradientBuf);
|
|
v_fbdata[i].gradient_data->gradientBuf = NULL;
|
|
}
|
|
if (v_fbdata[i].gradient_data->boxBuf){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], clean up boxBuf \t %p...\033[0m\n", __func__, __LINE__, v_fbdata[i].gradient_data->boxBuf);
|
|
cs_free_uncached(v_fbdata[i].gradient_data->boxBuf);
|
|
v_fbdata[i].gradient_data->boxBuf = NULL;
|
|
}
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], clean up gradient data \t %p...\033[0m\n", __func__, __LINE__, v_fbdata[i].gradient_data);
|
|
delete v_fbdata[i].gradient_data;
|
|
v_fbdata[i].gradient_data = NULL;
|
|
ret = true;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool CCDraw::clearScreenBuffer()
|
|
{
|
|
bool ret = false;
|
|
if (clearSavedScreen())
|
|
ret = true;
|
|
if (clearPaintCache())
|
|
ret = true;
|
|
if (clearFbGradientData())
|
|
ret = true;
|
|
firstPaint = true;
|
|
return ret;
|
|
}
|
|
|
|
void CCDraw::clearFbData()
|
|
{
|
|
clearScreenBuffer();
|
|
v_fbdata.clear();
|
|
}
|
|
|
|
bool CCDraw::CheckFbData(const cc_fbdata_t& fbdata, const char* func, const int line)
|
|
{
|
|
int32_t rows = fbdata.dx / (int32_t)frameBuffer->getScreenWidth(true) - 1 + fbdata.y;
|
|
int32_t rest = fbdata.dx % (int32_t)frameBuffer->getScreenWidth(true);
|
|
int32_t end = rows * (int32_t)frameBuffer->getScreenWidth(true) + rest;
|
|
if ( (fbdata.x < 0 || fbdata.y < 0) ||
|
|
(end >= (int32_t)frameBuffer->getScreenWidth(true)*(int32_t)frameBuffer->getScreenHeight(true))
|
|
) {
|
|
dprintf(DEBUG_NORMAL, "[CCDraw] ERROR! Position < 0 or > FB end [%s - %d]\n\tx = %d y = %d\n\tdx = %d dy = %d\n",
|
|
func, line,
|
|
fbdata.x, fbdata.y,
|
|
fbdata.dx, fbdata.dy);
|
|
return false;
|
|
}
|
|
if (fbdata.dx == 0 || fbdata.dy == 0) {
|
|
dprintf(DEBUG_DEBUG,"[CCDraw]\t[%s - %d], INFO! dx and/or dy = 0, tx = %d, y = %d, dx = %d, dy = %d\n",
|
|
func, line,
|
|
fbdata.x, fbdata.y,
|
|
fbdata.dx, fbdata.dy);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
//screen area save
|
|
fb_pixel_t* CCDraw::getScreen(int ax, int ay, int dx, int dy)
|
|
{
|
|
fb_pixel_t* pixbuf = NULL;
|
|
|
|
if (dx < 1 || dy < 1 || dx * dy == 0)
|
|
return NULL;
|
|
else
|
|
pixbuf = new fb_pixel_t[dx * dy];
|
|
|
|
frameBuffer->waitForIdle("CCDraw::getScreen()");
|
|
frameBuffer->SaveScreen(ax, ay, dx, dy, pixbuf);
|
|
return pixbuf;
|
|
}
|
|
|
|
cc_screen_data_t CCDraw::getScreenData(const int& ax, const int& ay, const int& dx, const int& dy)
|
|
{
|
|
cc_screen_data_t res;
|
|
res.x = res.y = res.dx = res.dy = 0;
|
|
res.pixbuf = getScreen(ax, ay, dx, dy);
|
|
|
|
if (res.pixbuf){
|
|
res.x = ax; res.y = ay; res.dx = dx; res.dy = dy;
|
|
}
|
|
else
|
|
dprintf(DEBUG_NORMAL, "\033[33m[CCDraw]\[%s - %d], Warning: initialize of screen buffer failed!\033[0m\n", __func__, __LINE__);
|
|
|
|
return res;
|
|
}
|
|
|
|
void CCDraw::enableSaveBg(bool save_bg)
|
|
{
|
|
if (!cc_save_bg || (cc_save_bg != save_bg))
|
|
clearSavedScreen();
|
|
cc_save_bg = save_bg;
|
|
}
|
|
|
|
void CCDraw::enablePaintCache(bool enable)
|
|
{
|
|
if (!cc_paint_cache || (cc_paint_cache != enable))
|
|
clearPaintCache();
|
|
cc_paint_cache = enable;
|
|
}
|
|
|
|
//paint framebuffer layers
|
|
void CCDraw::paintFbItems(bool do_save_bg)
|
|
{
|
|
//Pick up signal if filled and execute slots.
|
|
OnBeforePaintLayers();
|
|
|
|
//First we modify background handling.
|
|
enableSaveBg(do_save_bg);
|
|
|
|
//Save background before first paint, cc_save_bg must be true.
|
|
if (firstPaint && cc_save_bg){
|
|
/* On first we must ensure that screen buffer is empty.
|
|
* Here we clean possible screen buffers in bg layers,
|
|
* without paint cache and gradient buffer.
|
|
*/
|
|
clearSavedScreen();
|
|
|
|
/* On second step we check for
|
|
* usable item dimensions and exit here if found any problem.
|
|
*/
|
|
for(size_t i=0; i<v_fbdata.size(); i++){
|
|
if (!CheckFbData(v_fbdata[i], __func__, __LINE__)){
|
|
break;
|
|
}
|
|
|
|
/* Here we save the background of current box before paint.
|
|
* Only the reserved fbdata type CC_FBDATA_TYPE_BGSCREEN is here required and is used for this.
|
|
* This pixel buffer is required for the hide() method that will
|
|
* call the restore method from framebuffer class to restore
|
|
* background.
|
|
*/
|
|
if (v_fbdata[i].fbdata_type == CC_FBDATA_TYPE_BGSCREEN){
|
|
v_fbdata[i].pixbuf = getScreen(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy);
|
|
break;
|
|
}
|
|
}
|
|
firstPaint = false;
|
|
}
|
|
|
|
for(size_t i=0; i< v_fbdata.size(); i++){
|
|
cc_fbdata_t& fbdata = v_fbdata[i];
|
|
|
|
int fbtype = fbdata.fbdata_type;
|
|
|
|
//ignore bg screen layer
|
|
if (fbtype == CC_FBDATA_TYPE_BGSCREEN)
|
|
continue;
|
|
|
|
// Don't paint on dimension or position error dx or dy are 0.
|
|
if (!CheckFbData(fbdata, __func__, __LINE__))
|
|
continue;
|
|
|
|
/* Paint all fb relevant basic parts (shadow, frame and body)
|
|
* with all specified properties, paint_bg must be enabled.
|
|
*/
|
|
if (cc_enable_frame && cc_body_image.empty()){
|
|
if (fbtype == CC_FBDATA_TYPE_FRAME) {
|
|
if (fbdata.frame_thickness > 0 && cc_allow_paint){
|
|
frameBuffer->paintBoxFrame(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, fbdata.frame_thickness, fbdata.color, fbdata.r, fbdata.rtype);
|
|
v_fbdata[i].is_painted = true;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
if (paint_bg){
|
|
if (fbtype == CC_FBDATA_TYPE_BACKGROUND){
|
|
frameBuffer->paintBackgroundBoxRel(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy);
|
|
v_fbdata[i].is_painted = true;
|
|
continue;
|
|
}
|
|
}
|
|
if (fbtype == CC_FBDATA_TYPE_SHADOW_BOX && ((!is_painted || !fbdata.is_painted)|| shadow_force || force_paint_bg)) {
|
|
if (fbdata.enabled) {
|
|
/* Here we paint the shadow around the body.
|
|
* On 1st step we check for already cached screen buffer, if true
|
|
* then restore this instead to call the paint methode.
|
|
* This could be usally, if we use an existant instances of "this" object
|
|
*/
|
|
if (cc_allow_paint){
|
|
if (fbdata.pixbuf){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], paint shadow from cache...\033[0m\n", __func__, __LINE__);
|
|
frameBuffer->RestoreScreen(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, fbdata.pixbuf);
|
|
}else{
|
|
frameBuffer->paintBoxRel(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, fbdata.color, fbdata.r, fbdata.rtype);
|
|
}
|
|
//If is paint cache enabled, catch screen into cache
|
|
if (cc_paint_cache && fbdata.pixbuf == NULL)
|
|
fbdata.pixbuf = getScreen(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy);
|
|
fbdata.is_painted = true;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
if (paint_bg){
|
|
if (fbtype == CC_FBDATA_TYPE_BOX){
|
|
if(cc_allow_paint) {
|
|
/* Here we paint the main body of box.
|
|
* On 1st step we check for already cached background buffer, if true
|
|
* then restore this instead to call the paint methodes and gradient creation.
|
|
* Paint cache can be enable/disable with enablePaintCache()
|
|
*/
|
|
if (fbdata.pixbuf){
|
|
/* If is paint cache enabled and cache is filled, it's prefered to paint
|
|
* from cache. Cache is also filled if body background images are used
|
|
*/
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], paint body from cache...\033[0m\n", __func__, __LINE__);
|
|
frameBuffer->RestoreScreen(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, fbdata.pixbuf);
|
|
}else{
|
|
//Ensure clean gradient data on disabled gradient.
|
|
if(cc_body_gradient_enable == CC_COLGRAD_OFF && fbdata.gradient_data){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], gradient mode is disabled but filled\033[0m\n", __func__, __LINE__);
|
|
clearFbGradientData();
|
|
}
|
|
|
|
/* If background image is defined,
|
|
* we try to render an image instead to render default box.
|
|
* Paint of background image is prefered, next steps will be ignored!
|
|
*/
|
|
if (!cc_body_image.empty()){
|
|
if (g_PicViewer->DisplayImage(cc_body_image, fbdata.x, fbdata.y, fbdata.dx, fbdata.dy)){
|
|
// catch screen and store into paint cache
|
|
fbdata.pixbuf = getScreen(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy);
|
|
fbdata.is_painted = true;
|
|
}else{
|
|
if (fbdata.pixbuf){
|
|
delete[] fbdata.pixbuf;
|
|
fbdata.pixbuf = NULL;
|
|
}
|
|
fbdata.is_painted = false;
|
|
}
|
|
|
|
// On failed image paint, write this into log and reset image name.
|
|
if (!fbdata.is_painted){
|
|
dprintf(DEBUG_NORMAL, "\033[33m\[CCDraw]\t[%s - %d], WARNING: bg image %s defined, but paint failed,\nfallback to default rendering...\033[0m\n", __func__, __LINE__, cc_body_image.c_str());
|
|
cc_body_image = "";
|
|
}
|
|
}
|
|
|
|
/* If no background image is defined, we paint default box or box with gradient
|
|
* This is also possible if any background image is defined but image paint ist failed
|
|
*/
|
|
if (cc_body_image.empty()){
|
|
if (cc_body_gradient_enable != CC_COLGRAD_OFF ){
|
|
|
|
/* If color gradient enabled we create a gradient_data
|
|
* instance and add it to the fbdata object
|
|
* On disabled color gradient or image paint was failed, we do paint only a default box
|
|
*/
|
|
if (fbdata.gradient_data == NULL){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], create new gradient data)...\033[0m\n", __func__, __LINE__);
|
|
fbdata.gradient_data = getGradientData();
|
|
}
|
|
|
|
if (fbdata.gradient_data->boxBuf == NULL){
|
|
if (fbdata.pixbuf == NULL){
|
|
/* Before we paint any gradient box with hw acceleration, we must cleanup first.
|
|
* FIXME: This is only a workaround for this framebuffer behavior on enabled hw acceleration.
|
|
* Without this, ugly ghost letters or ghost images inside gradient boxes are possible.
|
|
*/
|
|
if (cc_gradient_bg_cleanup)
|
|
frameBuffer->paintBoxRel(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, 0, fbdata.r, fbdata.rtype);
|
|
|
|
// create gradient buffer and paint gradient box
|
|
fbdata.gradient_data->boxBuf = frameBuffer->paintBoxRel(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, 0, fbdata.gradient_data, fbdata.r, fbdata.rtype);
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], paint and cache new gradient into gradient cache...\033[0m\n", __func__, __LINE__);
|
|
}
|
|
|
|
/* On enabled paint cache or clean up, catch the screen into paint cache and clean up unused gradient buffer.
|
|
* If we don't do this explicit, gradient cache is used.
|
|
*/
|
|
if (cc_paint_cache || cc_gradient_bg_cleanup){
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], cache new created gradient into external cache...\033[0m\n", __func__, __LINE__);
|
|
fbdata.pixbuf = getScreen(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy);
|
|
if (clearFbGradientData())
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], remove unused gradient data...\033[0m\n", __func__, __LINE__);
|
|
}
|
|
}else{
|
|
// If found gradient buffer, paint box from gradient cache.
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], paint cached gradient)...\033[0m\n", __func__, __LINE__);
|
|
frameBuffer->checkFbArea(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, true);
|
|
frameBuffer->blitBox2FB(fbdata.gradient_data->boxBuf, fbdata.gradient_data->dx, fbdata.dy, fbdata.gradient_data->x, fbdata.y);
|
|
frameBuffer->checkFbArea(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, false);
|
|
}
|
|
}else{
|
|
/* If is nothihng cached or no background image was defined or image paint was failed,
|
|
* render a default box.
|
|
*/
|
|
dprintf(DEBUG_INFO, "\033[33m[CCDraw]\t[%s - %d], paint default box)...\033[0m\n", __func__, __LINE__);
|
|
frameBuffer->paintBoxRel(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy, fbdata.color, fbdata.r, fbdata.rtype);
|
|
|
|
//If is paint cache enabled, catch screen into cache.
|
|
if (cc_paint_cache)
|
|
fbdata.pixbuf = getScreen(fbdata.x, fbdata.y, fbdata.dx, fbdata.dy);
|
|
}
|
|
}
|
|
}
|
|
v_fbdata[i].is_painted = true;
|
|
OnAfterPaintBg();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//set is_painted attribut. if any layer was painted set it to true;
|
|
if (force_paint_bg){
|
|
is_painted = false;
|
|
}else{
|
|
for(size_t i=0; i< v_fbdata.size(); i++){
|
|
if (v_fbdata[i].is_painted){
|
|
is_painted = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//reset is painted ignore flag to default value
|
|
force_paint_bg = false;
|
|
|
|
OnAfterPaintLayers();
|
|
}
|
|
|
|
bool CCDraw::isPainted()
|
|
{
|
|
return is_painted;
|
|
}
|
|
|
|
void CCDraw::hide()
|
|
{
|
|
OnBeforeHide();
|
|
//restore saved screen background of item if available
|
|
for(size_t i =0; i< v_fbdata.size() ;i++) {
|
|
if (v_fbdata[i].fbdata_type == CC_FBDATA_TYPE_BGSCREEN){
|
|
if (v_fbdata[i].pixbuf) {
|
|
//restore screen from backround layer
|
|
frameBuffer->waitForIdle("CCDraw::hide()");
|
|
frameBuffer->RestoreScreen(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy, v_fbdata[i].pixbuf);
|
|
v_fbdata[i].is_painted = false;
|
|
}
|
|
}
|
|
}
|
|
firstPaint = true;
|
|
is_painted = false;
|
|
OnAfterHide();
|
|
}
|
|
|
|
//erase or paint over rendered objects
|
|
void CCDraw::kill(const fb_pixel_t& bg_color, const int& corner_radius, const int& fblayer_type /*fbdata_type*/)
|
|
{
|
|
int layers = fblayer_type;
|
|
|
|
if (fblayer_type & ~CC_FBDATA_TYPES)
|
|
layers = CC_FBDATA_TYPES;
|
|
|
|
for(size_t i =0; i< v_fbdata.size() ;i++){
|
|
if (v_fbdata[i].fbdata_type & layers){
|
|
|
|
int r = 0;
|
|
|
|
if (corner_radius > -1){
|
|
r = v_fbdata[i].r;
|
|
if (corner_radius != v_fbdata[i].r)
|
|
r = corner_radius;
|
|
}
|
|
|
|
if (v_fbdata[i].dx > 0 && v_fbdata[i].dy > 0){
|
|
frameBuffer->paintBoxRel(v_fbdata[i].x,
|
|
v_fbdata[i].y,
|
|
v_fbdata[i].dx,
|
|
v_fbdata[i].dy,
|
|
bg_color,
|
|
r,
|
|
v_fbdata[i].rtype);
|
|
|
|
if (v_fbdata[i].fbdata_type & CC_FBDATA_TYPE_FRAME){
|
|
if (v_fbdata[i].frame_thickness)
|
|
frameBuffer->paintBoxFrame(v_fbdata[i].x,
|
|
v_fbdata[i].y,
|
|
v_fbdata[i].dx,
|
|
v_fbdata[i].dy,
|
|
v_fbdata[i].frame_thickness,
|
|
bg_color,
|
|
v_fbdata[i].r,
|
|
v_fbdata[i].rtype);
|
|
}
|
|
}else
|
|
dprintf(DEBUG_DEBUG, "\033[33m[CCDraw][%s - %d], WARNING! render with bad dimensions [dx = %d dy = %d]\033[0m\n", __func__, __LINE__, v_fbdata[i].dx, v_fbdata[i].dy );
|
|
|
|
v_fbdata[i].is_painted = false;
|
|
}
|
|
}
|
|
|
|
firstPaint = true;
|
|
is_painted = false;
|
|
}
|
|
|
|
void CCDraw::killShadow(const fb_pixel_t& bg_color, const int& corner_radius)
|
|
{
|
|
kill(bg_color, corner_radius, CC_FBDATA_TYPE_SHADOW_BOX);
|
|
}
|
|
|
|
bool CCDraw::doPaintBg(bool do_paint)
|
|
{
|
|
if (paint_bg == do_paint)
|
|
return false;
|
|
|
|
paint_bg = do_paint;
|
|
//clearSavedScreen();
|
|
return true;
|
|
}
|
|
|
|
void CCDraw::enableShadow(int mode, const int& shadow_width, bool force_paint)
|
|
{
|
|
if (shadow != mode){
|
|
killShadow();
|
|
shadow = mode;
|
|
}
|
|
if (shadow != CC_SHADOW_OFF)
|
|
if (shadow_width != -1)
|
|
setShadowWidth(shadow_width);
|
|
shadow_force = force_paint;
|
|
}
|
|
|
|
void CCDraw::paintTrigger()
|
|
{
|
|
if (is_painted)
|
|
hide();
|
|
else
|
|
paint();
|
|
}
|
|
|
|
bool CCDraw::paintBlink(CComponentsTimer* Timer)
|
|
{
|
|
if (Timer){
|
|
Timer->OnTimer.connect(cc_draw_trigger_slot);
|
|
return Timer->isRun();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CCDraw::paintBlink(const int& interval, bool is_nano)
|
|
{
|
|
if (cc_draw_timer == NULL)
|
|
cc_draw_timer = new CComponentsTimer(interval, is_nano);
|
|
cc_draw_timer->setThreadName(__func__);
|
|
|
|
return paintBlink(cc_draw_timer);
|
|
}
|
|
|
|
bool CCDraw::cancelBlink(bool keep_on_screen)
|
|
{
|
|
bool res = false;
|
|
|
|
if (cc_draw_timer){
|
|
res = cc_draw_timer->stopTimer();
|
|
delete cc_draw_timer; cc_draw_timer = NULL;
|
|
}
|
|
|
|
if(keep_on_screen)
|
|
paint1();
|
|
else
|
|
hide();
|
|
|
|
|
|
return res;
|
|
}
|
|
|
|
bool CCDraw::setBodyBGImage(const std::string& image_path)
|
|
{
|
|
if (cc_body_image == image_path)
|
|
return false;
|
|
|
|
cc_body_image = image_path;
|
|
|
|
if (clearPaintCache())
|
|
dprintf(DEBUG_NORMAL, "\033[33m\[CCDraw]\t[%s - %d], new body background image defined: %s , \033[0m\n", __func__, __LINE__, cc_body_image.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CCDraw::setBodyBGImageName(const std::string& image_name)
|
|
{
|
|
return setBodyBGImage(frameBuffer->getIconPath(image_name));
|
|
}
|