// // Except as otherwise noted, // the author of this software is abiSoft. Inc. // Copyright (c) 1998 abiSoft. Inc. // Permission to use, copy, modify, and distribute this software for any // purpose without fee is hereby granted, provided that this entire notice // is included in all copies of any software which is or includes a copy // or modification of this software and in all copies of the supporting // documentation for such software. // THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED // WARRANTY. IN PARTICULAR, THE AUTHOR DOES NOT MAKE ANY // REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY // OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. // #include "abisoftButton.h" abisoftPictureButton::abisoftPictureButton(BRect frame, const char* name, BPicture *off, BPicture *on, BMessage *message, uint32 behavior, uint32 resizeMask, uint32 flags) : BPictureButton (frame, name, off, on, message, behavior, resizeMask, flags) { }; abisoftPictureButton::~abisoftPictureButton() { }; void abisoftPictureButton::MouseMoved( BPoint where, uint32 code, const BMessage *a_message) { if (a_message) { switch(code) { case B_ENTERED_VIEW: SetEnabled(false); break; case B_INSIDE_VIEW: snooze(1000.00 * 30.0); //Be a good citizen break; case B_EXITED_VIEW: default: SetEnabled(true); break; } } } abisoftButton::abisoftButton( BRect rect, const char *name, uint32 msgWhat, int flag, int argc, const char **argv, const char *picFile, int argc2, const char**argv2, const char *pic2File) :BView(rect, "MyButtonBitmapView", B_FOLLOW_ALL, B_NAVIGABLE ) { strncpy(button_name, name, 127); //arbitrary, limit button_name to 128 characters button_name[127] = '\0'; //find the current directory BAppFileInfo afi; be_app->GetAppInfo(&ai); //now get the parent directory BEntry Entry(&ai.ref); BPath path; Entry.GetPath(&path); path.GetParent(&parentPath); //establish the directories for sound files and image files sprintf(SoundDirectoryPath, "%s/%s", parentPath.Path(), SoundDirectoryName); SoundDirectory.SetTo(SoundDirectoryPath); sprintf(ImageDirectoryPath, "%s/%s", parentPath.Path(), ImageDirectoryName); ImageDirectory.SetTo(SoundDirectoryPath); SaveInDirectory = true; //default saving in directory //hooks for saving in resources or preferences not tested! ButtonRect = rect; //set some other defaults arrowType = flag; what = msgWhat; //here is where we save the what NumStrings = argc; LabelStrings = new char * [argc]; for (int32 i = 0; i < NumStrings; i++) if (argv && argv[i]) { LabelStrings[i] = strdup(argv[i]); } NumToggleStrings = argc2; ToggleStrings = new char * [argc2]; for (int32 i = 0; i < NumToggleStrings; i++) if (argv2 && argv2[i]) { ToggleStrings[i] = strdup(argv2[i]); } if (picFile) strcpy(picFileName, picFile); else picFileName[0] = '\0'; BuildColorTable(); if (arrowType == A_TWO_STRING) { //make the second button char buf[132]; sprintf(buf, "%sToggle", button_name); toggleButton = new abisoftButton(ButtonRect, buf, A_TOGGLE_BUTTON, A_STRING, NumToggleStrings, ToggleStrings, pic2File); } else toggleButton = NULL; //set default colors NormalArrowColor = 32; PressedArrowColor = 42; RightCornerColor = 19; LeftCornerColor = 18; RightVerticalInset1Color = 17; RightVerticalInset2Color = 24; EdgeColor = 9; NormalTopEdgeInsetColor = 29; NormalBackColor.red = 235; NormalBackColor.green = 235; NormalBackColor.blue = 235; //main background color NormalTopColor = 63; TopEdgeInsetColorPressed = 13; //one line in from edge TopColorPressed = 15; myFontSize = 11.0; myFont = BFont(be_bold_font); but = NULL; } abisoftButton::~abisoftButton() { for (int32 i = 0; i < 3; i++) delete ButtonBitmap[i]; for (int32 i = 0; i < NumStrings; i++) free(LabelStrings[i]); delete [] LabelStrings; for (int32 i = 0; i < NumToggleStrings; i++) free(ToggleStrings[i]); delete [] ToggleStrings; } void abisoftButton::AttachedToWindow() { BuildButton(); } void abisoftButton::SetLabelFontSize(float fsize) { myFontSize = fsize; if (Window()) {//check that we are attached for (int32 i = 0; i < 3; i++) delete ButtonBitmap[i]; BuildButton(); } if (toggleButton) toggleButton->SetLabelFontSize(fsize); } void abisoftButton::SetLabelFont(BFont& newFont) { myFont = newFont; myFontSize = newFont.Size(); if (Window()) {//check that we are attached for (int32 i = 0; i < 3; i++) delete ButtonBitmap[i]; BuildButton(); } if (toggleButton) { toggleButton->SetLabelFont(myFont); } } void abisoftButton::SetButtonPicture(const char *NewFileName) { strcpy(picFileName, NewFileName); if (Window()) {//check that we are attached for (int32 i = 0; i < 3; i++) delete ButtonBitmap[i]; BuildButton(); } if (toggleButton) toggleButton->SetButtonPicture(NewFileName) ; } void abisoftButton::SetBackgroundColor(rgb_color color) { NormalBackColor = color; if (Window()) {//check that we are attached for (int32 i = 0; i < 3; i++) delete ButtonBitmap[i]; BuildButton(); } if (toggleButton) toggleButton->SetBackgroundColor(color); } rgb_color abisoftButton::GetBackgroundColor() { return NormalBackColor; } void abisoftButton::GetBackgroundColor(rgb_color *color) { *color = NormalBackColor; } void abisoftButton::BuildButton() { unsigned char* bits; BRect tempRect = ButtonRect; ButtonWidth = tempRect.Width(); rgb_color c; int32 ArrowColor = NormalArrowColor; tempRect.OffsetTo(B_ORIGIN); BScreen myScreen; rgb_color HiColor = myScreen.ColorForIndex(ArrowColor); FindSoundRef(); //load sound, if any, for this button BBitmap *butBitmap = GetPictureFileBitmap(); if (!butBitmap && picFileName[0] != '\0') { //try to get the bitmap using datatypes and glue.lib //first, do we have a '/' in the file name if (strchr(picFileName, '/')) butBitmap = GetBitmap(picFileName); else { char buf[B_FILE_NAME_LENGTH +1]; sprintf(buf, "%s/%s", ImageDirectoryPath, picFileName); BFile readFile(buf, B_READ_ONLY); if (readFile.InitCheck() == B_NO_ERROR) { butBitmap = GetBitmap(buf); } } } //set "default" colors for edges for (int32 ButtonState = 0; ButtonState < 3; ButtonState++) { switch(arrowType) { case A_RIGHT_ARROW: case A_LEFT_ARROW: case A_UP_ARROW: case A_DOWN_ARROW: default: ButtonBitmap[ButtonState] = new BBitmap( tempRect, B_COLOR_8_BIT ); break; case A_STRING: case A_TWO_STRING: //construct so that we can attach a view ButtonBitmap[ButtonState] = new BBitmap( tempRect, B_COLOR_8_BIT, true); break; } int32 length = ButtonBitmap[ButtonState]->BitsLength(); int32 rowLength = ButtonBitmap[ButtonState]->BytesPerRow(); int32 rowWidthOffset = rowLength - (int32) ButtonWidth;; unsigned char *aptr = new unsigned char[length + 1]; switch(ButtonState) { case 0: TopEdgeInsetColor = NormalTopEdgeInsetColor; TopColor = NormalTopColor; ArrowColor = NormalArrowColor; BackColor = myScreen.IndexForColor(NormalBackColor); break; case 2: TopEdgeInsetColor = TopEdgeInsetColorPressed; //one line in from edge TopColor = TopColorPressed; ArrowColor = myScreen.IndexForColor( mylightcolor[NormalArrowColor]); BackColor = myScreen.IndexForColor( mylightcolor[myScreen.IndexForColor( NormalBackColor)]); case 1: default: TopEdgeInsetColor = TopEdgeInsetColorPressed; //one line in from edge TopColor = TopColorPressed; ArrowColor = myScreen.IndexForColor( mydarkcolor[NormalArrowColor]); BackColor = myScreen.IndexForColor( mydarkcolor[myScreen.IndexForColor( NormalBackColor)]); } for (int32 i = 0; i < length; i++) aptr[i] = BackColor; int32 NumRows = length/rowLength; for (int32 i = 0; i < length; i+= rowLength) { aptr[i] = EdgeColor; //leftmost column int32 CurRowNo = i/rowLength; //present row number if (CurRowNo > 0 && CurRowNo < NumRows -1) //column one in aptr[i+1] = TopEdgeInsetColor; if (CurRowNo > 1 && CurRowNo < NumRows - 2) { //inset 2 rows from top and bottom aptr[i + 2] = TopColor; //white on left if (CurRowNo < NumRows - 3) aptr[i+3] = TopColor; //white } //draw a dark line on the right -- value = RightVerticalInset1Color //start on the third line, one pixel in from the -3 end if (CurRowNo > 1 && CurRowNo < NumRows -1 ) aptr[i + rowLength-(rowWidthOffset +1)] = RightVerticalInset1Color; //now do a line parallel at value = RightVerticalInset2Color if (CurRowNo > 2 && CurRowNo < NumRows -2) aptr[i + rowLength - (rowWidthOffset +2) ] = RightVerticalInset2Color; aptr[i + rowLength -rowWidthOffset] = EdgeColor; //right left } //do the horizontal lines for (int32 i = 0; i < rowLength -rowWidthOffset; i++) { aptr[i] = EdgeColor; //top edge if (i > 2 && i < rowLength -(rowWidthOffset + 1) ) { aptr[length - rowLength * rowWidthOffset + i] = RightVerticalInset2Color; aptr[i+ 2*rowLength] = TopColor; if (i < rowLength - (rowWidthOffset + 2) ) aptr[i + 3*rowLength] = TopColor; } if (i > 1 && i < rowLength -rowWidthOffset) { aptr[i + rowLength] = TopEdgeInsetColor; aptr[length - rowLength * 2 + i] = RightVerticalInset1Color; } aptr[length - rowLength + i] = EdgeColor; //bottom } //now set the corners aptr[0] = LeftCornerColor; aptr[rowLength-rowWidthOffset] = RightCornerColor; aptr[length - rowLength] = LeftCornerColor; aptr[length -rowWidthOffset] = RightCornerColor; if (arrowType != A_STRING && arrowType != A_TWO_STRING) { //draw the triangle //find the point of the triangle //for a left pointing arrow //start at the middle of the rectangle, 1/3 in from the left //move the armed picture int32 LeftPoint = (NumRows/2 + ButtonState * 2) * rowLength + rowLength /3 + (ButtonState * 2); int32 maxX = .25 * rowLength; //length of the arrow aptr[LeftPoint] = ArrowColor; switch(arrowType) { case A_LEFT_ARROW: aptr[LeftPoint-1] = ArrowColor; break; case A_RIGHT_ARROW: default: aptr[LeftPoint + maxX + 1] = ArrowColor; break; } for (int32 i = 0; i < maxX ; i++) { aptr[LeftPoint + i +1] = ArrowColor; switch(arrowType) { case A_LEFT_ARROW: for (int32 j = 0; j < i *.5 ; j++) { //for a left arrow aptr[LeftPoint + i + (j + 1) * rowLength] = ArrowColor; aptr[LeftPoint + i + (j + 1) * rowLength + 1] = ArrowColor; aptr[LeftPoint + i - (j + 1) * rowLength] = ArrowColor; aptr[LeftPoint + i - (j + 1) * rowLength + 1] = ArrowColor; } break; case A_RIGHT_ARROW: default: for (int32 j = (maxX - i ) /2 -1; j >= 0; j--) { //for a right arrow aptr[LeftPoint + i + (j + 1) * rowLength] = ArrowColor; aptr[LeftPoint + i + (j + 1) * rowLength + 1] = ArrowColor; aptr[LeftPoint + i - (j + 1) * rowLength] = ArrowColor; aptr[LeftPoint + i - (j + 1) * rowLength + 1] = ArrowColor; } } } ButtonBitmap[ButtonState]->SetBits ( aptr, length, 0, B_COLOR_8_BIT); } else if (arrowType == A_STRING || arrowType == A_TWO_STRING) { //draw outline on button ButtonBitmap[ButtonState]->SetBits ( aptr, length, 0, B_COLOR_8_BIT); BRect offRect = tempRect; if (ButtonState == 0) offRect.InsetBy(2, 2); offRect.OffsetTo(B_ORIGIN); BView *offscreen = new BView(offRect, "offScreen", B_FOLLOW_ALL, 0); ButtonBitmap[ButtonState]->Lock(); ButtonBitmap[ButtonState]->AddChild(offscreen); offscreen->SetDrawingMode(B_OP_OVER); BFont SetFont(myFont); myFont.SetSize(myFontSize); SetFont.SetSize(myFontSize); offscreen->SetFont(&SetFont); //see if we have a picture if (butBitmap) { BBitmap *tmap = CompressBitmap(butBitmap, ButtonWidth); int32 tmapNumBytes = tmap->BitsLength(); tmap->Lock(); if (ButtonState == 1) { uchar *ptr = (uchar *) tmap->Bits(); for (int32 i = 0; i < tmapNumBytes; i++) ptr[i] = myScreen.IndexForColor(mydarkcolor[ptr[i]]); offscreen->DrawBitmap(tmap, BPoint(7,7)); } else if (ButtonState == 2) { uchar *ptr = (uchar *) tmap->Bits(); for (int32 i = 0; i < tmapNumBytes; i++) ptr[i] = myScreen.IndexForColor(mylightcolor[ptr[i]]); offscreen->DrawBitmap(tmap, BPoint(5,5)); } else offscreen->DrawBitmap(tmap, BPoint(5,5)); tmap->Unlock(); delete tmap; } float rectWidth = offRect.Width(); float rectHeight = offRect.Height(); BFont ourFont; offscreen->GetFont(&ourFont); font_height ourHeight; ourFont.GetHeight(&ourHeight); float lineheight = ourHeight.ascent + ourHeight.descent + ourHeight.leading; float ypos = (rectHeight - NumStrings*lineheight)/2+lineheight + 1; for (int32 n = 0; n < NumStrings; n++) { float width = offscreen->StringWidth(LabelStrings[n]); offscreen->MovePenTo(1 +(rectWidth - width)/2, ypos); offscreen->DrawString(LabelStrings[n]); ypos += lineheight; } offscreen->Sync(); ButtonBitmap[ButtonState]->RemoveChild(offscreen); delete offscreen; ButtonBitmap[ButtonState]->Unlock(); } delete [] aptr; } Window()->Lock(); BPicture *pic[3]; for (int i = 0; i < 3; i++) { pic[i] = new BPicture(); BeginPicture(pic[i]); DrawBitmap(ButtonBitmap[i], B_ORIGIN); EndPicture(); } if (but) { RemoveChild(but); delete but; } but = new abisoftPictureButton(tempRect, "hi", pic[0], pic[1], new BMessage(what), B_ONE_STATE_BUTTON); but->SetTarget(this); but->SetDisabledOff(pic[1]); but->SetDisabledOn(pic[1]); AddChild(but); Window()->Unlock(); delete pic[0]; delete pic[1]; delete pic[2]; delete butBitmap; } //from a Jon Watte posting //converts a 32 bit bitmap to an 8 bit bitmap BBitmap * abisoftButton::Get8BitBitmap(const BBitmap *input) { BBitmap *map = new BBitmap(input->Bounds(), B_COLOR_8_BIT, true); map->Lock(); BView *view = new BView(map->Bounds(), "", 0, 0); map->AddChild(view); /* do the conversion */ view->DrawBitmap(input, B_ORIGIN); view->Sync(); /* clean up unnecessary clutter */ map->RemoveChild(view); delete view; map->Unlock(); /* declare success and go home */ return map; } void abisoftButton::BuildColorTable() { BScreen myScreen; for (int i = 0; i < 256; i++) { rgb_color Color = myScreen.ColorForIndex(i); mycolor[i].red = Color.red; mycolor[i].green = Color.green; mycolor[i].blue = Color.blue; mycolor[i].alpha = 255; mylightcolor[i].red = Color.red * 1/2; mylightcolor[i].green = Color.green * 1/2; mylightcolor[i].blue = Color.blue * 1/2; mylightcolor[i].alpha = 255; mydarkcolor[i].red = Color.red * 2/3; mydarkcolor[i].green = Color.green * 2/3; mydarkcolor[i].blue = Color.blue * 2/3; mydarkcolor[i].alpha = 255; } } void abisoftButton::MessageReceived(BMessage *msg) { struct rgb_color *rgbColor; ssize_t numBytes = sizeof(struct rgb_color); entry_ref ref; but->SetEnabled(true); switch(msg->what) { case B_PASTE: { if ( msg->FindData( "RGBColor", (type_code) B_RGB_COLOR_TYPE, (void **) &rgbColor, &numBytes ) == B_OK) { if ( msg->WasDropped() ) { rgb_color CurrentColor = NormalBackColor; SetBackgroundColor(*rgbColor); msg->what = SAVE_COLOR; msg->AddString("buttonName", button_name); msg->AddData("OldColorRGB", B_RGB_COLOR_TYPE, (void *) &CurrentColor, sizeof(B_RGB_COLOR_TYPE) ); be_app->PostMessage(msg); } return; } } case '!FNT': { //the dropped font message from Marco Nelissen's FontSelector BFont font; FindMessageFont(msg, "font", 0, &font); // helper-function from Dianne Hackborn's FFont package SetLabelFont(font); msg->what = SAVE_FONT; msg->AddString("buttonColor", button_name); be_app->PostMessage(msg); return; } case B_SIMPLE_DATA: // Look for a ref in the message if( msg->FindRef("refs", &ref) == B_OK ){ //printf("file name to open is %s\n", ref.name ); BEntry Entry(&ref); BPath path; Entry.GetPath(&path); BSoundFile file; //is this a valid sound file? if (file.SetTo(&ref, B_READ_ONLY) == B_OK &&file.FileFormat() != B_UNKNOWN_FILE) { //valid sound file play_sound(&ref, true, true, true); //now save the soundfile in the SoundDirectory BFile saveFile(&ref, B_READ_ONLY); if (saveFile.InitCheck() == B_NO_ERROR) { off_t FileSize; ssize_t readLen; status_t rc; if ( ( rc = saveFile.GetSize(&FileSize)) == B_NO_ERROR) { //read file char *buf = new char [FileSize]; readLen = saveFile.Read(buf, (size_t) FileSize); if (readLen == (ssize_t) FileSize) { BFile newFile; SoundDirectory.CreateFile(button_name, &newFile); int rc = newFile.Write(buf, (size_t) FileSize); } } } SoundRef = ref; DoSound = true; } else { //image or text SetButtonPicture( path.Path()); } return; } } if (DoSound) { play_sound(&SoundRef, true, true, true); } if (arrowType == A_TWO_STRING) { toggleButton->Show(); Hide(); } if (msg->what == A_TOGGLE_BUTTON) { Hide(); abisoftButton *aB = (abisoftButton *) NextSibling(); aB->Show(); BMessage message(aB->GetMessageWhat() ); be_app->PostMessage(&message); } else be_app->PostMessage(msg); } uint32 abisoftButton::GetMessageWhat(void) { return what; } //CompressBitmap() is freely copied from // class DThumbnail // // Copyright 1997 Thorsten Seitz // // License: // This class may be freely used in your programs. // // Purpose: // create Thumbnails/Icons from BBitmaps, // read Thumbnails/Icons from attributes, // write Thumbnails/Icons to attributes #define min(a,b) ((a)>(b)?(b):(a)) #define max(a,b) ((a)>(b)?(a):(b)) BBitmap * abisoftButton::CompressBitmap(const BBitmap * original, int32 size) { BBitmap * thumbnail; float width = original->Bounds().Width() + 1.0; float height = original->Bounds().Height() + 1.0; float tWidth, tHeight; float newWidth = static_cast(size); if (width <= newWidth) //do not need compression return Get8BitBitmap(original); else { tWidth = newWidth; tHeight = (newWidth / width) * height; } // color space has to be B_RGB_32_BIT if (original->ColorSpace() != B_RGB_32_BIT) { auto_ptr new_map = new BBitmap(original->Bounds(), B_RGB_32_BIT, true); BView *view = new BView(original->Bounds(), NULL, B_FOLLOW_NONE, 0); new_map->AddChild(view); BAutolock lock(view->Looper()); view->DrawBitmap(original); original = new_map.get(); } // create thumbnail int32 w = static_cast(width); int32 h = static_cast(height); int32 tw = static_cast(tWidth); int32 th = static_cast(tHeight); //ASSERT(tw > 0 && th > 0); thumbnail = new BBitmap( BRect(0, 0, tw - 1.0, th - 1.0), B_COLOR_8_BIT ); // get color map (in case of dithering) int dither = 1; uint8 colorIndex; uint32 rgb15; int32 r_error, g_error, b_error, rd, gd, bd; int32 new_r_error, new_g_error, new_b_error; const color_map* colorMap = NULL; if (dither) colorMap = system_colors(); //DAutoBuffer be(tw); //DAutoBuffer ge(tw); //DAutoBuffer re(tw); int32 *be = new int32 [tw]; int32 *ge = new int32 [tw]; int32 *re = new int32 [tw]; // fill thumbnail (very simple algorithm) //DAutoBuffer blue(tw); // DAutoBuffer green(tw); // DAutoBuffer red(tw); // DAutoBuffer alpha(tw); // DAutoBuffer xcount(tw); int32 *blue = new int32 [tw]; int32 *green = new int32 [tw]; int32 *red = new int32 [tw]; int32 *alpha = new int32 [tw]; int32 *xcount = new int32 [tw]; uint32 bgra; uint32 *bits = static_cast(original->Bits()); uint32 *tBits = static_cast(thumbnail->Bits()); uint8 *tChars = static_cast(thumbnail->Bits()); uint32 *line = bits; uint8 *tCharLine = tChars; uint32 intsPerRow = original->BytesPerRow() / 4; uint32 tBytesPerRow = thumbnail->BytesPerRow(); uint32 x, y, xc, yc, itx, tx, ty, ycount, area, b, g, r, a; // calculate width of cells for (x = 0; x < tw; x++) { blue[x] = green[x] = red[x] = alpha[x] = xcount[x] = 0; be[x] = ge[x] = re[x] = 0; } tx = 0; xc = tw; do { xcount[tx]++; xc += tw; if (xc > w) { tx++; xc -= w; } } while (tx < tw); // calculate colors of cells y = ty = ycount = 0; yc = th; do { bits = line; ASSERT(y < h); for (tx = 0; tx < tw; tx++) { for (x = 0; x < xcount[tx]; x++) { bgra = *bits++; blue[tx] += (bgra & 0xFF000000) >> 24; green[tx] += (bgra & 0xFF0000) >> 16; red[tx] += (bgra & 0xFF00) >> 8; alpha[tx] += bgra & 0xFF; } } line += intsPerRow; y++; ycount++; yc += th; if (yc > h) { // write colors tBits = static_cast(static_cast(tCharLine)); tChars = tCharLine; r_error = g_error = b_error = 0; for (itx = 0; itx < tw; itx++) { if (dither && !(ty & 1)) tx = tw - itx - 1; else tx = itx; area = xcount[tx] * ycount; b = min((uint32)255, (blue[tx] / area)); g = min((uint32)255, (green[tx] / area)); r = min((uint32)255, (red[tx] / area)); a = min((uint32)255, (alpha[tx] / area)); bgra = (b << 24)| (g << 16) | (r << 8) | a; if (dither) { // dithering (error diffusion) rd = r + r_error + re[tx]; gd = g + g_error + ge[tx]; bd = b + b_error + be[tx]; rd = min((uint32)255, (uint32)max((int32)0, rd)); gd = min((uint32)255, (uint32)max((int32)0, gd)); bd = min((uint32)255, (uint32)max((int32)0, bd)); rgb15 = ((rd & 0xf8) << 7) | ((gd & 0xf8) << 2) | ((bd & 0xf8) >> 3); colorIndex = colorMap->index_map[rgb15]; tCharLine[tx] = colorIndex; rgb_color qCol = colorMap->color_list[colorIndex]; new_r_error = ((int32)r - (int32)qCol.red); new_g_error = ((int32)g - (int32)qCol.green); new_b_error = ((int32)b - (int32)qCol.blue); r_error += new_r_error * 5 / 16; g_error += new_g_error * 5 / 16; b_error += new_b_error * 5 / 16; if (tx > 0 && !(ty & 1) || tx+1 < tw && (ty & 1)) { re[tx + ((ty & 1) ? 1 : -1)] += new_r_error * 3 / 16; ge[tx + ((ty & 1) ? 1 : -1)] += new_g_error * 3 / 16; be[tx + ((ty & 1) ? 1 : -1)] += new_b_error * 3 / 16; } re[tx] += new_r_error * 7 / 16; ge[tx] += new_g_error * 7 / 16; be[tx] += new_b_error * 7 / 16; if (tx > 0 && (ty & 1) || tx+1 < tw && !(ty & 1)) { re[tx + ((ty & 1) ? -1 : 1)] += new_r_error - new_r_error * 7 / 16 - new_r_error * 3 / 16 - new_r_error * 5 / 16; ge[tx + ((ty & 1) ? -1 : 1)] += new_g_error - new_g_error * 7 / 16 - new_g_error * 3 / 16 - new_g_error * 5 / 16; be[tx + ((ty & 1) ? -1 : 1)] += new_b_error - new_b_error * 7 / 16 - new_b_error * 3 / 16 - new_b_error * 5 / 16; } } else { // true color *tBits++ = bgra; } blue[tx] = green[tx] = red[tx] = alpha[tx] = 0; } tCharLine += tBytesPerRow; ty++; ycount = 0; yc -= h; } } while (ty < th); delete [] be; delete [] ge; delete [] re; delete [] blue; delete [] green; delete [] red; delete [] alpha; delete [] xcount; return thumbnail; } void abisoftButton::SaveInDirectoryFlag(bool flag) { SaveInDirectory = flag; } BBitmap * abisoftButton::GetPictureFileBitmap() { //do we have filedata saved in Preferences -- preferences not yet implemented! //or in Image Directory? //If no, then look in resources //if yes, return as bitmap //return NULL if we can't find one if (SaveInDirectory) { char buf[B_FILE_NAME_LENGTH +1]; sprintf(buf, "%s/%s", ImageDirectoryPath, button_name); BFile readFile(buf, B_READ_ONLY); if (readFile.InitCheck() == B_NO_ERROR) { return GetBitmap(picFileName); } } BFile AppFile(&ai.ref, B_READ_ONLY); BResources rFile(&AppFile); size_t size; void *ptr; if (ptr = rFile.FindResource('BTPA', button_name, &size)) { BMemoryIO input(ptr, size); BitmapStream output; if (DATATranslate(input, NULL, NULL, output, DATA_BITMAP)) { free(ptr); return NULL; } BBitmap *ret = NULL; if (output.DetachBitmap(ret)){ free(ptr); return NULL; } free(ptr); return ret; } return NULL; } void abisoftButton::FindSoundRef() { //do we have a soundfile in SoundDirectory or in //Preferences //if no, look in resources // if (SaveInDirectory) { char buf[B_FILE_NAME_LENGTH +1]; sprintf(buf, "%s/%s", SoundDirectoryPath, button_name); BEntry sRef(buf); BFile tfile(&sRef, B_READ_ONLY); if (tfile.IsReadable()) { entry_ref ref; status_t rc = sRef.GetRef(&ref); if (rc == B_NO_ERROR) { SoundRef = ref; DoSound = true; return; } } } //look in resources BFile AppFile(&ai.ref, B_READ_ONLY); BResources rFile(&AppFile); size_t size; char *ptr; if (ptr = (char *) rFile.FindResource('SFXA', button_name, &size)) { BFile newFile; SoundDirectory.CreateFile(button_name, &newFile); ssize_t bytesWrite = newFile.Write(ptr, size); free(ptr); if (bytesWrite == size ) { char buf[B_FILE_NAME_LENGTH +1]; sprintf(buf, "%s/%s", SoundDirectoryPath, button_name); int rc = get_ref_for_path(buf, &SoundRef); if (rc == B_NO_ERROR) DoSound = true; } } }