/** * \file * * * \author Bernie Innocenti * * \brief Custom control for graphics LCD emulation (implementation) */ #include "lcd_gfx_qt.h" #include #include #include // CONFIG_BITMAP_FMT #include #include #include #include // Display colors #define LCD_FG_COLOR 0x0, 0x0, 0x0 #define LCD_BG_COLOR 0xBB, 0xCC, 0xBB EmulLCD::EmulLCD(QWidget *parent) : QFrame(parent), fg_color(LCD_FG_COLOR), bg_brush(QColor(LCD_BG_COLOR)) { // Optimized rendering: we repaint everything anyway setAttribute(Qt::WA_NoSystemBackground); // initialize bitmap memset(raster, 0xAA, sizeof(raster)); // set widget frame setFrameStyle(QFrame::Panel | QFrame::Sunken); frame_width = frameWidth(); setMinimumSize(WIDTH + frame_width * 2, HEIGHT + frame_width * 2); #if CONFIG_EMULLCD_SCALE QSizePolicy pol = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred, QSizePolicy::Frame); pol.setHeightForWidth(true); #else QSizePolicy pol = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, QSizePolicy::Frame); #endif setSizePolicy(pol); } EmulLCD::~EmulLCD() { // nop } #if CONFIG_EMULLCD_SCALE int EmulLCD::heightForWidth(int w) const { int h; w -= frame_width * 2; h = (w * HEIGHT + WIDTH/2) / WIDTH; h += frame_width * 2; return h; } #endif // CONFIG_EMULLCD_SCALE void EmulLCD::paintEvent(QPaintEvent * /*event*/) { QPainter p(this); QImage img(raster, WIDTH, HEIGHT, QImage::Format_Mono); #if CONFIG_EMULLCD_SCALE int w = width() - frame_width * 2; int h = height() - frame_width * 2; if ((w != WIDTH) || (h != HEIGHT)) { p.scale((qreal)w / WIDTH, (qreal)h / HEIGHT); //p.setRenderHint(QPainter::SmoothPixmapTransform); } #endif // CONFIG_EMULLCD_SCALE p.setBackgroundMode(Qt::OpaqueMode); p.setBackground(bg_brush); p.setPen(fg_color); p.drawImage(QPoint(frame_width, frame_width), img); } void EmulLCD::writeRaster(uint8_t *new_raster) { #if CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_H_MSB // Straight copy //memcpy(raster, new_raster, sizeof(raster)); // Inverting copy for (int i = 0; i < (int)sizeof(raster); ++i) raster[i] = ~new_raster[i]; #elif CONFIG_BITMAP_FMT == BITMAP_FMT_PLANAR_V_LSB // Rotation + inversion for (int y = 0; y < HEIGHT; ++y) { for (int xbyte = 0; xbyte < WIDTH/8; ++xbyte) { uint8_t v = 0; for (int xbit = 0; xbit < 8; ++xbit) v |= (new_raster[(xbyte * 8 + xbit) + (y / 8) * WIDTH] & (1 << (y%8)) ) ? (1 << (7 - xbit)) : 0; raster[y * ((WIDTH + 7) / 8) + xbyte] = v; } } #else #error Unsupported bitmap format #endif repaint(); } #include #include DECLARE_WALL(wall_before_raster, WALL_SIZE) /** * Raster buffer to draw into. * * Bits in the bitmap bytes have vertical orientation, * as required by the LCD driver. */ static uint8_t lcd_raster[RAST_SIZE(EmulLCD::WIDTH, EmulLCD::HEIGHT)]; DECLARE_WALL(wall_after_raster, WALL_SIZE) /*extern "C"*/ void lcd_gfx_qt_init(Bitmap *lcd_bitmap) { //FIXME INIT_WALL(wall_before_raster); //FIXME INIT_WALL(wall_after_raster); gfx_bitmapInit(lcd_bitmap, lcd_raster, EmulLCD::WIDTH, EmulLCD::HEIGHT); gfx_bitmapClear(lcd_bitmap); } /*extern "C"*/ void lcd_gfx_qt_blitBitmap(const Bitmap *bm) { //FIXME CHECK_WALL(wall_before_raster); //FIXME CHECK_WALL(wall_after_raster); emul->emulLCD->writeRaster(bm->raster); } #include "lcd_gfx_qt_moc.cpp"