VOID BltMaskRPort (struct BitMap *source, WORD srcLeft,WORD srcTop, struct RastPort *destination, WORD dstLeft,WORD dstTop,WORD dstWidth,WORD dstHeight, PLANEPTR maskPlane) { if(GetBitMapAttr(source, BMA_FLAGS) & BMF_INTERLEAVED) { struct BitMap mask; InitBitMap(&mask, 8, GetBitMapAttr(source, BMA_WIDTH), GetBitMapAttr(source, BMA_HEIGHT)); for(UWORD i = 0; i < 8; i++) mask.Planes[i] = maskPlane; BltBitMapRastPort(source, srcLeft, srcTop, destination, dstLeft, dstTop, dstWidth, dstHeight, MINTERM_B_EQUALS_C); BltBitMapRastPort(&mask, srcLeft,srcTop, destination, dstLeft, dstTop, dstWidth, dstHeight, MINTERM_B_OR_C); BltBitMapRastPort(source, srcLeft, srcTop, destination, dstLeft, dstTop, dstWidth, dstHeight, MINTERM_B_EQUALS_C); } else { BltMaskBitMapRastPort(source, srcLeft, srcTop, destination, dstLeft, dstTop, dstWidth, dstHeight, (ABC | ABNC | ANBC), maskPlane); } }
/// /// MyBltMaskBitMapRastPort() static void MyBltMaskBitMapRastPort(struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm, APTR bltMask) { ENTER(); if(GetBitMapAttr(srcBitMap, BMA_FLAGS) & BMF_INTERLEAVED) { LONG src_depth = GetBitMapAttr(srcBitMap, BMA_DEPTH); struct Rectangle rect; struct BltHook hook; // Define the destination rectangle in the rastport rect.MinX = xDest; rect.MinY = yDest; rect.MaxX = xDest + xSize - 1; rect.MaxY = yDest + ySize - 1; // Initialize the hook InitHook(&hook.hook, BltMaskHook, NULL); hook.srcBitMap = srcBitMap; hook.srcx = xSrc; hook.srcy = ySrc; hook.destx = xDest; hook.desty = yDest; // Initialize a bitmap where all plane pointers points to the mask InitBitMap(&hook.maskBitMap, src_depth, GetBitMapAttr(srcBitMap, BMA_WIDTH), GetBitMapAttr(srcBitMap, BMA_HEIGHT)); while(src_depth) { hook.maskBitMap.Planes[--src_depth] = bltMask; } // Blit onto the Rastport */ DoHookClipRects(&hook.hook, destRP, &rect); } else { BltMaskBitMapRastPort(srcBitMap, xSrc, ySrc, destRP, xDest, yDest, xSize, ySize, minterm, bltMask); } LEAVE(); }
VOID MyBltMaskBitMapRastPort( struct BitMap *srcBitMap, LONG xSrc, LONG ySrc, struct RastPort *destRP, LONG xDest, LONG yDest, LONG xSize, LONG ySize, ULONG minterm, APTR bltMask) { if (GetBitMapAttr(srcBitMap,BMA_FLAGS)&BMF_INTERLEAVED) { LONG src_depth = GetBitMapAttr(srcBitMap,BMA_DEPTH); struct Rectangle rect; struct BltMaskHook hook; /* Define the destination rectangle in the rastport */ rect.MinX = xDest; rect.MinY = yDest; rect.MaxX = xDest + xSize - 1; rect.MaxY = yDest + ySize - 1; /* Initialize the hook */ #if defined(__AMIGAOS4__) || defined(__MORPHOS__) || defined(__AROS__) hook.hook.h_Entry = (HOOKFUNC)hookEntry; hook.hook.h_SubEntry = (HOOKFUNC)HookFunc_BltMask; #else hook.hook.h_Entry = (HOOKFUNC)HookFunc_BltMask; #endif hook.srcBitMap = srcBitMap; hook.srcx = xSrc; hook.srcy = ySrc; hook.destx = xDest; hook.desty = yDest; /* Initialize a bitmap where all plane pointers points to the mask */ InitBitMap(&hook.maskBitMap,src_depth,GetBitMapAttr(srcBitMap,BMA_WIDTH),GetBitMapAttr(srcBitMap,BMA_HEIGHT)); while (src_depth) hook.maskBitMap.Planes[--src_depth] = (PLANEPTR)bltMask; /* Blit onto the Rastport */ DoHookClipRects(&hook.hook,destRP,&rect); } else { BltMaskBitMapRastPort(srcBitMap, xSrc, ySrc, destRP, xDest, yDest, xSize, ySize, minterm, (PLANEPTR)bltMask); } }
// Draw an object void backdrop_draw_object( BackdropInfo *info, BackdropObject *object, UWORD flags, struct RastPort *rp, short left, short top) { UBYTE fpen=1,bpen=0,drawmode=JAM2,opus_drawmode=JAM2; UWORD *imagedata=0; struct Image *image=0; struct Rectangle rect; short len; BOOL comp=0,draw=1,state=0; short has_border; // No icon? if (!object->icon) return; // See if icon has no border has_border=backdrop_icon_border(object); // Not just clearing image? if (!(flags&BRENDERF_CLEAR)) { // Get image to render if ((image=(struct Image *)object->icon->do_Gadget.GadgetRender)) imagedata=image->ImageData; // Is icon selected? if (object->state) { // Is there a select image? if (object->icon->do_Gadget.SelectRender && (object->icon->do_Gadget.Flags&GFLG_GADGHIMAGE)) { if ((image=(struct Image *)object->icon->do_Gadget.SelectRender)) imagedata=image->ImageData; state=1; } else comp=1; } } #ifdef USE_DRAWICONSTATE if (GetIconRectangle( rp, object->icon, NULL, &rect, ICONDRAWA_Borderless, TRUE, TAG_DONE)) { object->pos.Width = rect.MaxX - rect.MinX + 1; object->pos.Height = rect.MaxY - rect.MinY + 1; } #elif defined(__MORPHOS__) if (ISOWN(object->icon)) { struct OwnDiskObject *o = (APTR)object->icon; object->pos.Width = o->pngimage_width; object->pos.Height = o->pngimage_height; } #endif // Get object position if (flags&BRENDERF_REAL) { short border_x=0,border_y_top=0,border_y_bottom=0; // Border? if (has_border) { // Use default border border_x=ICON_BORDER_X; border_y_top=ICON_BORDER_Y_TOP; border_y_bottom=ICON_BORDER_Y_BOTTOM; } // Calculate full size object->full_size.MinX=left-border_x; object->full_size.MinY=top-border_y_top; object->full_size.MaxX=left+object->pos.Width+border_x-1; object->full_size.MaxY=top+object->pos.Height+border_y_bottom-1; // Get image rectangle rect.MinX=object->full_size.MinX+(info->size.MinX-info->offset_x); rect.MinY=object->full_size.MinY+(info->size.MinY-info->offset_y); rect.MaxX=object->full_size.MaxX+(info->size.MinX-info->offset_x); rect.MaxY=object->full_size.MaxY+(info->size.MinY-info->offset_y); // Store position object->show_rect=rect; object->image_rect=rect; // Is object offscreen? if (rect.MaxX<info->size.MinX || rect.MaxY<info->size.MinY || rect.MinX>info->size.MaxX || rect.MinY>info->size.MaxY) draw=0; // Offset by coordinates left+=info->size.MinX-info->offset_x; top+=info->size.MinY-info->offset_y; } else { rect.MinX=left; rect.MinY=top; rect.MaxX=left+object->pos.Width-1; rect.MaxY=top+object->pos.Height-1; } // Clear area? if (flags&BRENDERF_CLEAR) { // Ok to draw? if (draw) { // Clear whole icon? if (!(flags&BRENDERF_LABEL)) { EraseRect(rp,rect.MinX,rect.MinY,rect.MaxX,rect.MaxY); } } // Can't draw else flags&=~BRENDERF_CLEAR; } // Object state changed? else if (object->flags&BDOF_STATE_CHANGE) { #ifndef USE_DRAWICONSTATE // Need to clear if transparent #if !defined(__MORPHOS__) if (!has_border) #endif EraseRect(rp,rect.MinX,rect.MinY,rect.MaxX,rect.MaxY); #endif object->flags&=~BDOF_STATE_CHANGE; } // Draw as normal if (!(flags&BRENDERF_CLEAR)) { // Not drawing if no image if (!imagedata) draw=0; // Ok to draw? if (draw) { struct BitMap bitmap; BOOL use_mask=0; // Full icon? if (flags&BRENDERF_REAL) { // Want border? if (has_border) { // Draw border around icon DrawBox(rp,&rect,GUI->draw_info,object->state); // Get background colour #ifdef USE_64BIT SetAPen( rp, (object->flags&BDOF_BACKGROUND)? object->pen: GUI->draw_info->dri_Pens[BACKGROUNDPEN]); #else SetAPen( rp, (object->flags&BDOF_BACKGROUND)? object->size: GUI->draw_info->dri_Pens[BACKGROUNDPEN]); #endif // Clear boundary around image #ifdef USE_DRAWICONSTATE RectFill(rp,rect.MinX+1,rect.MinY+1,rect.MaxX-1,rect.MaxY-1); #else RectFill(rp,rect.MinX+1,rect.MinY+1,rect.MaxX-1,rect.MinY+2); RectFill(rp,rect.MinX+1,rect.MinY+1,rect.MinX+3,rect.MaxY-1); RectFill(rp,rect.MinX+4,rect.MaxY-3,rect.MaxX-1,rect.MaxY-1); RectFill(rp,rect.MaxX-3,rect.MinY+3,rect.MaxX-1,rect.MaxY-4); #endif } #ifdef USE_DRAWICONSTATE else { EraseRect(rp,rect.MinX,rect.MinY,rect.MaxX,rect.MaxY); } #endif } #ifdef USE_DRAWICONSTATE DrawIconState( rp, object->icon, NULL, left, top, object->state ? IDS_SELECTED : IDS_NORMAL, ICONDRAWA_Frameless, TRUE, ICONDRAWA_Borderless, TRUE, ICONDRAWA_EraseBackground, FALSE, TAG_DONE); #else #if defined(__MORPHOS__) if (ISOWN(object->icon)) { IPTR tags[] = { BLTBMA_USESOURCEALPHA, TRUE, TAG_DONE }; struct OwnDiskObject *o = (APTR)object->icon; BltBitMapRastPortAlpha(o->pngimage, 0, 0, rp, left, top, o->pngimage_width, o->pngimage_height, (struct TagItem *)&tags); if (object->state) { ProcessPixelArray(rp, left, top, o->pngimage_width, o->pngimage_height, POP_TINT, 0x5082ff, NULL); } } else { #endif // Get image as a bitmap backdrop_image_bitmap(info,image,imagedata,&bitmap); // Using a mask (no border)? if (!has_border && object->image_mask[state]) { // Draw using a mask BltMaskBitMapRastPort( &bitmap,0,0, rp,left,top, image->Width,image->Height, 0xe0, (PLANEPTR)object->image_mask[state]); use_mask=1; } // Draw normally else { // Draw image BltBitMapRastPort( &bitmap,0,0, rp,left,top, image->Width,image->Height, 0xc0); } // Complement? if (comp) { DragInfo *drag_info; UBYTE mask; // Only complement to image depth mask=rp->Mask; SetWrMsk(rp,image->PlanePick); // Need backfill? if ((object->icon->do_Gadget.Flags&GFLG_GADGBACKFILL) && (drag_info=GetDragInfo(info->window,0,-object->pos.Width,-object->pos.Height,0))) { // Draw icon into drag buffer BltBitMapRastPort( &bitmap,0,0, &drag_info->drag_rp,0,0, image->Width,image->Height, 0xc0); // Build mask GetDragMask(drag_info); // Complement area with mask BltMaskBitMapRastPort( &drag_info->drag_bm, 0,0, rp, left,top, image->Width, image->Height, 0x20, (PLANEPTR)drag_info->bob.ImageShadow); // Free temporary drag info FreeDragInfo(drag_info); } // Just complement image else { ClipBlit( rp, left,top, rp, left,top, image->Width, image->Height, 0x50); } // Restore mask SetWrMsk(rp,mask); } #if defined(__MORPHOS__) } #endif #endif // Left out (on desktop), or a link? if (!(environment->env->desktop_flags&DESKTOPF_NO_ARROW) && ((object->type==BDO_LEFT_OUT && !(object->flags&BDOF_DESKTOP_FOLDER) && info->flags&BDIF_MAIN_DESKTOP) || object->flags&BDOF_LINK_ICON)) { struct Image *image; // Get correct image for this resolution image=(GUI->screen_info&SCRI_LORES)?&arrow_image[1]:&arrow_image[0]; // Is object big enough for the 'shortcut arrow'? if (object->pos.Width>(image->Width<<1) && object->pos.Height>image->Height+4) { // Draw arrow in bottom-left corner DrawImage(rp,image,rect.MinX,rect.MaxY-image->Height+1); } } // Ghosted icon? if (object->flags&BDOF_GHOSTED) { // Draw ghosting over the icon backdrop_draw_icon_ghost(rp,&rect,(use_mask)?(PLANEPTR)object->image_mask[state]:0); } } // Get pens from configuration fpen=(info->flags&BDIF_MAIN_DESKTOP)?environment->env->icon_fpen:environment->env->iconw_fpen; bpen=(info->flags&BDIF_MAIN_DESKTOP)?environment->env->icon_bpen:environment->env->iconw_bpen; drawmode=(info->flags&BDIF_MAIN_DESKTOP)?environment->env->icon_style:environment->env->iconw_style; opus_drawmode=drawmode; // Shadow/Outline? if (drawmode==MODE_SHADOW || drawmode==MODE_OUTLINE) { UBYTE temp; // Set back to JAM1 drawmode=JAM1; // Swap the pens temp=fpen; fpen=bpen; bpen=temp; } // Fix pens for user colours if (fpen>=4 && fpen<252) fpen=GUI->pens[fpen-4]; if (bpen>=4 && bpen<252) bpen=GUI->pens[bpen-4]; // Use fast call under 39 if(((struct Library *)GfxBase)->lib_Version>=39) { SetABPenDrMd(rp,fpen,bpen,drawmode); } else { SetAPen(rp,fpen); SetBPen(rp,bpen); SetDrMd(rp,drawmode); } } // Full icon? if (flags&BRENDERF_REAL && !(object->flags&BDOF_NO_LABEL)) { char *name,namebuf[40]; // Bad disk? if (object->type==BDO_BAD_DISK) { // Get bad disk name backdrop_bad_disk_name(object,namebuf); name=namebuf; } // Custom label? else if (object->flags&BDOF_CUSTOM_LABEL) name=object->device_name; // Get name pointer else name=object->name; // Get text length if ((len=strlen(name))) { struct TextExtent extent; short max_width=0,loop,textx,texty; // Splitting long labels? if (environment->env->desktop_flags&DESKTOPF_SPLIT_LABELS) { // Calculate maximum text width (minimum 6 chars) max_width=RECTWIDTH(&rect)+(RECTWIDTH(&rect)>>1); if (max_width<rp->Font->tf_XSize*6) max_width=rp->Font->tf_XSize*6; } // Position for text textx=rect.MinX+(RECTWIDTH(&rect)>>1); texty=rect.MaxY+ICON_LABEL_SPACE+rp->TxBaseline+((opus_drawmode==MODE_OUTLINE)?1:0); Move(rp,textx,texty); // Get text pixel size TextMultiLine(rp,name,len,max_width,TMLF_CENTER|TMLF_EXTENT,&extent); // Fix extent for shadow/outline if (opus_drawmode==MODE_SHADOW) { extent.te_Extent.MaxX++; extent.te_Width++; extent.te_Height++; } else if (opus_drawmode==MODE_OUTLINE) { extent.te_Extent.MinX--; extent.te_Extent.MaxX++; extent.te_Width+=2; extent.te_Height+=2; } // Stretch out rectangle sides if necessary if (extent.te_Extent.MinX<rect.MinX) object->full_size.MinX-=rect.MinX-extent.te_Extent.MinX; if (extent.te_Extent.MaxX>rect.MaxX) object->full_size.MaxX+=extent.te_Extent.MaxX-rect.MaxX; if (object->show_rect.MinX>extent.te_Extent.MinX) object->show_rect.MinX=extent.te_Extent.MinX; if (object->show_rect.MaxX<extent.te_Extent.MinX+extent.te_Width-1) object->show_rect.MaxX=extent.te_Extent.MinX+extent.te_Width-1; // Save bottom of text object->show_rect.MaxY+=ICON_LABEL_SPACE+extent.te_Height; // +((opus_drawmode==MODE_OUTLINE)?1:0); object->full_size.MaxY+=ICON_LABEL_SPACE+extent.te_Height; // +((opus_drawmode==MODE_OUTLINE)?1:0); // Clear? if (flags&BRENDERF_CLEAR) { EraseRect(rp, extent.te_Extent.MinX,rect.MaxY+ICON_LABEL_SPACE+((opus_drawmode==MODE_OUTLINE)?1:0), extent.te_Extent.MinX+extent.te_Width-1,rect.MaxY+ICON_LABEL_SPACE+extent.te_Height-1); } // Draw text else { // Is object selected? if (object->flags&BDOF_SELECTED) { if (drawmode==JAM2) SetDrMd(rp,INVERSVID|JAM2); else if (fpen!=GUI->draw_info->dri_Pens[HIGHLIGHTTEXTPEN]) SetAPen(rp,GUI->draw_info->dri_Pens[HIGHLIGHTTEXTPEN]); else SetAPen(rp,GUI->draw_info->dri_Pens[BACKGROUNDPEN]); } // Shadow if (opus_drawmode==MODE_SHADOW) { // Draw shadow text first Move(rp,textx+1,texty+1); TextMultiLine(rp,name,len,max_width,TMLF_CENTER,0); // Draw text SetAPen(rp,bpen); Move(rp,textx,texty); TextMultiLine(rp,name,len,max_width,TMLF_CENTER,0); } // Normal text else if (opus_drawmode!=MODE_OUTLINE) { // Render text TextMultiLine(rp,name,len,max_width,TMLF_CENTER,0); } // Outline else { Move(rp,textx+1,texty+1); for (loop=0;loop<5;loop++) { // Render text TextMultiLine(rp,name,len,max_width,TMLF_CENTER,0); // Doing shadow? if (loop<4) { short s_x=0,s_y=0; // Switch to other pen? if (loop==3) SetAPen(rp,bpen); // Get the new offsets else if (loop==0) { s_x=-1; s_y=1; } else if (loop==1) { s_x=-1; s_y=-1; } else if (loop==2) { s_x=1; s_y=-1; } // Position for text Move(rp,textx+s_x,texty+s_y); } } } // Reset draw mode if necessary if (object->flags&BDOF_SELECTED) SetDrMd(rp,drawmode); } }
void BMKBRP(struct BitMap *a,WORD b, WORD c,struct RastPort *d,WORD e,WORD f,WORD g,WORD h,UBYTE i,APTR j) {BltMaskBitMapRastPort(a,b,c,d,e,f,g,h,i,j);}