// vi:ts=4:shiftwidth=4:expandtab /*************************************************************************** graphdev.cpp - description ------------------- begin : Sun Auguest 26 2001 copyright : (C) 2001 by huyong, rick email : ccpaging@online.sh.cn rick@chinaren.com ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "debug.h" #include "display/fbdev.h" #include "display/vgadev.h" #if defined(linux) || defined(__FreeBSD__) #ifdef HAVE_GGI_LIB #include "display/libggi.h" #endif #endif using namespace std; // mmap framebuffer address GraphDev *GraphDev::mpGraphDev = NULL; // font int GraphDev::mXres = 0; int GraphDev::mYres = 0; BaseFont *GraphDev::mpAscFont = NULL; BaseFont *GraphDev::mpDblFont = NULL; // char display int GraphDev::mBlockWidth = 0; int GraphDev::mBlockHeight = 0; int GraphDev::mBlankLineHeight = 0; struct CharBitMap GraphDev::mAsc = {0}; struct CharBitMap GraphDev::mDbl = {0}; bool GraphDev::Open(char* drv) { if (drv == string("auto")) { /* auto:fbdev->ggi->vga */ cerr << "trying fbdev driver" << endl; OPEN_RC rc = FBDev::TryOpen(); if (rc == NORMAL) return true; else cerr << "Can not open FrameBuffer device on this machine." << endl; /* now ggi */ #ifdef HAVE_GGI_LIB cerr << "trying ggi driver" << endl; if (LIBGGI::TryOpen()) return true; else cerr << "Can not open libggi on this machine." << endl; #endif /* finally vga */ #if defined(linux) #ifdef USING_VGA if (VGADev::TryOpen()) return true; #endif #endif return false; } else if (drv == string("ggi")) { #ifdef HAVE_GGI_LIB if (LIBGGI::TryOpen()) return true; else cerr << "Can not open libggi on this machine." << endl; #endif return false; } else if (drv == string("fb")) { OPEN_RC rc = FBDev::TryOpen(); if (rc == NORMAL) return true; else cerr << "Can not open FrameBuffer device on this machine." << endl; return false; } else if (drv == string("vga")) { #if defined(linux) #ifdef USING_VGA if (VGADev::TryOpen()) return true; #endif #endif return false; } else { throw runtime_error("unknown video driver"); } } bool GraphDev::Open(int xres, int yres, int depth) { return FBDev::TryOpen(xres, yres, depth); } void GraphDev::Close() { if (mpGraphDev) mpGraphDev->ClearScr(); if (mAsc.pBuf) delete[] mAsc.pBuf; if (mDbl.pBuf) delete[] mDbl.pBuf; delete mpGraphDev; } void GraphDev::ClearScr() { FillRect(0, 0, Width() - 1, Height() - 1, 0); } void GraphDev::DrawLine(int x1,int y1,int x2,int y2,int color) { assert( x1 >= 0 && x1 < Width() && y1 >=0 && y1 < Height()); assert( x2 >= 0 && x2 < Width() && y2 >=0 && y2 < Height()); int dx = x2 - x1; int dy = y2 - y1; int ax = abs(dx) << 1; int ay = abs(dy) << 1; int sx = (dx >= 0) ? 1 : -1; int sy = (dy >= 0) ? 1 : -1; int x = x1; int y = y1; if (ax > ay) { int d = ay - (ax >> 1); while (x != x2) { PutPixel(x, y,color); if ((d > 0) || ((d == 0) && (sx == 1))) { y += sy; d -= ax; } x += sx; d += ay; } } else { int d = ax - (ay >> 1); while (y != y2) { PutPixel(x, y,color); if ((d > 0) || ((d == 0) && (sy == 1))) { x += sx; d -= ay; } y += sy; d += ax; } } PutPixel(x, y,color); } void GraphDev::DrawRect(int x1,int y1,int x2,int y2,int color) { assert( x1 >= 0 && x1 < Width() && y1 >=0 && y1 < Height()); assert( x2 >= 0 && x2 < Width() && y2 >=0 && y2 < Height()); DrawLine(x1,y1,x2,y1,color); DrawLine(x1,y1,x1,y2,color); DrawLine(x1,y2,x2,y2,color); DrawLine(x2,y1,x2,y2,color); } void GraphDev::SetAscFont(BaseFont *pAscFont) { mpAscFont = pAscFont; mBlockWidth = pAscFont->Width(); mBlockHeight = pAscFont->Height() + mBlankLineHeight; mAsc.h = pAscFont->Height(); mAsc.w = pAscFont->Width(); mAsc.wBytes = pAscFont->WidthBytes(); mAsc.BufLen = mBlockHeight * mAsc.wBytes; if (mAsc.pBuf) delete[] mAsc.pBuf; mAsc.pBuf = (char *) new char[mAsc.BufLen]; mAsc.pLast = mAsc.pBuf + (mAsc.h - 1)* mAsc.wBytes; mAsc.ExtLen = mBlankLineHeight * mAsc.wBytes; mAsc.isMulti8 = (mAsc.w % 8) ? false : true; } void GraphDev::SetDblFont(BaseFont *pDblFont) { mpDblFont = pDblFont; mDbl.h = pDblFont->Height(); mDbl.w = pDblFont->Width(); mDbl.wBytes = pDblFont->WidthBytes(); mDbl.BufLen = (mDbl.h + mBlankLineHeight) * mDbl.wBytes; if (mDbl.pBuf) delete[] mDbl.pBuf; mDbl.pBuf = (char *) new char[mDbl.BufLen]; mDbl.pLast = mDbl.pBuf + (mDbl.h - 1) * mDbl.wBytes; mDbl.ExtLen = mBlankLineHeight * mDbl.wBytes; mDbl.isMulti8 = (mDbl.w % 8) ? false : true; } //draw a ascii char void GraphDev::OutChar(int x, int y, int fg, int bg, char c) { assert( x >= 0 && x + mBlockWidth <= Width() && y >=0 && y + mBlockHeight <= Height()); char *p = mpAscFont->GetChar(c); memcpy(mAsc.pBuf, p, mAsc.BufLen); if (mBlankLineHeight > 0) { if (c >= 0xb0 && c <= 0xdf) { char *pExt = mAsc.pLast + mAsc.wBytes; int row = mBlankLineHeight; for(; row--; pExt += mAsc.wBytes) { memcpy(pExt, mAsc.pLast, mAsc.wBytes); } } else { memset(mAsc.pLast + mAsc.wBytes, 0, mAsc.ExtLen); } } DrawChar(x,y,fg,bg,&mAsc); // true set extend to blank } // draw a hz at (x,y) and fill bottom with blank // note:this routine can draw half hz at (x,y) // depend on the value of tag void GraphDev::OutChar(int x, int y, int fg, int bg, char c1, char c2) { assert(c1); assert(c2); assert( x >= 0 && x + mBlockWidth * 2 <= Width() && y >=0 && y + mBlockHeight <= Height()); char *p = mpDblFont->GetChar(c1, c2); memcpy(mDbl.pBuf, p, mDbl.BufLen); if (mBlankLineHeight > 0) { memset(mDbl.pLast + mDbl.wBytes, 0, mDbl.ExtLen); } DrawChar(x,y,fg,bg,&mDbl); }