/*:::::*/ FBCALL void fb_GfxWindow(float x1, float y1, float x2, float y2, int screen) { FB_GFXCTX *context = fb_hGetContext(); float temp; if (!__fb_gfx) return; if (x1 || y1 || x2 || y2) { if (x2 < x1) { temp = x1; x1 = x2; x2 = temp; } if (y2 < y1) { temp = y1; y1 = y2; y2 = temp; } context->win_x = x1; context->win_w = x2 - x1; context->win_y = y1; context->win_h = y2 - y1; context->flags |= CTX_WINDOW_ACTIVE; if (screen) context->flags |= CTX_WINDOW_SCREEN; } else context->flags &= ~(CTX_WINDOW_ACTIVE | CTX_WINDOW_SCREEN); }
/*:::::*/ static void fb_hPutPResetC(unsigned char *src, unsigned char *dest, int w, int h, int src_pitch, int dest_pitch, int alpha, BLENDER *blender, void *param) { int x; FB_GFXCTX *context = fb_hGetContext(); w <<= (context->target_bpp >> 1); src_pitch -= w; dest_pitch -= w; for (; h; h--) { if (w & 1) *dest++ = 0xFF ^ *src++; if (w & 2) { *(unsigned short *)dest = 0xFFFF ^ *(unsigned short *)src; dest += 2; src += 2; } for (x = w >> 2; x; x--) { *(unsigned int *)dest = 0xFFFFFFFF ^ *(unsigned int *)src; dest += 4; src += 4; } src += src_pitch; dest += dest_pitch; } }
/*:::::*/ FBCALL void fb_GfxView(int x1, int y1, int x2, int y2, unsigned int fill_color, unsigned int border_color, int flags) { FB_GFXCTX *context = fb_hGetContext(); unsigned int old_bg_color; if (!__fb_gfx) return; fb_hPrepareTarget(context, NULL); fb_hSetPixelTransfer(context, border_color); fb_hFixCoordsOrder(&x1, &y1, &x2, &y2); if ((x1 | y1 | x2 | y2) != 0xFFFF8000) { context->flags |= CTX_VIEWPORT_SET; if (flags & VIEW_SCREEN) context->flags |= CTX_VIEW_SCREEN; else context->flags &= ~CTX_VIEW_SCREEN; if (!(flags & DEFAULT_COLOR_2)) { border_color = fb_hFixColor(context->target_bpp, border_color); /* Temporarily set full screen area clipping to draw view border */ context->view_x = 0; context->view_y = 0; context->view_w = __fb_gfx->w; context->view_h = __fb_gfx->h; fb_hGfxBox(x1 - 1, y1 - 1, x2 + 1, y2 + 1, border_color & __fb_gfx->color_mask, FALSE, 0xFFFF); } context->view_x = MID(0, x1, __fb_gfx->w); context->view_y = MID(0, y1, __fb_gfx->h); context->view_w = MIN(x2 - x1 + 1, __fb_gfx->w - x1); context->view_h = MIN(y2 - y1 + 1, __fb_gfx->h - y1); if (!(flags & DEFAULT_COLOR_1)) { old_bg_color = context->bg_color; context->bg_color = fb_hFixColor(context->target_bpp, fill_color); fb_GfxClear(1); context->bg_color = old_bg_color; } } else { context->flags &= ~CTX_VIEWPORT_SET; context->view_x = context->view_y = 0; context->view_w = __fb_gfx->w; context->view_h = __fb_gfx->h; } }
/*:::::*/ FBCALL float fb_GfxCursor(int func) { FB_GFXCTX *context = fb_hGetContext(); if (!__fb_gfx) return 0.0; switch (func) { case 0: return fb_GfxPMap(context->last_x, 0); case 1: return fb_GfxPMap(context->last_y, 1); case 2: return context->last_x; case 3: return context->last_y; } return 0; }
FBCALL void fb_GfxPset(void *target, float fx, float fy, unsigned int color, int flags, int ispreset) { FB_GFXCTX *context; int x, y; FB_GRAPHICS_LOCK( ); if (!__fb_gfx) { FB_GRAPHICS_UNLOCK( ); return; } context = fb_hGetContext( ); fb_hPrepareTarget(context, target); if (flags & DEFAULT_COLOR_1) { if (ispreset) color = context->bg_color; else color = context->fg_color; } else { color = fb_hFixColor(context->target_bpp, color); } fb_hSetPixelTransfer(context, color); fb_hFixRelative(context, flags, &fx, &fy, NULL, NULL); fb_hTranslateCoord(context, fx, fy, &x, &y); if ((x < context->view_x) || (y < context->view_y) || (x >= context->view_x + context->view_w) || (y >= context->view_y + context->view_h)) { FB_GRAPHICS_UNLOCK( ); return; } DRIVER_LOCK(); context->put_pixel(context, x, y, color); if (__fb_gfx->framebuffer == context->line[0]) __fb_gfx->dirty[y] = TRUE; DRIVER_UNLOCK(); FB_GRAPHICS_UNLOCK( ); }
/*:::::*/ FBCALL float fb_GfxPMap(float coord, int func) { FB_GFXCTX *context = fb_hGetContext(); if (!__fb_gfx) return 0.0; fb_hPrepareTarget(context, NULL); fb_hSetPixelTransfer(context, MASK_A_32); switch (func) { case 0: if (context->flags & CTX_WINDOW_ACTIVE) coord = ((coord - context->win_x) * context->view_w) / context->win_w; return coord; case 1: if (context->flags & CTX_WINDOW_ACTIVE) { coord = ((coord - context->win_y) * context->view_h) / context->win_h; if ((context->flags & CTX_WINDOW_SCREEN) == 0) coord = context->view_h - 1 - coord; } return coord; case 2: if (context->flags & CTX_WINDOW_ACTIVE) coord = ((coord * context->win_w) / context->view_w) + context->win_x; return coord; case 3: if (context->flags & CTX_WINDOW_ACTIVE) { if ((context->flags & CTX_WINDOW_SCREEN) == 0) coord = context->view_h - 1 - coord; coord = ((coord * context->win_h) / context->view_h) + context->win_y; } return coord; } return 0; }
/*:::::*/ void fb_hPutPReset(unsigned char *src, unsigned char *dest, int w, int h, int src_pitch, int dest_pitch, int alpha, BLENDER *blender, void *param) { static PUTTER *all_putters[] = { fb_hPutPResetC, fb_hPutPResetC, NULL, fb_hPutPResetC, #ifdef HOST_X86 fb_hPutPResetMMX, fb_hPutPResetMMX, NULL, fb_hPutPResetMMX, #endif }; PUTTER *putter; FB_GFXCTX *context = fb_hGetContext(); if (!context->putter[PUT_MODE_PRESET]) { #ifdef HOST_X86 if (__fb_gfx->flags & HAS_MMX) context->putter[PUT_MODE_PRESET] = &all_putters[4]; else #endif context->putter[PUT_MODE_PRESET] = &all_putters[0]; } putter = context->putter[PUT_MODE_PRESET][context->target_bpp - 1]; putter(src, dest, w, h, src_pitch, dest_pitch, alpha, blender, param); }
FBCALL void fb_GfxDraw(void *target, FBSTRING *command) { FB_GFXCTX *context; float x, y, dx, dy, ax, ay, x2, y2; int angle = 0, diagonal = FALSE; char *c; intptr_t value1, value2; int draw = TRUE, move = TRUE, length = 0, flags, rel; FB_GRAPHICS_LOCK( ); if ((!__fb_gfx) || (!command) || (!command->data)) { if (command) fb_hStrDelTemp(command); FB_GRAPHICS_UNLOCK( ); return; } context = fb_hGetContext( ); fb_hPrepareTarget(context, target); fb_hSetPixelTransfer(context, MASK_A_32); x = context->last_x; y = context->last_y; DRIVER_LOCK(); flags = context->flags; context->flags |= CTX_VIEW_SCREEN; for (c = command->data; *c;) { switch (toupper(*c)) { case 'B': c++; draw = FALSE; break; case 'N': c++; move = FALSE; break; case 'C': c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; context->fg_color = fb_hFixColor(context->target_bpp, value1); break; case 'S': c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; base_scale = (float)value1 / 4.0; break; case 'A': c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; base_angle = (value1 & 0x3) * 90; break; case 'T': c++; if (toupper(*c) != 'A') goto error; c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; base_angle = mod360( value1 ); break; case 'X': c++; /* Here we could be more severe with checking, but it's unlikely our substring * resides at location FB_NAN (0x80000000) */ if ((value1 = parse_number(&c)) == FB_NAN) goto error; /* Store our current x/y for the recursive fb_GfxDraw() call */ context->last_x = x; context->last_y = y; DRIVER_UNLOCK(); fb_GfxDraw(target, (FBSTRING *)value1); DRIVER_LOCK(); /* And update to x/y produced by the recursive fb_GfxDraw() call */ x = context->last_x; y = context->last_y; break; case 'P': c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; value2 = value1; if (*c == ',') { c++; if ((value2 = parse_number(&c)) == FB_NAN) goto error; } DRIVER_UNLOCK(); fb_GfxPaint(target, x, y, value1 & __fb_gfx->color_mask, value2 & __fb_gfx->color_mask, NULL, PAINT_TYPE_FILL, COORD_TYPE_A); DRIVER_LOCK(); break; case 'M': c++; while ((*c == ' ') || (*c == '\t')) c++; rel = ((*c == '+') || (*c == '-')); if ((value1 = parse_number(&c)) == FB_NAN) goto error; if (*c++ != ',') goto error; if ((value2 = parse_number(&c)) == FB_NAN) goto error; x2 = (float)value1; y2 = (float)value2; if (rel) { ax = dcos(base_angle); ay = -dsin(base_angle); dx = x2; dy = y2; x2 = (((dx * ax) - (dy * ay)) * base_scale) + x; y2 = (((dy * ax) + (dx * ay)) * base_scale) + y; } if (draw) { DRIVER_UNLOCK(); fb_GfxLine(target, (int)x, (int)y, (int)x2, (int)y2, 0, LINE_TYPE_LINE, 0xFFFF, COORD_TYPE_AA | DEFAULT_COLOR_1); DRIVER_LOCK(); } if (move) { x = x2; y = y2; } move = draw = TRUE; break; case 'F': case 'D': angle += 90; case 'G': case 'L': angle += 90; case 'H': case 'U': angle += 90; case 'E': case 'R': diagonal = ((toupper(*c) >= 'E') && (toupper(*c) <= 'H')); c++; if ((value1 = parse_number(&c)) != FB_NAN) length = value1; else length = 1; angle = mod360( angle + base_angle ); dx = (float)length * base_scale * dcos( angle ); dy = (float)length * base_scale * -dsin( angle ); if (diagonal) { x2 = x + (dx + dy); y2 = y + (dy - dx); } else { x2 = x + dx; y2 = y + dy; } if (draw) { fb_GfxDrawLine( context, CINT(x), CINT(y), CINT(x2), CINT(y2), context->fg_color, 0xffff ); } if (move) { x = x2; y = y2; } angle = 0; move = draw = TRUE; break; default: c++; break; } } context->last_x = x; context->last_y = y; error: context->flags = flags; DRIVER_UNLOCK(); /* del if temp */ fb_hStrDelTemp( command ); FB_GRAPHICS_UNLOCK( ); }
FBCALL void fb_GfxEllipse(void *target, float fx, float fy, float radius, unsigned int color, float aspect, float start, float end, int fill, int flags) { FB_GFXCTX *context; int x, y, x1, y1, top, bottom; unsigned int orig_color; float a, b, orig_x, orig_y, increment; FB_GRAPHICS_LOCK( ); if (!__fb_gfx || radius <= 0.0) { FB_GRAPHICS_UNLOCK( ); return; } context = fb_hGetContext(); orig_x = fx; orig_y = fy; fb_hPrepareTarget(context, target); orig_color = color; if (flags & DEFAULT_COLOR_1) color = context->fg_color; else color = fb_hFixColor(context->target_bpp, color); fb_hSetPixelTransfer(context, color); fb_hFixRelative(context, flags, &fx, &fy, NULL, NULL); fb_hTranslateCoord(context, fx, fy, &x, &y); if (context->flags & CTX_WINDOW_ACTIVE) { /* radius gets multiplied by the VIEW/WINDOW width ratio (aspect is unchanged) */ radius *= (context->view_w / context->win_w); } if (aspect == 0.0) aspect = __fb_gfx->aspect; if (aspect > 1.0) { a = (radius / aspect); b = radius; } else { a = radius; b = (radius * aspect); } if ((start != 0.0) || (end != 3.141593f * 2.0)) { if (start < 0) { start = -start; get_arc_point(start, a, b, &x1, &y1); x1 = orig_x + x1; y1 = orig_y - y1; fb_GfxLine(target, orig_x, orig_y, x1, y1, orig_color, LINE_TYPE_LINE, 0xFFFF, COORD_TYPE_AA | (flags & ~COORD_TYPE_MASK)); } if (end < 0) { end = -end; get_arc_point(end, a, b, &x1, &y1); x1 = orig_x + x1; y1 = orig_y - y1; fb_GfxLine(target, orig_x, orig_y, x1, y1, orig_color, LINE_TYPE_LINE, 0xFFFF, COORD_TYPE_AA | (flags & ~COORD_TYPE_MASK)); } while (end < start) end += 2 * PI; while (end - start > 2 * PI) start += 2 * PI; increment = 1 / (sqrt(a) * sqrt(b) * 1.5); DRIVER_LOCK(); top = bottom = y; for (; start < end + (increment / 2); start += increment) { get_arc_point(start, a, b, &x1, &y1); x1 = x + x1; y1 = y - y1; if ((x1 < context->view_x) || (x1 >= context->view_x + context->view_w) || (y1 < context->view_y) || (y1 >= context->view_y + context->view_h)) continue; context->put_pixel(context, x1, y1, color); if (y1 > bottom) bottom = y1; if (y1 < top) top = y1; } } else { DRIVER_LOCK(); draw_ellipse(context, x, y, a, b, color, fill, &top, &bottom); } top = MID(context->view_y, top, context->view_y + context->view_h - 1); bottom = MID(context->view_y, bottom, context->view_y + context->view_h - 1); if( top > bottom ) SWAP( top, bottom ); SET_DIRTY(context, top, bottom - top + 1); DRIVER_UNLOCK(); FB_GRAPHICS_UNLOCK( ); }
static int set_mode ( int mode, int w, int h, int depth, int scanline_size, int num_pages, int refresh_rate, int palette, int font, int flags, float aspect, int text_w, int text_h ) { const GFXDRIVER *driver = NULL; FB_GFXCTX *context; int i, j, try_count; char *c, *driver_name; unsigned char *dest; /* normalize flags */ if ((flags >= 0) && (flags & DRIVER_SHAPED_WINDOW)) flags |= DRIVER_SHAPED_WINDOW | DRIVER_NO_FRAME | DRIVER_NO_SWITCH; release_gfx_mem(); if( (mode == 0) || (w == 0) ) { memset(&__fb_ctx.hooks, 0, sizeof(__fb_ctx.hooks)); if (flags != SCREEN_EXIT) { /* set and clear text screen mode or the width and line_len will be wrong */ fb_Width( 80, 25 ); fb_Cls( 0 ); } /* reset viewport to console dimensions */ fb_ConsoleSetTopBotRows(-1, -1); } else { __fb_ctx.hooks.inkeyproc = fb_GfxInkey; __fb_ctx.hooks.getkeyproc = fb_GfxGetkey; __fb_ctx.hooks.keyhitproc = fb_GfxKeyHit; __fb_ctx.hooks.clsproc = fb_GfxClear; __fb_ctx.hooks.colorproc = fb_GfxColor; __fb_ctx.hooks.locateproc = fb_GfxLocate; __fb_ctx.hooks.widthproc = fb_GfxWidth; __fb_ctx.hooks.getxproc = fb_GfxGetX; __fb_ctx.hooks.getyproc = fb_GfxGetY; __fb_ctx.hooks.getxyproc = fb_GfxGetXY; __fb_ctx.hooks.getsizeproc = fb_GfxGetSize; __fb_ctx.hooks.printbuffproc = fb_GfxPrintBufferEx; __fb_ctx.hooks.printbuffwproc = fb_GfxPrintBufferWstrEx; __fb_ctx.hooks.readstrproc = fb_GfxReadStr; __fb_ctx.hooks.multikeyproc = fb_GfxMultikey; __fb_ctx.hooks.getmouseproc = fb_GfxGetMouse; __fb_ctx.hooks.setmouseproc = fb_GfxSetMouse; __fb_ctx.hooks.inproc = fb_GfxIn; __fb_ctx.hooks.outproc = fb_GfxOut; __fb_ctx.hooks.viewupdateproc = fb_GfxViewUpdate; __fb_ctx.hooks.lineinputproc = fb_GfxLineInput; __fb_ctx.hooks.lineinputwproc = fb_GfxLineInputWstr; __fb_ctx.hooks.readxyproc = fb_GfxReadXY; __fb_ctx.hooks.sleepproc = fb_GfxSleep; __fb_ctx.hooks.isredirproc = fb_GfxIsRedir; __fb_ctx.hooks.pagecopyproc = fb_GfxPageCopy; __fb_ctx.hooks.pagesetproc = fb_GfxPageSet; __fb_gfx = (FBGFX *)calloc(1, sizeof(FBGFX)); } if (__fb_gfx) { __fb_gfx->id = screen_id++; __fb_gfx->mode_num = mode; __fb_gfx->w = w; __fb_gfx->h = h; __fb_gfx->depth = depth; if ((flags >= 0) && (flags & DRIVER_OPENGL)) __fb_gfx->depth = MAX(16, __fb_gfx->depth); __fb_gfx->default_palette = (palette >= 0) ? &__fb_palette[palette] : NULL; __fb_gfx->scanline_size = scanline_size; __fb_gfx->font = (font >= 0) ? &__fb_font[font] : NULL; if( aspect != 0.0f ) __fb_gfx->aspect = aspect; else __fb_gfx->aspect = (4.0 / 3.0) * ((float)__fb_gfx->h / (float)__fb_gfx->w); switch (__fb_gfx->depth) { case 15: case 16: __fb_gfx->color_mask = 0xFFFF; __fb_gfx->depth = 16; break; case 24: case 32: __fb_gfx->color_mask = 0xFFFFFFFF; __fb_gfx->depth = 32; break; default: __fb_gfx->color_mask = (1 << __fb_gfx->depth) - 1; } __fb_gfx->bpp = BYTES_PER_PIXEL(__fb_gfx->depth); __fb_gfx->pitch = __fb_gfx->w * __fb_gfx->bpp; __fb_gfx->page = (unsigned char **)malloc(sizeof(unsigned char *) * num_pages); for (i = 0; i < num_pages; i++) { /* 0xF for the para alignment, p_size is sizeof(void *) rounded up to % 16 for the storage for the original pointer */ int p_size = (sizeof(void *) + 0xF) & 0xF; void *tmp = malloc((__fb_gfx->pitch * __fb_gfx->h) + p_size + 0xF); __fb_gfx->page[i] = (unsigned char *)(((intptr_t)tmp + p_size + 0xF) & ~0xF); ((void **)(__fb_gfx->page[i]))[-1] = tmp; } __fb_gfx->num_pages = num_pages; __fb_gfx->framebuffer = __fb_gfx->page[0]; /* dirty lines array may be bigger than needed; this is to please the gfx driver which is not aware of the scanline size */ __fb_gfx->dirty = (char *)calloc(1, __fb_gfx->h * __fb_gfx->scanline_size); __fb_gfx->device_palette = (unsigned int *)calloc(1, sizeof(int) * 256); __fb_gfx->palette = (unsigned int *)calloc(1, sizeof(int) * 256); __fb_gfx->color_association = (unsigned char *)malloc(16); __fb_gfx->key = (char *)calloc(1, 128); __fb_gfx->event_queue = (EVENT *)malloc(sizeof(EVENT) * MAX_EVENTS); __fb_gfx->event_mutex = fb_MutexCreate(); __fb_color_conv_16to32 = (unsigned int *)malloc(sizeof(int) * 512); if (flags != DRIVER_NULL) { if (flags & DRIVER_ALPHA_PRIMITIVES) __fb_gfx->flags |= ALPHA_PRIMITIVES; if (flags & DRIVER_OPENGL) __fb_gfx->flags |= OPENGL_SUPPORT; if (flags & DRIVER_HIGH_PRIORITY) __fb_gfx->flags |= HIGH_PRIORITY; } fb_hSetupFuncs(__fb_gfx->bpp); fb_hSetupData(); if (!__fb_window_title) { __fb_window_title = fb_hGetExeName( window_title_buff, WINDOW_TITLE_SIZE - 1 ); if ((c = strrchr(__fb_window_title, '.'))) *c = '\0'; } driver_name = __fb_gfx_driver_name; if (!driver_name) driver_name = getenv("FBGFX"); if ((flags == DRIVER_NULL) || ((driver_name) && (!strcasecmp(driver_name, "null")))) driver = &__fb_gfxDriverNull; else { for (try_count = (driver_name ? 4 : 2); try_count; try_count--) { for (i = 0; __fb_gfx_drivers_list[i >> 1]; i++) { driver = __fb_gfx_drivers_list[i >> 1]; if ((driver_name) && !(try_count & 0x1) && (strcasecmp(driver_name, driver->name))) { driver = NULL; continue; } if (!driver->init(__fb_window_title, __fb_gfx->w, __fb_gfx->h * __fb_gfx->scanline_size, __fb_gfx->depth, (i & 0x1) ? 0 : refresh_rate, flags)) break; driver->exit(); driver = NULL; } if (driver) break; if (driver_name) { if (try_count == 3) flags ^= DRIVER_FULLSCREEN; } else flags ^= DRIVER_FULLSCREEN; } } if (!driver) { exit_proc(); return fb_ErrorSetNum(FB_RTERROR_ILLEGALFUNCTIONCALL); } __fb_gfx->driver = driver; fb_GfxPalette(-1, 0, 0, 0); __fb_gfx->text_w = text_w; __fb_gfx->text_h = text_h; context = fb_hGetContext(); fb_hResetCharCells(context, TRUE); for (i = 0; i < num_pages; i++) { dest = __fb_gfx->page[i]; for (j = 0; j < __fb_gfx->h; j++) { context->pixel_set(dest, context->bg_color, context->view_w); dest += __fb_gfx->pitch; } } if( !exit_proc_set ) { exit_proc_set = TRUE; atexit(exit_proc); } } if( flags!=SCREEN_EXIT ) { /* Reset VIEW PRINT * * Normally, resetting VIEW PRINT should also result in setting the cursor * position to Y,X = 1,1 but this doesn't seem to be suitable (at least * on Win32 platforms). I don't believe that this is a problem because * on DOS, the cursor position will automatically be reset when the screen * mode changes and not changing the console cursor position on Win32 * and Linux seem to be more "natural". */ fb_ConsoleViewEx( 0, 0, __fb_gfx!=NULL ); } return fb_ErrorSetNum( FB_RTERROR_OK ); }
/*:::::*/ FBCALL void fb_GfxPaint(void *target, float fx, float fy, unsigned int color, unsigned int border_color, FBSTRING *pattern, int mode, int flags) { FB_GFXCTX *context = fb_hGetContext(); int size, x, y; unsigned char data[256], *dest, *src; SPAN **span, *s, *tail, *head; if (!__fb_gfx) return; fb_hPrepareTarget(context, target); if (flags & DEFAULT_COLOR_1) color = context->fg_color; else color = fb_hFixColor(context->target_bpp, color); if (flags & DEFAULT_COLOR_2) border_color = color; else border_color = fb_hFixColor(context->target_bpp, border_color); fb_hSetPixelTransfer(context,color); fb_hFixRelative(context, flags, &fx, &fy, NULL, NULL); fb_hTranslateCoord(context, fx, fy, &x, &y); fb_hMemSet(data, 0, sizeof(data)); if ((mode == PAINT_TYPE_PATTERN) && (pattern)) { fb_hMemCpy(data, pattern->data, MIN(256, FB_STRSIZE(pattern))); } if (pattern) { /* del if temp */ fb_hStrDelTemp( pattern ); } if ((x < context->view_x) || (x >= context->view_x + context->view_w) || (y < context->view_y) || (y >= context->view_y + context->view_h)) return; if (context->get_pixel(context, x, y) == border_color) return; size = sizeof(SPAN *) * (context->view_y + context->view_h); span = (SPAN **)malloc(size); fb_hMemSet(span, 0, size); tail = head = add_span(context, span, &x, y, border_color); /* Find all spans to paint */ while (tail) { if (tail->y - 1 >= context->view_y) { for (x = tail->x1; x <= tail->x2; x++) { if (context->get_pixel(context, x, tail->y - 1) != border_color) { s = add_span(context, span, &x, tail->y - 1, border_color); if (s) { head->next = s; head = s; } } } } if (tail->y + 1 < context->view_y + context->view_h) { for (x = tail->x1; x <= tail->x2; x++) { if (context->get_pixel(context, x, tail->y + 1) != border_color) { s = add_span(context, span, &x, tail->y + 1, border_color); if (s) { head->next = s; head = s; } } } } tail = tail->next; } DRIVER_LOCK(); /* Fill spans */ for (y = context->view_y; y < context->view_y + context->view_h; y++) { for (s = tail = span[y]; s; s = s->row_next, free(tail), tail = s) { dest = context->line[s->y] + (s->x1 * context->target_bpp); if (mode == PAINT_TYPE_FILL) context->pixel_set(dest, color, s->x2 - s->x1 + 1); else { src = data + (((s->y & 0x7) << 3) * context->target_bpp); if (s->x1 & 0x7) { if ((s->x1 & ~0x7) == (s->x2 & ~0x7)) size = s->x2 - s->x1 + 1; else size = 8 - (s->x1 & 0x7); fb_hPixelCpy(dest, src + ((s->x1 & 0x7) * context->target_bpp), size); dest += size * context->target_bpp; } s->x2++; for (x = (s->x1 + 7) >> 3; x < (s->x2 & ~0x7) >> 3; x++) { fb_hPixelCpy(dest, src, 8); dest += 8 * context->target_bpp; } if ((s->x2 & 0x7) && ((s->x1 & ~0x7) != (s->x2 & ~0x7))) fb_hPixelCpy(dest, src, s->x2 & 0x7); } if (__fb_gfx->framebuffer == context->line[0]) __fb_gfx->dirty[context->view_y + y] = TRUE; } } free(span); DRIVER_UNLOCK(); }
void fb_GfxPrintBufferEx( const void *buffer, size_t len, int mask ) { FB_GFXCTX *context; const char *pachText = (const char *) buffer; int win_left, win_top, win_cols, win_rows; int view_top, view_bottom; fb_PrintInfo info; fb_ConHooks hooks; FB_GRAPHICS_LOCK( ); /* Do we want to correct the console cursor position? */ if( (mask & FB_PRINT_FORCE_ADJUST)==0 ) { /* No, we can check for the length to avoid unnecessary stuff ... */ if( len==0 ) { FB_GRAPHICS_UNLOCK( ); return; } } context = fb_hGetContext( ); fb_hPrepareTarget(context, NULL); fb_hSetPixelTransfer(context, MASK_A_32); DRIVER_LOCK(); fb_GetSize( &win_cols, &win_rows ); fb_ConsoleGetView( &view_top, &view_bottom ); win_left = win_top = 0; hooks.Opaque = &info; hooks.Scroll = fb_hHookConScroll; hooks.Write = fb_hHookConWrite; hooks.Border.Left = win_left; hooks.Border.Top = win_top + view_top - 1; hooks.Border.Right = win_left + win_cols - 1; hooks.Border.Bottom = win_top + view_bottom - 1; info.context = context; info.dirty_start = info.dirty_end = 0; { hooks.Coord.X = __fb_gfx->cursor_x; hooks.Coord.Y = __fb_gfx->cursor_y; if( __fb_gfx->flags & PRINT_SCROLL_WAS_OFF ) { __fb_gfx->flags &= ~PRINT_SCROLL_WAS_OFF; ++hooks.Coord.Y; hooks.Coord.X = hooks.Border.Left; fb_hConCheckScroll( &hooks ); } fb_ConPrintTTY( &hooks, pachText, len, TRUE ); if( hooks.Coord.X != hooks.Border.Left || hooks.Coord.Y != (hooks.Border.Bottom+1) ) { fb_hConCheckScroll( &hooks ); } else { __fb_gfx->flags |= PRINT_SCROLL_WAS_OFF; hooks.Coord.X = hooks.Border.Right; hooks.Coord.Y = hooks.Border.Bottom; } fb_GfxLocateRaw( hooks.Coord.Y, hooks.Coord.X, -1 ); } SET_DIRTY(context, info.dirty_start, info.dirty_end - info.dirty_start); DRIVER_UNLOCK(); FB_GRAPHICS_UNLOCK( ); }
FBCALL void fb_GfxDraw(void *target, FBSTRING *command) { FB_GFXCTX *context; float x, y, dx, dy, ax, ay, x2, y2, scale = 1.0, angle = 0.0; char *c; intptr_t value1, value2; int draw = TRUE, move = TRUE, length = 0, flags, rel, ix, iy; FB_GRAPHICS_LOCK( ); if ((!__fb_gfx) || (!command) || (!command->data)) { if (command) fb_hStrDelTemp(command); FB_GRAPHICS_UNLOCK( ); return; } context = fb_hGetContext( ); fb_hPrepareTarget(context, target); fb_hSetPixelTransfer(context, MASK_A_32); x = context->last_x; y = context->last_y; DRIVER_LOCK(); flags = context->flags; context->flags |= CTX_VIEW_SCREEN; for (c = command->data; *c;) { switch (toupper(*c)) { case 'B': c++; draw = FALSE; break; case 'N': c++; move = FALSE; break; case 'C': c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; context->fg_color = fb_hFixColor(context->target_bpp, value1); break; case 'S': c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; base_scale = (float)value1 / 4.0; break; case 'A': c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; base_angle = (float)(value1 & 0x3) * PI * 0.5; break; case 'T': c++; if (toupper(*c) != 'A') goto error; c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; base_angle = (float)value1 * PI / 180.0; break; case 'X': c++; /* Here we could be more severe with checking, but it's unlikely our substring * resides at location FB_NAN (0x80000000) */ if ((value1 = parse_number(&c)) == FB_NAN) goto error; /* Store our current x/y for the recursive fb_GfxDraw() call */ context->last_x = x; context->last_y = y; DRIVER_UNLOCK(); fb_GfxDraw(target, (FBSTRING *)value1); DRIVER_LOCK(); /* And update to x/y produced by the recursive fb_GfxDraw() call */ x = context->last_x; y = context->last_y; break; case 'P': c++; if ((value1 = parse_number(&c)) == FB_NAN) goto error; value2 = value1; if (*c == ',') { c++; if ((value2 = parse_number(&c)) == FB_NAN) goto error; } DRIVER_UNLOCK(); fb_GfxPaint(target, x, y, value1 & __fb_gfx->color_mask, value2 & __fb_gfx->color_mask, NULL, PAINT_TYPE_FILL, COORD_TYPE_A); DRIVER_LOCK(); break; case 'M': c++; rel = FALSE; while ((*c == ' ') || (*c == '\t')) c++; if ((*c == '+') || (*c == '-')) { rel = TRUE; } if ((value1 = parse_number(&c)) == FB_NAN) goto error; if (*c++ != ',') goto error; if ((value2 = parse_number(&c)) == FB_NAN) goto error; x2 = (float)value1; y2 = (float)value2; if (rel) { ax = cos(base_angle); ay = -sin(base_angle); dx = x2; dy = y2; x2 = (((dx * ax) - (dy * ay)) * base_scale) + x; y2 = (((dy * ax) + (dx * ay)) * base_scale) + y; } else { x2 += 0.5; y2 += 0.5; } if (draw) { DRIVER_UNLOCK(); fb_GfxLine(target, (int)x, (int)y, (int)x2, (int)y2, 0, LINE_TYPE_LINE, 0xFFFF, COORD_TYPE_AA | DEFAULT_COLOR_1); DRIVER_LOCK(); } if (move) { x = x2; y = y2; } move = draw = TRUE; break; case 'F': angle += PI * 0.25; case 'D': angle += PI * 0.25; case 'G': angle += PI * 0.25; case 'L': angle += PI * 0.25; case 'H': angle += PI * 0.25; case 'U': angle += PI * 0.25; case 'E': angle += PI * 0.25; case 'R': if ((toupper(*c) >= 'E') && (toupper(*c) <= 'H')) scale = SQRT_2; c++; if ((value1 = parse_number(&c)) != FB_NAN) length = value1; else length = 1; break; default: c++; break; } if (length) { length = (int)(((float)length * (base_scale * scale)) + 0.5); if (length < 0) { angle += PI; length = -length; } angle += base_angle; dx = x; dy = y; for (; length >= 0; length--) { if (draw) { ix = dx; iy = dy; if ((ix >= context->view_x) && (ix < context->view_x + context->view_w) && (iy >= context->view_y) && (iy < context->view_y + context->view_h)) { context->put_pixel(context, ix, iy, context->fg_color); if (__fb_gfx->framebuffer == context->line[0]) __fb_gfx->dirty[iy] = TRUE; } } if (length) { dx += cos(angle); dy -= sin(angle); } } if (move) { x = dx; y = dy; } angle = 0.0; scale = 1.0; length = 0; move = draw = TRUE; } } context->last_x = x; context->last_y = y; error: context->flags = flags; DRIVER_UNLOCK(); /* del if temp */ fb_hStrDelTemp( command ); FB_GRAPHICS_UNLOCK( ); }
FBCALL void fb_GfxControl_i( int what, int *param1, int *param2, int *param3, int *param4 ) { FB_GFXCTX *context = fb_hGetContext(); int res = 0; int res1 = 0, res2 = 0, res3 = 0, res4 = 0; int temp1, temp2, temp3, temp4; if (!param1) param1 = &temp1; if (!param2) param2 = &temp2; if (!param3) param3 = &temp3; if (!param4) param4 = &temp4; switch ( what ) { case GET_WINDOW_POS: if ((__fb_gfx) && (__fb_gfx->driver->set_window_pos)) res = __fb_gfx->driver->set_window_pos(0x80000000, 0x80000000); res1 = (int)((short)(res & 0xFFFF)); res2 = res >> 16; break; case GET_WINDOW_HANDLE: if (__fb_gfx) res1 = fb_hGetWindowHandle(); break; case GET_DESKTOP_SIZE: fb_hScreenInfo(&res1, &res2, &temp3, &temp4); break; case GET_SCREEN_SIZE: if (__fb_gfx) { res1 = __fb_gfx->w; res2 = __fb_gfx->h; } break; case GET_SCREEN_DEPTH: if (__fb_gfx) res1 = __fb_gfx->depth; break; case GET_SCREEN_BPP: if (__fb_gfx) res1 = __fb_gfx->bpp; break; case GET_SCREEN_PITCH: if (__fb_gfx) res1 = __fb_gfx->pitch; break; case GET_SCREEN_REFRESH: if (__fb_gfx) res1 = __fb_gfx->refresh_rate; break; case GET_TRANSPARENT_COLOR: if ((__fb_gfx) && (__fb_gfx->bpp > 1)) res1 = MASK_COLOR_32; break; case GET_VIEWPORT: if (__fb_gfx) { res1 = context->view_x; res2 = context->view_y; res3 = context->view_x + context->view_w - 1; res4 = context->view_y + context->view_h - 1; } break; case GET_PEN_POS: if (__fb_gfx) { res1 = context->last_x; res2 = context->last_y; } break; case GET_COLOR: if (__fb_gfx) { res1 = context->fg_color; res2 = context->bg_color; } break; case GET_ALPHA_PRIMITIVES: if (__fb_gfx) res1 = (__fb_gfx->flags & ALPHA_PRIMITIVES) ? FB_TRUE : FB_FALSE; break; case GET_HIGH_PRIORITY: if (__fb_gfx) res1 = (__fb_gfx->flags & HIGH_PRIORITY) ? FB_TRUE : FB_FALSE; break; case SET_WINDOW_POS: if ((__fb_gfx) && (__fb_gfx->driver->set_window_pos)) __fb_gfx->driver->set_window_pos(*param1, *param2); break; case SET_PEN_POS: if (__fb_gfx) { if (*param1 != 0x80000000) context->last_x = *param1; if (*param2 != 0x80000000) context->last_y = *param2; } break; case SET_ALPHA_PRIMITIVES: if ((__fb_gfx) && (*param1 != 0x80000000)) { if (*param1) __fb_gfx->flags |= ALPHA_PRIMITIVES; else __fb_gfx->flags &= ~ALPHA_PRIMITIVES; } break; #ifndef DISABLE_OPENGL case SET_GL_COLOR_BITS: __fb_gl_params.color_bits = *param1; break; case SET_GL_COLOR_RED_BITS: __fb_gl_params.color_red_bits = *param1; break; case SET_GL_COLOR_GREEN_BITS: __fb_gl_params.color_green_bits = *param1; break; case SET_GL_COLOR_BLUE_BITS: __fb_gl_params.color_blue_bits = *param1; break; case SET_GL_COLOR_ALPHA_BITS: __fb_gl_params.color_alpha_bits = *param1; break; case SET_GL_DEPTH_BITS: __fb_gl_params.depth_bits = *param1; break; case SET_GL_STENCIL_BITS: __fb_gl_params.stencil_bits = *param1; break; case SET_GL_ACCUM_BITS: __fb_gl_params.accum_bits = *param1; break; case SET_GL_ACCUM_RED_BITS: __fb_gl_params.accum_red_bits = *param1; break; case SET_GL_ACCUM_GREEN_BITS: __fb_gl_params.accum_green_bits = *param1; break; case SET_GL_ACCUM_BLUE_BITS: __fb_gl_params.accum_blue_bits = *param1; break; case SET_GL_ACCUM_ALPHA_BITS: __fb_gl_params.accum_alpha_bits = *param1; break; case SET_GL_NUM_SAMPLES: __fb_gl_params.num_samples = *param1; break; #endif case POLL_EVENTS: if ((__fb_gfx) && (__fb_gfx->driver->poll_events)) __fb_gfx->driver->poll_events(); break; } if (what < SET_FIRST_SETTER) { *param1 = res1; *param2 = res2; *param3 = res3; *param4 = res4; } }
/*:::::*/ static int gfx_get(void *target, float fx1, float fy1, float fx2, float fy2, unsigned char *dest, int coord_type, FBARRAY *array, int usenewheader ) { FB_GFXCTX *context = fb_hGetContext(); PUT_HEADER *header; int x1, y1, x2, y2, w, h, pitch; if (!__fb_gfx) return fb_ErrorSetNum(FB_RTERROR_ILLEGALFUNCTIONCALL); fb_hPrepareTarget(context, target); fb_hSetPixelTransfer(context, MASK_A_32); fb_hFixRelative(context, coord_type, &fx1, &fy1, &fx2, &fy2); fb_hTranslateCoord(context, fx1, fy1, &x1, &y1); fb_hTranslateCoord(context, fx2, fy2, &x2, &y2); fb_hFixCoordsOrder(&x1, &y1, &x2, &y2); if ((x1 < context->view_x) || (y1 < context->view_y) || (x2 >= context->view_x + context->view_w) || (y2 >= context->view_y + context->view_h)) return fb_ErrorSetNum(FB_RTERROR_ILLEGALFUNCTIONCALL); w = x2 - x1 + 1; h = y2 - y1 + 1; header = (PUT_HEADER *)dest; if (!usenewheader) { /* use old-style header for compatibility */ header->old.bpp = context->target_bpp; header->old.width = w; header->old.height = h; pitch = w * context->target_bpp; dest += 4; } else { /* use new-style header */ header->type = PUT_HEADER_NEW; header->width = w; header->height = h; header->bpp = context->target_bpp; pitch = header->pitch = ((w * context->target_bpp) + 0xF) & ~0xF; dest += sizeof(PUT_HEADER); } if( array != NULL ) { if ((array->size > 0) && ((intptr_t)dest + (pitch * h) > (intptr_t)array->data + array->size)) return fb_ErrorSetNum(FB_RTERROR_ILLEGALFUNCTIONCALL); } DRIVER_LOCK(); for (; y1 <= y2; y1++) { fb_hPixelCpy(dest, context->line[y1] + (x1 * context->target_bpp), w); dest += pitch; } DRIVER_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_OK ); }