home *** CD-ROM | disk | FTP | other *** search
- /*************************************
- * *
- * Render v2.0 *
- * by Torsten Jürgeleit in 05/91 *
- * *
- * Routines *
- * *
- *************************************/
-
- /* Includes */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #include <functions.h>
- #include "render.h"
-
- /* Defines */
-
- #define RED_SCALE 3 /* amount of RGB values to take in account the different visual impact of those colors */
- #define GREEN_SCALE 6
- #define BLUE_SCALE 2
-
- /* Statics */
-
- STATIC USHORT image_data_arrow_left[] = { /* bitmap data for left arrow image */
- 0x0780, 0x3e00, 0xf800, 0x3e00, 0x0780, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000
- };
- STATIC USHORT image_data_arrow_right[] = { /* bitmap data for right arrow image */
- 0xf000, 0x3e00, 0x0f80, 0x3e00, 0xf000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000
- };
- STATIC USHORT image_data_arrow_up[] = { /* bitmap data for up arrow image */
- 0x0800, 0x1c00, 0x3e00, 0x7700, 0xc180, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000
- };
- STATIC USHORT image_data_arrow_down[] = { /* bitmap data for down arrow image */
- 0xc180, 0x7700, 0x3e00, 0x1c00, 0x0800, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000
- };
- STATIC USHORT image_data_toggle_knob_unselected[] = { /* bitmap data for unselected toggle knob image */
- 0x1ffc, 0x0000, 0x7000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000,
- 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x7000, 0x0000,
- 0x1000, 0x0000, /* Plane 0 */
- 0x0002, 0x0000, 0x0003, 0x8000, 0x0000, 0xc000, 0x0000, 0xc000,
- 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0003, 0x8000,
- 0x0ffe, 0x0000 /* Plane 1 */
- };
- STATIC USHORT image_data_toggle_knob_selected[] = { /* bitmap data for selected toggle knob image */
- 0x0002, 0x0000, 0x0003, 0x8000, 0x03f0, 0xc000, 0x0ffc, 0xc000,
- 0x0ffc, 0xc000, 0x0ffc, 0xc000, 0x03f0, 0xc000, 0x0003, 0x8000,
- 0x0ffe, 0x0000, /* Plane 0 */
- 0x1ffc, 0x0000, 0x7000, 0x0000, 0xc3f0, 0x0000, 0xcffc, 0x0000,
- 0xcffc, 0x0000, 0xcffc, 0x0000, 0xc3f0, 0x0000, 0x7000, 0x0000,
- 0x1000, 0x0000 /* Plane 1 */
- };
- STATIC USHORT image_data_toggle_check_selected[] = { /* bitmap data for selected toggle checkmark image */
- 0x0038, 0x0060, 0x00c0, 0xe180, 0x7300, 0x3e00, 0x1c00
- };
- STATIC USHORT image_data_cycle[] = { /* bitmap data for cycle image */
- 0x7f01, 0xc181, 0xc181, 0xc7e1, 0xc3c1, 0xc181, 0xc001, 0xc181,
- 0x7f01, /* Plane 0 */
- 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
- 0x0002 /* Plane 1 */
- };
- STATIC USHORT image_data_count_left[] = { /* bitmap data for left count image */
- 0x0700, 0x3f00, 0xff00, 0x3f00, 0x0700
- };
- STATIC USHORT image_data_count_right[] = { /* bitmap data for right count image */
- 0xe000, 0xfc00, 0xff00, 0xfc00, 0xe000
- };
- STATIC struct Image images[MAX_RENDER_IMAGES] = {
- { /* left arrow */
- 0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
- &image_data_arrow_left[0], 0, 0, NULL
- }, { /* right arrow */
- 0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
- &image_data_arrow_right[0], 0, 0, NULL
- }, { /* up arrow */
- 0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
- &image_data_arrow_up[0], 0, 0, NULL
- }, { /* down arrow */
- 0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
- &image_data_arrow_down[0], 0, 0, NULL
- }, { /* toggle select knob unselected */
- 0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
- &image_data_toggle_knob_unselected[0], 0, 0, NULL
- }, { /* toggle select knob selected */
- 0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
- &image_data_toggle_knob_selected[0], 0, 0, NULL
- }, { /* toggle select check unselected */
- IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
- IMAGE_CHECK_HEIGHT, 0, NULL, 0, 0, NULL
- }, { /* toggle select check selected */
- IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
- IMAGE_CHECK_HEIGHT, IMAGE_CHECK_DEPTH,
- &image_data_toggle_check_selected[0], 0, 0, NULL
- }, { /* cycle */
- 0, 0, IMAGE_CYCLE_WIDTH, IMAGE_CYCLE_HEIGHT, IMAGE_CYCLE_DEPTH,
- &image_data_cycle[0], 0, 0, NULL
- }, { /* left count */
- 0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
- &image_data_count_left[0], 0, 0, NULL
- }, { /* right count */
- 0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
- &image_data_count_right[0], 0, 0, NULL
- }
- };
- STATIC struct TextAttr topaz80_attr = { (STRPTR)"topaz.font", TOPAZ_EIGHTY,
- FS_NORMAL, FPF_ROMFONT };
- /* Static prototypes */
-
- SHORT calc_color_level(SHORT color);
- VOID init_render_info_images(struct RenderInfo *ri);
- UBYTE get_image_pixel_color(struct Image *image, USHORT x, USHORT y);
- VOID set_image_pixel_color(struct Image *image, USHORT x, USHORT y,
- UBYTE color);
- /* Static pragmas */
-
- #pragma regcall(calc_color_level(d0))
- #pragma regcall(init_render_info_images(a0))
- #pragma regcall(get_image_pixel_color(a0,d0,d1))
- #pragma regcall(set_image_pixel_color(a0,d0,d1,d2))
-
- /* Get render info for given screen */
-
- struct RenderInfo *
- get_render_info(struct Screen *screen, USHORT flags)
- {
- struct RenderInfo *ri = NULL;
- struct Screen wb_screen;
- struct ColorMap *cmap;
- struct Image *image = &images[0];
- USHORT *data;
- ULONG data_size = 0;
- SHORT i, j, temp, num_colors, back_color, colors[MAX_RENDER_COLORS],
- color_levels[MAX_RENDER_COLORS], pens[MAX_RENDER_COLORS];
-
- if (ri = AllocMem((LONG)sizeof(struct RenderInfo),
- (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
- /* If no screen given then use workbench screen */
- if (! screen) {
- GetScreenData((BYTE *)(screen = &wb_screen), (LONG)
- sizeof(struct Screen), (LONG)WBENCHSCREEN,
- (struct Screen *)NULL);
- }
-
- /* Get screen and window data */
- ri->ri_ScreenWidth = screen->Width;
- ri->ri_ScreenHeight = screen->Height;
- ri->ri_ScreenDepth = screen->RastPort.BitMap->Depth;
- ri->ri_WindowBorderTop = screen->BarHeight -
- screen->BarVBorder + screen->WBorTop;
- ri->ri_WindowBorderLeft = screen->WBorLeft;
- ri->ri_WindowBorderRight = screen->WBorRight;
- ri->ri_WindowBorderBottom = screen->WBorBottom;
- ri->ri_Flags = flags;
-
- /* Calc gadget chipmem data buffer size */
- for (i = 0; i < MAX_RENDER_IMAGES; i++, image++) {
- if (image->ImageData) {
- data_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0)) *
- image->Height * ri->ri_ScreenDepth * 2;
- }
- }
- if (!(data = AllocMem(data_size, (LONG)MEMF_PUBLIC | MEMF_CHIP |
- MEMF_CLEAR))) {
- FreeMem(ri, (LONG)sizeof(struct RenderInfo));
- ri = NULL;
- } else {
- /* Insert image data buffer and size */
- ri->ri_ImageData = data;
- ri->ri_ImageDataSize = data_size;
-
- /* Open screen text font and clone screen text attr struct */
- Forbid();
- if (screen->Font) {
- ri->ri_TextFont = OpenFont(screen->Font);
- }
- Permit();
- if (ri->ri_TextFont) {
- ri->ri_TextAttr.ta_Name = (STRPTR)
- ri->ri_TextFont->tf_Message.mn_Node.ln_Name;
- ri->ri_TextAttr.ta_YSize = ri->ri_TextFont->tf_YSize;
- ri->ri_TextAttr.ta_Style = ri->ri_TextFont->tf_Style;
- ri->ri_TextAttr.ta_Flags = ri->ri_TextFont->tf_Flags;
- } else {
- ri->ri_TextFont = OpenFont(&topaz80_attr);
- CopyMem((BYTE *)&topaz80_attr, (BYTE *)&ri->ri_TextAttr, (LONG)
- sizeof(struct TextAttr));
- }
-
- /* Examine screen colors */
- if ((num_colors = 1 << ri->ri_ScreenDepth) > MAX_RENDER_COLORS) {
- num_colors = MAX_RENDER_COLORS;
- }
- if (num_colors < 3) {
-
- /* Set render pens for monochrome screen */
- ri->ri_HighlightPen = 1;
- ri->ri_ShadowPen = 1;
- ri->ri_TextPen1 = 1;
- ri->ri_TextPen2 = 1;
- ri->ri_BackPen = 0;
- } else {
-
- /* Get current screen colors */
- Forbid();
- cmap = screen->ViewPort.ColorMap;
- for (i = 0; i < num_colors; i++) {
- colors[i] = GetRGB4(cmap, (LONG)i);
- color_levels[i] = calc_color_level(colors[i]);
- pens[i] = i;
- }
- Permit();
-
- /* Save normal background color */
- back_color = colors[0];
-
- /* Sort colors darkest to brightest (BUBBLE SORT) */
- for (i = 0; i < (num_colors - 1); i++) {
- for (j = i + 1; j < num_colors; j++) {
- if (color_levels[i] > color_levels[j]) {
-
- /* Swap colors, color levels and pens */
- temp = colors[i];
- colors[i] = colors[j];
- colors[j] = temp;
-
- temp = color_levels[i];
- color_levels[i] = color_levels[j];
- color_levels[j] = temp;
-
- temp = pens[i];
- pens[i] = pens[j];
- pens[j] = temp;
- }
- }
- }
- if (flags & RENDER_INFO_FLAG_BACK_FILL) {
-
- /* Set render pens - highlight pen first */
- ri->ri_HighlightPen = pens[num_colors - 1];
-
- /* Set shadow pen */
- ri->ri_ShadowPen = pens[0];
-
- /* Set back pen */
- if (! pens[i = 1]) { /* don't use normal background color */
- i++;
- }
- ri->ri_BackPen = pens[i];
- back_color = colors[i]; /* new background color */
- } else {
-
- /* Set render pens - highlight pen first */
- if (! pens[i = num_colors - 1]) { /* don't use normal background color */
- i--;
- }
- ri->ri_HighlightPen = pens[i];
-
- /* Set shadow pen */
- if (! pens[i = 0]) {
- i++;
- }
- ri->ri_ShadowPen = pens[i];
-
- /* Set back pen */
- ri->ri_BackPen = 0;
- }
-
- /* Set text pen 1 */
- for (i = 0, j = 0; i < num_colors; i++) {
- if ((temp = calc_color_difference(colors[i],
- back_color)) > j) {
- j = temp;
- ri->ri_TextPen1 = pens[i];
- }
- }
-
- /* Set text pen 2 */
- for (i = 0, j = 0; i < num_colors; i++) {
- if ((temp = calc_color_difference(colors[i],
- back_color)) > j && pens[i] != ri->ri_TextPen1) {
- j = temp;
- ri->ri_TextPen2 = pens[i];
- }
- }
- }
- init_render_info_images(ri);
- }
- }
- return(ri);
- }
- /* Calc color level with specified scaling values */
-
- STATIC SHORT
- calc_color_level(SHORT color)
- {
- return(calc_color_difference(color, 0));
- }
- /* Calc color difference with specified scaling values */
-
- SHORT /* non static - needed by menus.c too */
- calc_color_difference(SHORT color1, SHORT color2)
- {
- USHORT temp, diff;
-
- temp = (color1 & 0x00f) - (color2 & 0x00f);
- diff = temp * temp * BLUE_SCALE;
- temp = ((color1 >> 4) & 0x00f) - ((color2 >> 4) & 0x00f);
- diff += temp * temp * GREEN_SCALE;
- temp = ((color1 >> 8) & 0x00f) - ((color2 >> 8) & 0x00f);
- diff += temp * temp * RED_SCALE;
- return(diff);
- }
- /* Init render info images */
-
- STATIC VOID
- init_render_info_images(struct RenderInfo *ri)
- {
- struct Image *image_src = &images[0], *image_dest = &ri->ri_Images[0];
- UBYTE color;
- USHORT i, x, y, *data = ri->ri_ImageData;
-
- CopyMem((BYTE *)image_src, (BYTE *)image_dest, (LONG)(MAX_RENDER_IMAGES *
- sizeof(struct Image)));
- for (i = 0; i < MAX_RENDER_IMAGES; i++, image_src++, image_dest++) {
- image_dest->Depth = ri->ri_ScreenDepth;
- if (image_src->ImageData) {
-
- /* Set data buffer ptr */
- image_dest->ImageData = data;
- image_dest->PlanePick = (1 << image_dest->Depth) - 1;
- data += (image_dest->Width / 16 + (image_dest->Width & 15 ? 1 :
- 0)) * image_dest->Height * image_dest->Depth;
- /* Convert image data */
- for (y = 0; y < image_src->Height; y++) {
- for (x = 0; x < image_src->Width; x++) {
- switch(get_image_pixel_color(image_src, x, y)) {
- case 0 : /* back pen */
- color = ri->ri_BackPen;
- break;
- case 1 : /* highlight pen */
- color = ri->ri_HighlightPen;
- break;
- case 2 : /* shadow pen */
- color = ri->ri_ShadowPen;
- break;
- case 3 : /* special pen */
- color = ri->ri_TextPen2;
- break;
- }
- set_image_pixel_color(image_dest, x, y, color);
- }
- }
- } else {
-
- /* No image data -> monochrome rectangle */
- switch(image_src->PlaneOnOff) {
- case 0 : /* back pen */
- color = ri->ri_BackPen;
- break;
- case 1 : /* highlight pen */
- color = ri->ri_HighlightPen;
- break;
- case 2 : /* shadow pen */
- color = ri->ri_ShadowPen;
- break;
- case 3 : /* special pen */
- color = ri->ri_TextPen2;
- break;
- }
- image_dest->PlaneOnOff = color;
- }
- }
- }
- /* Get color of image pixel */
-
- STATIC UBYTE
- get_image_pixel_color(struct Image *image, USHORT x, USHORT y)
- {
- UBYTE i, depth = image->Depth, color_mask = 1, color = 0;
- USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
- *data = image->ImageData + y * modulo + x / 16,
- bit_mask = 0x8000 >> (x & 15);
-
- for (i = 0; i < depth; i++, data += image->Height * modulo,
- color_mask <<= 1) {
- if (*data & bit_mask) {
- color |= color_mask;
- }
- }
- return(color);
- }
- /* Set color of image pixel */
-
- STATIC VOID
- set_image_pixel_color(struct Image *image, USHORT x, USHORT y, UBYTE color)
- {
- UBYTE i, depth = image->Depth;
- USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
- *data = image->ImageData + y * modulo + x / 16,
- bit_mask = 0x8000 >> (x & 15);
-
- for (i = 0; i < depth; i++, data += image->Height * modulo, color >>= 1) {
- if (color & 1) {
- *data |= bit_mask;
- }
- }
- }
- /* Free render info */
-
- VOID
- free_render_info(struct RenderInfo *ri)
- {
- if (ri) {
- if (ri->ri_TextFont) {
- CloseFont(ri->ri_TextFont);
- }
- FreeMem(ri->ri_ImageData, ri->ri_ImageDataSize);
- FreeMem(ri, (LONG)sizeof(struct RenderInfo));
- }
- }
- /* Open window */
-
- struct Window *
- open_window(struct RenderInfo *ri, struct NewWindow *org_nw, USHORT flags)
- {
- struct NewWindow *nw, new_nw;
- struct Window *win = NULL;
-
- if (ri && org_nw) {
-
- /* Duplicate given new window struct */
- CopyMem((BYTE *)org_nw, (BYTE *)(nw = &new_nw), (LONG)
- sizeof(struct NewWindow));
- /* Scale new window dimension */
- if (nw->Width > ri->ri_ScreenWidth) {
- nw->LeftEdge = 0;
- nw->Width = ri->ri_ScreenWidth;
- } else {
- if ((nw->LeftEdge + nw->Width) > ri->ri_ScreenWidth) {
- nw->LeftEdge = ri->ri_ScreenWidth - nw->Width;
- }
- }
- if (nw->Height > ri->ri_ScreenHeight) {
- nw->TopEdge = 0;
- nw->Height = ri->ri_ScreenHeight;
- } else {
- if ((nw->TopEdge + nw->Height) > ri->ri_ScreenHeight) {
- nw->TopEdge = ri->ri_ScreenHeight - nw->Height;
- }
- }
-
- /* Change new window struct */
- if (flags & OPEN_WINDOW_FLAG_CENTER_WINDOW) {
- nw->LeftEdge = (ri->ri_ScreenWidth - nw->Width) / 2;
- nw->TopEdge = (ri->ri_ScreenHeight - nw->Height) / 2;
- }
- if (flags & OPEN_WINDOW_FLAG_RENDER_PENS) {
- if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
- nw->DetailPen = ri->ri_TextPen1;
- nw->BlockPen = ri->ri_BackPen;
- } else {
- nw->DetailPen = ri->ri_BackPen;
- nw->BlockPen = ri->ri_TextPen1;
- }
- }
- if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
- nw->Width += ri->ri_WindowBorderLeft + ri->ri_WindowBorderRight;
- if ((nw->LeftEdge + nw->Width) > ri->ri_ScreenWidth) {
- nw->Width = ri->ri_ScreenWidth - nw->LeftEdge;
- }
- nw->Height += ri->ri_WindowBorderTop + ri->ri_WindowBorderBottom;
- if ((nw->TopEdge + nw->Height) > ri->ri_ScreenHeight) {
- nw->Height = ri->ri_ScreenHeight - nw->TopEdge;
- }
- }
- if (win = OpenWindow(nw)) {
- if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
- clear_render_window(ri, win, 0, 0, nw->Width, nw->Height);
- }
- }
- }
- return(win);
- }
- /* Clear given rectangle of window with data from render info */
-
- VOID
- clear_render_window(struct RenderInfo *ri, struct Window *win,
- USHORT left_edge, USHORT top_edge, USHORT width, USHORT height)
- {
- struct RastPort *rp = win->RPort;
- USHORT inner_left, inner_top, inner_width, inner_height, back_pen,
- flags = ri->ri_Flags;
-
- /* Calc inner window dimension */
- if ((flags & RENDER_INFO_FLAG_INNER_WINDOW) ||
- (flags & RENDER_INFO_FLAG_BACK_FILL)) {
- inner_left = ri->ri_WindowBorderLeft;
- inner_top = ri->ri_WindowBorderTop;
- inner_width = win->Width - inner_left - ri->ri_WindowBorderRight;
- inner_height = win->Height - inner_top - ri->ri_WindowBorderBottom;
- } else {
- inner_left = 0;
- inner_top = 0;
- inner_width = win->Width;
- inner_height = win->Height;
- }
-
- /* Check if given rectangle fits into inner window and if not then scale it */
- if ((SHORT)left_edge >= 0 && (SHORT)top_edge >= 0 && width && height &&
- left_edge < (inner_left + inner_width) && top_edge < (inner_top +
- inner_height)) {
- if (left_edge < inner_left) {
- left_edge = inner_left;
- } else {
- left_edge += inner_left;
- }
- if (top_edge < inner_top) {
- top_edge = inner_top;
- } else {
- top_edge += inner_top;
- }
- if ((SHORT)width <= 0 || (left_edge + width) > (inner_left +
- inner_width)) {
- width = inner_left + inner_width - left_edge;
- }
- if ((SHORT)height <= 0 || (top_edge + height) > (inner_top +
- inner_height)) {
- height = inner_top + inner_height - top_edge;
- }
- if (flags & RENDER_INFO_FLAG_BACK_FILL) {
- back_pen = ri->ri_BackPen;
- } else {
- back_pen = 0;
- }
- SetDrMd(rp, (LONG)JAM1);
- SetAPen(rp, (LONG)back_pen);
- RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge +
- width - 1), (LONG)(top_edge + height - 1));
- }
- }
-