You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

456 lines
10 KiB

#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "parser.h"
#include "globals.h"
#include "framebuffer.h"
const char circle[]={
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,1,1,1,1,1,1,1,1,1,1,1,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9
};
Cfb* Cfb::getInstance()
{
static Cfb* instance = NULL;
if(!instance)
instance = new Cfb();
return instance;
}
Cfb::Cfb()
{
cpars = CParser::getInstance();
memset(&lfb, 0, sizeof(lfb));
memset(&lbb, 0, sizeof(lbb));
}
Cfb::~Cfb()
{
Cleanup();
}
int Cfb::init()
{
FT_Error error;
fb = sx = ex = sy = ey = -1;
// open Framebuffer
fb=open ( "/dev/fb/0", O_RDWR );
// init framebuffer
if(ioctl(fb, FBIOGET_FSCREENINFO, &fix_screeninfo) == -1)
{
printf("[%s] <FBIOGET_FSCREENINFO failed>\n",BASENAME);
return(2);
}
if(ioctl(fb, FBIOGET_VSCREENINFO, &var_screeninfo) == -1)
{
printf("[%s] <FBIOGET_VSCREENINFO failed>\n",BASENAME);
return(2);
}
if(!(lfb = (unsigned char*)mmap(0, fix_screeninfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0)))
{
printf("[%s] <mapping of Framebuffer failed>\n",BASENAME);
return(2);
}
// init fontlibrary
if((error = FT_Init_FreeType(&library)))
{
printf("[%s] <FT_Init_FreeType failed with Errorcode 0x%.2X>",BASENAME, error);
munmap(lfb, fix_screeninfo.smem_len);
return(2);
}
if((error = FTC_Manager_New(library, 1, 2, 0, &MyFaceRequester, this, &manager)))
{
printf("[%s] <FTC_Manager_New failed with Errorcode 0x%.2X>\n",BASENAME, error);
FT_Done_FreeType(library);
munmap(lfb, fix_screeninfo.smem_len);
return(2);
}
if((error = FTC_SBitCache_New(manager, &cache)))
{
printf("[%s] <FTC_SBitCache_New failed with Errorcode 0x%.2X>\n",BASENAME, error);
FTC_Manager_Done(manager);
FT_Done_FreeType(library);
munmap(lfb, fix_screeninfo.smem_len);
return(2);
}
if((error = FTC_Manager_Lookup_Face(manager, (char *)FONT, &face)))
{
printf("[%s] <FTC_Manager_Lookup_Face failed with Errorcode 0x%.2X>\n",BASENAME, error);
FTC_Manager_Done(manager);
FT_Done_FreeType(library);
munmap(lfb, fix_screeninfo.smem_len);
return(2);
}
use_kerning = FT_HAS_KERNING(face);
desc.face_id = (char *)FONT;
desc.flags = FT_LOAD_MONOCHROME;
// init backbuffer
if(!(lbb = (unsigned char*)malloc(fix_screeninfo.line_length*var_screeninfo.yres)))
{
printf("[%s] <allocating of Backbuffer failed>\n",BASENAME);
FTC_Manager_Done(manager);
FT_Done_FreeType(library);
munmap(lfb, fix_screeninfo.smem_len);
return(2);
}
// volle Bildschirmauflösung reservieren (Parameter: buffer, color, size in bytes)
memset(lbb, 0, fix_screeninfo.line_length*var_screeninfo.yres);
printf("[%s] - init: FB %dx%dx%d stride %d\n",BASENAME, var_screeninfo.xres, var_screeninfo.yres, var_screeninfo.bits_per_pixel, fix_screeninfo.line_length);;
cpars->read_neutrino_osd_conf(&ex,&sx,&ey,&sy,NEUTRINOCONF);
if((ex == -1) || (sx == -1) || (ey == -1) || (sy == -1))
{
sx = 80;
ex = var_screeninfo.xres - 80;
sy = 80;
ey = var_screeninfo.yres - 80;
}
int mwidth = ex-sx;
int mheight = ey-sy;
//mwidth = 620;
startx = sx + (((ex-sx) - mwidth)/2);
starty = sy + (((ey-sy) - mheight)/2);
//vyres = var_screeninfo.yres;
return(0);
}
/******************************************************************************
* MyFaceRequester
******************************************************************************/
FT_Error Cfb::MyFaceRequester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *aface)
{
FT_Error result;
result = FT_New_Face(library, (char *)face_id, 0, aface);
if(!result)
{
printf("[%s] - <Font \"%s\" loaded>\n",BASENAME, (char*)face_id);
}
else
{
printf("[%s] <Font \"%s\" failed>\n",BASENAME, (char*)face_id);
}
return result;
}
/******************************************************************************
* RenderChar
******************************************************************************/
int Cfb::RenderChar(FT_ULong currentchar, int sx, int sy, int ex, int color)
{
int row, pitch, bit, x = 0, y = 0;
FT_Error error;
FT_UInt glyphindex;
FT_Vector kerning;
FTC_Node anode;
//load char
if(!(glyphindex = FT_Get_Char_Index(face, currentchar)))
{
printf("[%s] <FT_Get_Char_Index for Char \"%#.2X\" failed: \"undefined character code\">\n",BASENAME, (int)currentchar);
return 0;
}
if((error = FTC_SBitCache_Lookup(cache, &desc, glyphindex, &sbit, &anode)))
{
printf("[%s] <FTC_SBitCache_Lookup for Char \"%#.2X\" failed with Errorcode 0x%.2X>\n",BASENAME, (int)currentchar, error);
return 0;
}
if(use_kerning)
{
FT_Get_Kerning(face, prev_glyphindex, glyphindex, ft_kerning_default, &kerning);
prev_glyphindex = glyphindex;
kerning.x >>= 6;
}
else
{
kerning.x = 0;
}
// render char
if(color != -1) /* don't render char, return charwidth only */
{
if(sx + sbit->xadvance >= ex)
{
return -1; /* limit to maxwidth */
}
for(row = 0; row < sbit->height; row++)
{
for(pitch = 0; pitch < sbit->pitch; pitch++)
{
for(bit = 7; bit >= 0; bit--)
{
if(pitch*8 + 7-bit >= sbit->width)
{
break; /* render needed bits only */
}
if((sbit->buffer[row * sbit->pitch + pitch]) & 1<<bit)
{
memcpy ( lbb + startx*4 + sx*4 + ( sbit->left + kerning.x + x ) *4 + fix_screeninfo.line_length* ( starty + sy - sbit->top + y ),cpars->bgra[color],4 );
}
x++;
}
}
x = 0;
y++;
}
}
// return charwidth
return sbit->xadvance + kerning.x;
}
/******************************************************************************
* GetStringLen
******************************************************************************/
int Cfb::GetStringLen(const char *string)
{
int stringlen = 0;
// reset kerning
prev_glyphindex = 0;
// calc len
while(*string != '\0')
{
stringlen += RenderChar(*string, -1, -1, -1, -1);
string++;
}
return stringlen;
}
/******************************************************************************
* RenderString
******************************************************************************/
void Cfb::RenderString(const char *string, int sx, int sy, int maxwidth, int layout, int size, int color)
{
int stringlen, ex, charwidth;
// set size
if(size == SMALL)
{
desc.width = desc.height = 26;
}
else if(size == NORMAL)
{
desc.width = desc.height = 32;
}
else
{
desc.width = desc.height = 40;
}
// set alignment
if(layout != LEFT)
{
stringlen = GetStringLen(string);
switch(layout)
{
case CENTER:
if(stringlen < maxwidth)
{
sx += (maxwidth - stringlen)/2;
}
break;
case RIGHT:
if(stringlen < maxwidth)
{
sx += maxwidth - stringlen;
}
}
}
// reset kerning
prev_glyphindex = 0;
// render string
ex = sx + maxwidth;
while(*string != '\0')
{
if((charwidth = RenderChar(*string, sx, sy, ex, color)) == -1)
{
return; /* string > maxwidth */
}
sx += charwidth;
string++;
}
}
/******************************************************************************
* RenderBox
******************************************************************************/
void Cfb::RenderBox(int sx, int sy, int ex, int ey, int mode, int color)
{
int loop;
if(mode == FILL)
{
for(; sy <= ey; sy++)
{
HorLine(sx, sy, ex-sx+1, color);
}
}
else
{
// hor lines
for(loop = sx; loop <= ex; loop++)
{
SetPixel(loop, sy , color);
SetPixel(loop, sy+1, color);
SetPixel(loop, ey-1, color);
SetPixel(loop, ey , color);
}
// ver lines
for(loop = sy; loop <= ey; loop++)
{
SetPixel(sx , loop, color);
SetPixel(sx+1, loop, color);
SetPixel(ex-1, loop, color);
SetPixel(ex , loop, color);
}
}
}
/******************************************************************************
* RenderCircle
******************************************************************************/
void Cfb::RenderCircle(int sx, int sy, int color)
{
int x, y;
for (y=0; y<15; y++)
for (x=0; x<15; x++)
if (circle[x+y*15])
{
if (circle[x+y*15] == 1)
SetPixel(sx + x, sy + y, color);
else
SetPixel(sx + x, sy + y, (int)circle[x+y*15]);
}
}
/******************************************************************************
* HorLine / SetPixel / PaintIcon
******************************************************************************/
//#define SetPixel(x, y, c) memcpy(lbb + ((startx + (x))<<2) + fix_screeninfo.line_length*(starty + (y)), bgra[c], 4)
void Cfb::HorLine(int x, int y, int l, int color)
{
for (l+=x; x<l; x++)
SetPixel(x, y, color);
}
void Cfb::SetPixel(int x, int y, int c)
{
memcpy(lbb + ((startx + (x))<<2) + fix_screeninfo.line_length*(starty + (y)), cpars->bgra[c], 4);
}
void Cfb::PaintIcon(unsigned char *icon, int sx, int sy)
{
struct rawHeader header;
uint16_t width, height;
int x, y;
memcpy(&header, icon, sizeof(struct rawHeader));
width = (header.width_hi << 8) | header.width_lo;
height = (header.height_hi << 8) | header.height_lo;
icon+=sizeof(struct rawHeader);
for (y=0; y<height; y++)
{
for (x=0; x<width; x+=2)
{
unsigned char pix;
pix = (*icon & 0xf0) >> 4;
if (pix != header.transp)
SetPixel(sx+x, sy+y, pix+1);
pix = (*icon++ & 0x0f);
if (pix != header.transp)
SetPixel(sx+x+1, sy+y, pix+1);
}
}
}
void Cfb::FBPaint(void)
{
memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres);
}
void Cfb::FBClear(void)
{
RenderBox(0, 0, ex-sx, ey-sy, FILL, 0);
}
/******************************************************************************
* Cleanup
******************************************************************************/
void Cfb::Cleanup (void)
{
FTC_Manager_Done(manager);
FT_Done_FreeType(library);
free(lbb);
munmap(lfb, fix_screeninfo.smem_len);
close(fb);
}