/* * GELs (Icons, Bobs, Windows) Images is an interleaved bitmap with optional * mask. We define Blit function to draw any portion of Image into any * position on BitMap (RastPort). It shifts the image by 0-15 bits, thus * there is a requirement of just one more 16-bit word of data. */ #include #include #include #include #include #include #include #include #include #include #include #define WordWidth(w) (((w)+15)>>4) struct myImage { UWORD *Data; /* Interleaved image data (+1 word) */ UWORD *Mask; /* Mask */ UWORD Width, Height; /* Pixel size */ UBYTE Depth; /* Number of planes */ UBYTE Shift; /* Current shift value */ }; extern __far struct Custom custom; /* allocImage: Alloc space for Image */ BOOL allocImage(struct myImage *pi, UWORD width, UWORD height, UBYTE depth, BOOL mask) { if (pi->Data = AllocMem((RASSIZE(width, height) * depth) + RASSIZE(width, 1), MEMF_CHIP)) { if (mask) { pi->Mask = AllocMem(RASSIZE(width, height) + RASSIZE(width, 1), MEMF_CHIP|MEMF_CLEAR); } else { pi->Mask = NULL; } if (!mask || pi->Mask) { pi->Width = width; pi->Height = height; pi->Depth = depth; pi->Shift = 0; return(TRUE); } if (mask && pi->Mask) { FreeMem(pi->Mask, RASSIZE(width, height) + RASSIZE(width, 1)); } FreeMem(pi->Data, (RASSIZE(width, height) * depth) + RASSIZE(width, 1)); } return(FALSE); } /* freeImage: Free image data */ void freeImage(struct myImage *pi) { UWORD width = pi->Width, height = pi->Height; UBYTE depth = pi->Depth; if (pi->Mask) { FreeMem(pi->Mask, RASSIZE(width, height) + RASSIZE(width, 1)); } FreeMem(pi->Data, (RASSIZE(width, height) * depth) + RASSIZE(width, 1)); } /* shiftImage: Shift Image by N. */ void shiftImage(struct myImage *pi, BYTE n) { struct Custom *pc = &custom; BYTE diff; UWORD *data = pi->Data; UWORD wordWidth = WordWidth(pi->Width); UWORD height = pi->Height; UBYTE depth = pi->Depth; if (n < 0) { n += 16; } if ((diff = n - pi->Shift) == 0) { return; } printf("%d (%d)\n", diff, n); pi->Shift = n; #ifndef ECS assert((height * depth) <= 1024); #endif OwnBlitter(); WaitBlit(); if (diff > 0) { pc->bltcon0 = SRCA | DEST | A_TO_D | (diff << ASHIFTSHIFT); pc->bltcon1 = 0; } else { pc->bltcon0 = SRCA | DEST | A_TO_D | ((-diff) << ASHIFTSHIFT); pc->bltcon1 = BLITREVERSE; data += wordWidth * height * depth + (wordWidth - 1); } pc->bltapt = data; pc->bltdpt = data; pc->bltamod = 0; pc->bltdmod = 0; pc->bltafwm = 0xffff; pc->bltalwm = 0xffff; #ifndef ECS pc->bltsize = (((height * depth) + 1) << 6) | wordWidth; #else pc->bltsizv = (height * depth) + 1; pc->bltsizh = wordWidth; #endif if (data = pi->Mask) { WaitBlit(); if (diff > 0) { pc->bltcon0 = SRCA | DEST | A_TO_D | (diff << ASHIFTSHIFT); pc->bltcon1 = 0; } else { pc->bltcon0 = SRCA | DEST | A_TO_D | ((-diff) << ASHIFTSHIFT); pc->bltcon1 = BLITREVERSE; data += wordWidth * height + (wordWidth - 1); } pc->bltapt = data; pc->bltdpt = data; pc->bltamod = 0; pc->bltdmod = 0; pc->bltafwm = 0xffff; pc->bltalwm = 0xffff; pc->bltsize = ((height + 1) << 6) | wordWidth; } DisownBlitter(); } /* blitImage: Blit any portion of Image on any position within BitMap */ void blitImage(struct myImage *pi, UWORD ix, UWORD iy, struct BitMap *pbm, UWORD bmx, UWORD bmy, UWORD width, UWORD height) { struct Custom *pc = &custom; UWORD wordWidth = WordWidth(pi->Width); UBYTE depth = pi->Depth; UWORD bpr = pbm->BytesPerRow, mod = bpr / depth; UWORD *src; WORD diff; PLANEPTR dest; WORD span = 0; shiftImage(pi, diff = (bmx & 0xF) - (ix & 0xF)); /* Check the proper positioning */ if (((width - 1) & 0xF) + (bmx & 0xF) > 16) { span = 1; } OwnBlitter(); if (pi->Mask == NULL) { WaitBlit(); if ((width & 0xF) == 0 && ((bmx & 0xF) == 0)) { /* Data aligned; Perform Fast blit */ pc->bltcon0 = SRCA | DEST | A_TO_D; pc->bltcon1 = 0; pc->bltapt = pi->Data + (iy * wordWidth * depth) + (ix >> 4); pc->bltdpt = pbm->Planes[0] + (bmy * bpr) + ((bmx >> 4) << 1); pc->bltamod = (wordWidth - WordWidth(width)) << 1; pc->bltdmod = mod - (WordWidth(width) << 1); pc->bltafwm = 0xffff; pc->bltalwm = 0xffff; pc->bltsize = ((height * depth) << 6) | (WordWidth(width)); } else { pc->bltcon0 = SRCB | SRCC | DEST | 0xca; pc->bltcon1 = 0; pc->bltadat = 0xffff; src = pi->Data + (iy * wordWidth * depth) + (ix >> 4); if (diff < 0) src++; pc->bltbpt = src; pc->bltcpt = dest = pbm->Planes[0] + (bmy * bpr) + ((bmx >> 4) << 1); pc->bltdpt = dest; pc->bltbmod = (wordWidth - (WordWidth(width) + span)) << 1; pc->bltcmod = mod - ((WordWidth(width) + span) << 1); pc->bltdmod = mod - ((WordWidth(width) + span) << 1); pc->bltafwm = 0xffff >> (bmx & 0xF); pc->bltalwm = 0xffff << ((16 - ((bmx & 0xF) + (width & 0xf))) & 0xF); pc->bltsize = ((height * depth) << 6) | (WordWidth(width) + span); } } else { /* Implement mask blit */ } DisownBlitter(); } int main(void) { struct myImage img; if (allocImage(&img, 64, 64, 5, FALSE)) { struct BitMap aux; struct RastPort rp; UBYTE p; struct Screen *s; aux.Planes[0] = (PLANEPTR)img.Data; aux.BytesPerRow = (WordWidth(img.Width) << 1) * img.Depth; aux.Rows = img.Height; aux.Depth = img.Depth; for (p = 1; p < img.Depth; p++) { aux.Planes[p] = aux.Planes[p - 1] + (WordWidth(img.Width) << 1); } InitRastPort(&rp); rp.BitMap = &aux; SetOutlinePen(&rp, 1); SetAPen(&rp, 3); RectFill(&rp, 0, 0, img.Width - 1, img.Height - 1); if (s = OpenScreenTags(NULL, SA_Depth, 5, SA_Quiet, TRUE, SA_Interleaved, TRUE, TAG_DONE)) { blitImage(&img, 60, 4, s->RastPort.BitMap, 4, 4, 4, 60); Delay(500); CloseScreen(s); } freeImage(&img); } return(0); }