/* Based up Neutrino-GUI - Tuxbox-Project Copyright (C) 2001 by Steffen Hehn 'McClean' Classes for generic GUI-related components. Copyright (C) 2012-2014, 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "cc_base.h" #include #include using namespace std; //abstract basic class CComponents CComponents::CComponents() : COSDFader(g_settings.theme.menu_Content_alpha) { x = saved_screen.x = 0; y = saved_screen.y = 0; cc_xr = x; cc_yr = y; height = saved_screen.dy = CC_HEIGHT_MIN; width = saved_screen.dx = CC_WIDTH_MIN; col_body = COL_MENUCONTENT_PLUS_0; col_shadow = COL_MENUCONTENTDARK_PLUS_0; col_frame = COL_MENUCONTENT_PLUS_6; col_frame_sel = COL_MENUCONTENTSELECTED_PLUS_0; corner_type = CORNER_ALL; corner_rad = 0; cc_tag = NULL; shadow = CC_SHADOW_OFF; shadow_w = SHADOW_OFFSET; fr_thickness = 0; fr_thickness_sel = 3; firstPaint = true; is_painted = false; paint_bg = true; save_tbox_screen = false; cc_allow_paint = true; frameBuffer = CFrameBuffer::getInstance(); v_fbdata.clear(); saved_screen.pixbuf = NULL; col_body_gradient = false; cc_gradientData.gradientBuf = NULL; cc_gradientData.boxBuf = NULL; } CComponents::~CComponents() { hide(); clearSavedScreen(); clearFbData(); if (cc_gradientData.gradientBuf) free(cc_gradientData.gradientBuf); if (cc_gradientData.boxBuf) cs_free_uncached(cc_gradientData.boxBuf); } void CComponents::clearSavedScreen() { if (saved_screen.pixbuf) delete[] saved_screen.pixbuf; saved_screen.pixbuf = NULL; } bool CComponents::CheckFbData(const comp_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, "[CComponents] 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,"[CComponents] INFO! dx and/or dy = 0 [%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; } return true; } //paint framebuffer stuff and fill buffer void CComponents::paintFbItems(bool do_save_bg) { //save background before first paint, do_save_bg must be true if (firstPaint && do_save_bg){ for(size_t i=0; isave screen: %d, fbdata_type: %d\n\tx = %d\n\ty = %d\n\tdx = %d\n\tdy = %d\n", __func__, __LINE__, firstPaint, v_fbdata[i].fbdata_type, v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy); saved_screen.x = v_fbdata[i].x; saved_screen.y = v_fbdata[i].y; saved_screen.dx = v_fbdata[i].dx; saved_screen.dy = v_fbdata[i].dy; clearSavedScreen(); saved_screen.pixbuf = getScreen(saved_screen.x, saved_screen.y, saved_screen.dx, saved_screen.dy); firstPaint = false; break; } } for(size_t i=0; i< v_fbdata.size(); i++){ // Don't paint on dimension or position error dx or dy are 0 if (!CheckFbData(v_fbdata[i], __func__, __LINE__)){ continue; } int fbtype = v_fbdata[i].fbdata_type; dprintf(DEBUG_DEBUG, "[CComponents]\n\t[%s - %d], fbdata_[%d]\n\tx = %d\n\ty = %d\n\tdx = %d\n\tdy = %d\n", __func__, __LINE__, (int)i, v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy); //some elements can be assembled from lines and must be handled as one unit (see details line), //so all individual backgrounds of boxes must be saved and painted in "firstpaint mode" #if 0 if (firstPaint){ if (do_save_bg && fbtype == CC_FBDATA_TYPE_LINE) v_fbdata[i].pixbuf = getScreen(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy); //ensure painting of all line fb items with saved screens if (fbtype == CC_FBDATA_TYPE_LINE) firstPaint = true; else firstPaint = false; } #endif if (do_save_bg && fbtype == CC_FBDATA_TYPE_LINE) v_fbdata[i].pixbuf = getScreen(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy); //paint all fb relevant basic parts (frame and body) with all specified properties, paint_bg must be true if (fbtype != CC_FBDATA_TYPE_BGSCREEN && paint_bg){ if (fbtype == CC_FBDATA_TYPE_FRAME) { if (v_fbdata[i].frame_thickness > 0 && cc_allow_paint) frameBuffer->paintBoxFrame(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy, v_fbdata[i].frame_thickness, v_fbdata[i].color, v_fbdata[i].r, corner_type); } else if (fbtype == CC_FBDATA_TYPE_BACKGROUND) frameBuffer->paintBackgroundBoxRel(x, y, v_fbdata[i].dx, v_fbdata[i].dy); else if (fbtype == CC_FBDATA_TYPE_SHADOW_BOX) { if (shadow) { int sw = shadow_w; int sw_cur = sw; int x_sh = v_fbdata[i].x + v_fbdata[i].dx - sw; int y_sh = v_fbdata[i].y + v_fbdata[i].dy - sw; if (corner_type && v_fbdata[i].r) { //calculate positon of shadow areas x_sh += sw - 2*v_fbdata[i].r; y_sh += sw - 2*v_fbdata[i].r; //calculate current shadow width depends of current corner_rad sw_cur = max(2*v_fbdata[i].r, sw); } if (cc_allow_paint){ // shadow right frameBuffer->paintBoxRel(x_sh, v_fbdata[i].y, sw_cur, v_fbdata[i].dy-sw_cur, v_fbdata[i].color, v_fbdata[i].r, corner_type & CORNER_TOP_RIGHT); // shadow bottom frameBuffer->paintBoxRel(v_fbdata[i].x, y_sh, v_fbdata[i].dx, sw_cur, v_fbdata[i].color, v_fbdata[i].r, corner_type & CORNER_BOTTOM); } } } else { if(cc_allow_paint) { if (col_body_gradient && (v_fbdata[i].fbdata_type == CC_FBDATA_TYPE_BOX) && (v_fbdata[i].data != NULL)) { // color gradient gradientData_t *gradientData = static_cast (v_fbdata[i].data); if (gradientData->boxBuf == NULL) gradientData->boxBuf = frameBuffer->paintBoxRel(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy, 0, gradientData, v_fbdata[i].r, corner_type); else // frameBuffer->blit2FB(gradientData->boxBuf, v_fbdata[i].dx, v_fbdata[i].dy, v_fbdata[i].x, v_fbdata[i].y); frameBuffer->blitBox2FB(gradientData->boxBuf, v_fbdata[i].dx, v_fbdata[i].dy, v_fbdata[i].x, v_fbdata[i].y); } else frameBuffer->paintBoxRel(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy, v_fbdata[i].color, v_fbdata[i].r, corner_type); } } } } is_painted = true; } //screen area save inline fb_pixel_t* CComponents::getScreen(int ax, int ay, int dx, int dy) { if (dx * dy == 0) return NULL; fb_pixel_t* pixbuf = new fb_pixel_t[dx * dy]; frameBuffer->waitForIdle("CComponents::getScreen()"); frameBuffer->SaveScreen(ax, ay, dx, dy, pixbuf); return pixbuf; } //restore screen from buffer inline void CComponents::hide() { for(size_t i =0; i< v_fbdata.size() ;i++) { if (v_fbdata[i].pixbuf){ frameBuffer->waitForIdle("CComponents::hide()"); frameBuffer->RestoreScreen(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy, v_fbdata[i].pixbuf); } } clearFbData(); is_painted = false; } //erase or paint over rendered objects void CComponents::kill(const fb_pixel_t& bg_color, const int& corner_radius) { for(size_t i =0; i< v_fbdata.size() ;i++){ #if 0 if (bg_color != COL_BACKGROUND_PLUS_0) #endif int r = v_fbdata[i].r; if (corner_radius > -1) r = corner_radius; frameBuffer->paintBoxRel(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy, bg_color, r, corner_type); 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, r, corner_type); #if 0 else frameBuffer->paintBackgroundBoxRel(v_fbdata[i].x, v_fbdata[i].y, v_fbdata[i].dx, v_fbdata[i].dy); #endif } clearFbData(); firstPaint = true; is_painted = false; } //clean old screen buffer void CComponents::clearFbData() { for(size_t i =0; i< v_fbdata.size() ;i++) { if (v_fbdata[i].pixbuf) delete[] v_fbdata[i].pixbuf; #if 0 if (v_fbdata[i].data && (v_fbdata[i].fbdata_type == CC_FBDATA_TYPE_BOX)) { gradientData_t *gradientData = static_cast (v_fbdata[i].data); if (gradientData->boxBuf) cs_free_uncached(gradientData->boxBuf); } #endif } v_fbdata.clear(); } inline void CComponents::setXPos(const int& xpos) { x = xpos; } inline void CComponents::setYPos(const int& ypos) { y = ypos; } void CComponents::setFrameThickness(const int& thickness, const int& thickness_sel) { fr_thickness = thickness; if (fr_thickness_sel != thickness_sel) fr_thickness_sel = thickness_sel; } void CComponents::enableColBodyGradient(bool do_paint_gradient) { col_body_gradient = g_settings.gradiant ? do_paint_gradient : false; }