1 /*****************************************************************************/ 2 // SGITranslator 3 // Written by Stephan Aßmus 4 // based on TIFFTranslator written mostly by 5 // Michael Wilber 6 // 7 // SGITranslator.cpp 8 // 9 // This BTranslator based object is for opening and writing 10 // SGI images. 11 // 12 // 13 // Copyright (c) 2003-2006 Haiku Project 14 // 15 // Permission is hereby granted, free of charge, to any person obtaining a 16 // copy of this software and associated documentation files (the "Software"), 17 // to deal in the Software without restriction, including without limitation 18 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 19 // and/or sell copies of the Software, and to permit persons to whom the 20 // Software is furnished to do so, subject to the following conditions: 21 // 22 // The above copyright notice and this permission notice shall be included 23 // in all copies or substantial portions of the Software. 24 // 25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 26 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 30 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31 // DEALINGS IN THE SOFTWARE. 32 /*****************************************************************************/ 33 // 34 // How this works: 35 // 36 // libtiff has a special version of SGIOpen() that gets passed custom 37 // functions for reading writing etc. and a handle. This handle in our case 38 // is a BPositionIO object, which libtiff passes on to the functions for reading 39 // writing etc. So when operations are performed on the SGI* handle that is 40 // returned by SGIOpen(), libtiff uses the special reading writing etc 41 // functions so that all stream io happens on the BPositionIO object. 42 43 #include <new> 44 #include <stdio.h> 45 #include <string.h> 46 47 #include <OS.h> 48 49 #include "SGIImage.h" 50 #include "SGITranslator.h" 51 #include "SGIView.h" 52 53 using std::nothrow; 54 55 // The input formats that this translator supports. 56 translation_format gInputFormats[] = { 57 { 58 B_TRANSLATOR_BITMAP, 59 B_TRANSLATOR_BITMAP, 60 BBT_IN_QUALITY, 61 BBT_IN_CAPABILITY, 62 "image/x-be-bitmap", 63 "Be Bitmap Format (SGITranslator)" 64 }, 65 { 66 SGI_FORMAT, 67 B_TRANSLATOR_BITMAP, 68 SGI_IN_QUALITY, 69 SGI_IN_CAPABILITY, 70 "image/sgi", 71 "SGI image" 72 } 73 }; 74 75 // The output formats that this translator supports. 76 translation_format gOutputFormats[] = { 77 { 78 B_TRANSLATOR_BITMAP, 79 B_TRANSLATOR_BITMAP, 80 BBT_OUT_QUALITY, 81 BBT_OUT_CAPABILITY, 82 "image/x-be-bitmap", 83 "Be Bitmap Format (SGITranslator)" 84 }, 85 { 86 SGI_FORMAT, 87 B_TRANSLATOR_BITMAP, 88 SGI_OUT_QUALITY, 89 SGI_OUT_CAPABILITY, 90 "image/sgi", 91 "SGI image" 92 } 93 }; 94 95 // Default settings for the Translator 96 TranSetting gDefaultSettings[] = { 97 {B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false}, 98 {B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false}, 99 {SGI_SETTING_COMPRESSION, TRAN_SETTING_INT32, SGI_COMP_RLE} 100 // compression is set to RLE by default 101 }; 102 103 // --------------------------------------------------------------- 104 // make_nth_translator 105 // 106 // Creates a SGITranslator object to be used by BTranslatorRoster 107 // 108 // Preconditions: 109 // 110 // Parameters: n, The translator to return. Since 111 // SGITranslator only publishes one 112 // translator, it only returns a 113 // SGITranslator if n == 0 114 // 115 // you, The image_id of the add-on that 116 // contains code (not used). 117 // 118 // flags, Has no meaning yet, should be 0. 119 // 120 // Postconditions: 121 // 122 // Returns: NULL if n is not zero, 123 // a new SGITranslator if n is zero 124 // --------------------------------------------------------------- 125 BTranslator * 126 make_nth_translator(int32 n, image_id you, uint32 flags, ...) 127 { 128 if (!n) 129 return new SGITranslator(); 130 else 131 return NULL; 132 } 133 134 // --------------------------------------------------------------- 135 // Constructor 136 // 137 // Sets up the version info and the name of the translator so that 138 // these values can be returned when they are requested. 139 // 140 // Preconditions: 141 // 142 // Parameters: 143 // 144 // Postconditions: 145 // 146 // Returns: 147 // --------------------------------------------------------------- 148 SGITranslator::SGITranslator() 149 : BaseTranslator("SGI Images", "SGI image translator", 150 SGI_TRANSLATOR_VERSION, 151 gInputFormats, sizeof(gInputFormats) / sizeof(translation_format), 152 gOutputFormats, sizeof(gOutputFormats) / sizeof(translation_format), 153 "SGITranslator_Settings", 154 gDefaultSettings, sizeof(gDefaultSettings) / sizeof(TranSetting), 155 B_TRANSLATOR_BITMAP, SGI_FORMAT) 156 { 157 } 158 159 // --------------------------------------------------------------- 160 // Destructor 161 // 162 // Does nothing 163 // 164 // Preconditions: 165 // 166 // Parameters: 167 // 168 // Postconditions: 169 // 170 // Returns: 171 // --------------------------------------------------------------- 172 SGITranslator::~SGITranslator() 173 { 174 } 175 176 status_t 177 identify_sgi_header(BPositionIO *inSource, translator_info *outInfo, uint32 outType, 178 SGIImage **poutSGIImage = NULL) 179 { 180 status_t status = B_NO_MEMORY; 181 // construct new SGIImage object and set it to the provided BPositionIO 182 SGIImage* sgiImage = new(nothrow) SGIImage(); 183 if (sgiImage) 184 status = sgiImage->SetTo(inSource); 185 186 if (status >= B_OK) { 187 if (outInfo) { 188 outInfo->type = SGI_FORMAT; 189 outInfo->group = B_TRANSLATOR_BITMAP; 190 outInfo->quality = SGI_IN_QUALITY; 191 outInfo->capability = SGI_IN_CAPABILITY; 192 strcpy(outInfo->MIME, "image/sgi"); 193 strcpy(outInfo->name, "SGI image"); 194 } 195 } else { 196 delete sgiImage; 197 sgiImage = NULL; 198 } 199 if (!poutSGIImage) 200 // close SGIImage if caller is not interested in SGIImage handle 201 delete sgiImage; 202 else 203 // leave SGIImage open (if it is) and return handle if caller needs it 204 *poutSGIImage = sgiImage; 205 206 return status; 207 } 208 209 // --------------------------------------------------------------- 210 // DerivedIdentify 211 // 212 // Examines the data from inSource and determines if it is in a 213 // format that this translator knows how to work with. 214 // 215 // Preconditions: 216 // 217 // Parameters: inSource, where the data to examine is 218 // 219 // inFormat, a hint about the data in inSource, 220 // it is ignored since it is only a hint 221 // 222 // ioExtension, configuration settings for the 223 // translator (not used) 224 // 225 // outInfo, information about what data is in 226 // inSource and how well this translator 227 // can handle that data is stored here 228 // 229 // outType, The format that the user wants 230 // the data in inSource to be 231 // converted to 232 // 233 // Postconditions: 234 // 235 // Returns: B_NO_TRANSLATOR, if this translator can't handle 236 // the data in inSource 237 // 238 // B_ERROR, if there was an error converting the data to the host 239 // format 240 // 241 // B_BAD_VALUE, if the settings in ioExtension are bad 242 // 243 // B_OK, if this translator understood the data and there were 244 // no errors found 245 // 246 // Other errors if BPositionIO::Read() returned an error value 247 // --------------------------------------------------------------- 248 status_t 249 SGITranslator::DerivedIdentify(BPositionIO *inSource, 250 const translation_format *inFormat, BMessage *ioExtension, 251 translator_info *outInfo, uint32 outType) 252 { 253 return identify_sgi_header(inSource, outInfo, outType); 254 } 255 256 // translate_from_bits 257 status_t 258 SGITranslator::translate_from_bits(BPositionIO *inSource, uint32 outType, 259 BPositionIO *outDestination) 260 { 261 TranslatorBitmap bitsHeader; 262 263 uint32 compression = fSettings->SetGetInt32(SGI_SETTING_COMPRESSION); 264 265 status_t ret = identify_bits_header(inSource, NULL, &bitsHeader); 266 if (ret < B_OK) 267 return ret; 268 269 // Translate B_TRANSLATOR_BITMAP to SGI_FORMAT 270 if (outType == SGI_FORMAT) { 271 272 // common fields which are independent of the bitmap format 273 uint32 width = bitsHeader.bounds.IntegerWidth() + 1; 274 uint32 height = bitsHeader.bounds.IntegerHeight() + 1; 275 uint32 bytesPerRow = bitsHeader.rowBytes; 276 uint32 bytesPerChannel = 1; 277 color_space format = bitsHeader.colors; 278 279 uint32 channelCount; 280 switch (format) { 281 case B_GRAY8: 282 channelCount = 1; 283 break; 284 case B_RGB32: 285 case B_RGB32_BIG: 286 case B_RGB24: 287 case B_RGB24_BIG: 288 channelCount = 3; 289 break; 290 case B_RGBA32: 291 case B_RGBA32_BIG: 292 channelCount = 4; 293 break; 294 default: 295 return B_NO_TRANSLATOR; 296 } 297 298 // Set up SGI header 299 SGIImage* sgiImage = new SGIImage(); 300 status_t ret = sgiImage->SetTo(outDestination, width, height, 301 channelCount, bytesPerChannel, compression); 302 if (ret >= B_OK) { 303 // read one row at a time, 304 // convert to the correct format 305 // and write out the results 306 307 // SGI Images store each channel separately 308 // a buffer is allocated big enough to hold all channels 309 // then the pointers are assigned with offsets into that buffer 310 uint8** rows = new(nothrow) uint8*[channelCount]; 311 if (rows) 312 rows[0] = new(nothrow) uint8[width * channelCount * bytesPerChannel]; 313 // rowBuffer is going to hold the converted data 314 uint8* rowBuffer = new(nothrow) uint8[bytesPerRow]; 315 if (rows && rows[0] && rowBuffer) { 316 // assign the other pointers (channel offsets in row buffer) 317 for (uint32 i = 1; i < channelCount; i++) 318 rows[i] = rows[0] + i * width; 319 // loop through all lines of the image 320 for (int32 y = height - 1; y >= 0 && ret >= B_OK; y--) { 321 322 ret = inSource->Read(rowBuffer, bytesPerRow); 323 // see if an error happened while reading 324 if (ret < B_OK) 325 break; 326 // convert to native format (big endian) 327 switch (format) { 328 case B_GRAY8: { 329 uint8* src = rowBuffer; 330 for (uint32 x = 0; x < width; x++) { 331 rows[0][x] = src[0]; 332 src += 1; 333 } 334 break; 335 } 336 case B_RGB24: { 337 uint8* src = rowBuffer; 338 for (uint32 x = 0; x < width; x++) { 339 rows[0][x] = src[2]; 340 rows[1][x] = src[1]; 341 rows[2][x] = src[0]; 342 src += 3; 343 } 344 break; 345 } 346 case B_RGB24_BIG: { 347 uint8* src = rowBuffer; 348 for (uint32 x = 0; x < width; x++) { 349 rows[0][x] = src[0]; 350 rows[1][x] = src[1]; 351 rows[2][x] = src[2]; 352 src += 3; 353 } 354 break; 355 } 356 case B_RGB32: { 357 uint8* src = rowBuffer; 358 for (uint32 x = 0; x < width; x++) { 359 rows[0][x] = src[2]; 360 rows[1][x] = src[1]; 361 rows[2][x] = src[0]; 362 // ignore src[3] 363 src += 4; 364 } 365 break; 366 } 367 case B_RGB32_BIG: { 368 uint8* src = rowBuffer; 369 for (uint32 x = 0; x < width; x++) { 370 rows[0][x] = src[1]; 371 rows[1][x] = src[2]; 372 rows[2][x] = src[3]; 373 // ignore src[0] 374 src += 4; 375 } 376 break; 377 } 378 case B_RGBA32: { 379 uint8* src = rowBuffer; 380 for (uint32 x = 0; x < width; x++) { 381 rows[0][x] = src[2]; 382 rows[1][x] = src[1]; 383 rows[2][x] = src[0]; 384 rows[3][x] = src[3]; 385 src += 4; 386 } 387 break; 388 } 389 case B_RGBA32_BIG: { 390 uint8* src = rowBuffer; 391 for (uint32 x = 0; x < width; x++) { 392 rows[0][x] = src[1]; 393 rows[1][x] = src[2]; 394 rows[2][x] = src[3]; 395 rows[3][x] = src[0]; 396 src += 4; 397 } 398 break; 399 } 400 default: 401 // cannot be here 402 break; 403 } // switch (format) 404 405 // for each channel, write a row buffer 406 for (uint32 z = 0; z < channelCount; z++) { 407 ret = sgiImage->WriteRow(rows[z], y, z); 408 if (ret < B_OK) { 409 printf("WriteRow() returned %s!\n", strerror(ret)); 410 break; 411 } 412 } 413 414 } // for (uint32 y = 0; y < height && ret >= B_OK; y++) 415 if (ret >= B_OK) 416 ret = B_OK; 417 } else // if (rows && rows[0] && rowBuffer) 418 ret = B_NO_MEMORY; 419 420 delete[] rows[0]; 421 delete[] rows; 422 delete[] rowBuffer; 423 } 424 425 // done with the SGIImage object 426 delete sgiImage; 427 428 return ret; 429 } 430 return B_NO_TRANSLATOR; 431 } 432 433 // translate_from_sgi 434 status_t 435 SGITranslator::translate_from_sgi(BPositionIO *inSource, uint32 outType, 436 BPositionIO *outDestination) 437 { 438 status_t ret = B_NO_TRANSLATOR; 439 440 // if copying SGI_FORMAT to SGI_FORMAT 441 if (outType == SGI_FORMAT) { 442 translate_direct_copy(inSource, outDestination); 443 return B_OK; 444 } 445 446 // variables needing cleanup 447 SGIImage* sgiImage = NULL; 448 449 ret = identify_sgi_header(inSource, NULL, outType, &sgiImage); 450 451 if (ret >= B_OK) { 452 453 bool bheaderonly = false, bdataonly = false; 454 455 uint32 width = sgiImage->Width(); 456 uint32 height = sgiImage->Height(); 457 uint32 channelCount = sgiImage->CountChannels(); 458 color_space format = B_RGBA32; 459 uint32 bytesPerRow = 0; 460 uint32 bytesPerChannel = sgiImage->BytesPerChannel(); 461 462 if (channelCount == 1) { 463 // format = B_GRAY8; // this format is not supported by most applications 464 // bytesPerRow = width; 465 format = B_RGB32; 466 bytesPerRow = width * 4; 467 } else if (channelCount == 2) { 468 // means gray (luminance) + alpha, we convert that to B_RGBA32 469 format = B_RGBA32; 470 bytesPerRow = width * 4; 471 } else if (channelCount == 3) { 472 format = B_RGB32; // should be B_RGB24, but let's not push it too hard... 473 bytesPerRow = width * 4; 474 } else if (channelCount == 4) { 475 format = B_RGBA32; 476 bytesPerRow = width * 4; 477 } else 478 ret = B_NO_TRANSLATOR; // we cannot handle this image 479 480 if (ret >= B_OK && !bdataonly) { 481 // Construct and write Be bitmap header 482 TranslatorBitmap bitsHeader; 483 bitsHeader.magic = B_TRANSLATOR_BITMAP; 484 bitsHeader.bounds.left = 0; 485 bitsHeader.bounds.top = 0; 486 bitsHeader.bounds.right = width - 1; 487 bitsHeader.bounds.bottom = height - 1; 488 bitsHeader.rowBytes = bytesPerRow; 489 bitsHeader.colors = format; 490 bitsHeader.dataSize = bitsHeader.rowBytes * height; 491 if ((ret = swap_data(B_UINT32_TYPE, &bitsHeader, 492 sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN)) < B_OK) { 493 return ret; 494 } else 495 ret = outDestination->Write(&bitsHeader, sizeof(TranslatorBitmap)); 496 } 497 if (ret < B_OK) 498 printf("error writing bits header: %s\n", strerror(ret)); 499 if (ret >= B_OK && !bheaderonly) { 500 // read one row at a time, 501 // convert to the correct format 502 // and write out the results 503 504 // SGI Images store each channel separately 505 // a buffer is allocated big enough to hold all channels 506 // then the pointers are assigned with offsets into that buffer 507 uint8** rows = new(nothrow) uint8*[channelCount]; 508 if (rows) 509 rows[0] = new(nothrow) uint8[width * channelCount * bytesPerChannel]; 510 // rowBuffer is going to hold the converted data 511 uint8* rowBuffer = new(nothrow) uint8[bytesPerRow]; 512 if (rows && rows[0] && rowBuffer) { 513 // assign the other pointers (channel offsets in row buffer) 514 for (uint32 i = 1; i < channelCount; i++) 515 rows[i] = rows[0] + i * width * bytesPerChannel; 516 // loop through all lines of the image 517 for (int32 y = height - 1; y >= 0 && ret >= B_OK; y--) { 518 // fill the row buffer with each channel 519 for (uint32 z = 0; z < channelCount; z++) { 520 ret = sgiImage->ReadRow(rows[z], y, z); 521 if (ret < B_OK) 522 break; 523 } 524 // see if an error happened while reading 525 if (ret < B_OK) 526 break; 527 // convert to native format (big endian) 528 if (bytesPerChannel == 1) { 529 switch (format) { 530 case B_GRAY8: { 531 uint8* dst = rowBuffer; 532 for (uint32 x = 0; x < width; x++) { 533 dst[0] = rows[0][x]; 534 dst += 1; 535 } 536 break; 537 } 538 case B_RGB24: { 539 uint8* dst = rowBuffer; 540 for (uint32 x = 0; x < width; x++) { 541 dst[0] = rows[2][x]; 542 dst[1] = rows[1][x]; 543 dst[2] = rows[0][x]; 544 dst += 3; 545 } 546 break; 547 } 548 case B_RGB32: { 549 uint8* dst = rowBuffer; 550 if (channelCount == 1) { 551 for (uint32 x = 0; x < width; x++) { 552 dst[0] = rows[0][x]; 553 dst[1] = rows[0][x]; 554 dst[2] = rows[0][x]; 555 dst[3] = 255; 556 dst += 4; 557 } 558 } else { 559 for (uint32 x = 0; x < width; x++) { 560 dst[0] = rows[2][x]; 561 dst[1] = rows[1][x]; 562 dst[2] = rows[0][x]; 563 dst[3] = 255; 564 dst += 4; 565 } 566 } 567 break; 568 } 569 case B_RGBA32: { 570 uint8* dst = rowBuffer; 571 if (channelCount == 2) { 572 for (uint32 x = 0; x < width; x++) { 573 dst[0] = rows[0][x]; 574 dst[1] = rows[0][x]; 575 dst[2] = rows[0][x]; 576 dst[3] = rows[1][x]; 577 dst += 4; 578 } 579 } else { 580 for (uint32 x = 0; x < width; x++) { 581 dst[0] = rows[2][x]; 582 dst[1] = rows[1][x]; 583 dst[2] = rows[0][x]; 584 dst[3] = rows[3][x]; 585 dst += 4; 586 } 587 } 588 break; 589 } 590 default: 591 // cannot be here 592 break; 593 } // switch (format) 594 ret = outDestination->Write(rowBuffer, bytesPerRow); 595 } else { 596 // support for 16 bits per channel images 597 uint16** rows16 = (uint16**)rows; 598 switch (format) { 599 case B_GRAY8: { 600 uint8* dst = rowBuffer; 601 for (uint32 x = 0; x < width; x++) { 602 dst[0] = rows16[0][x] >> 8; 603 dst += 1; 604 } 605 break; 606 } 607 case B_RGB24: { 608 uint8* dst = rowBuffer; 609 for (uint32 x = 0; x < width; x++) { 610 dst[0] = rows16[2][x] >> 8; 611 dst[1] = rows16[1][x] >> 8; 612 dst[2] = rows16[0][x] >> 8; 613 dst += 3; 614 } 615 break; 616 } 617 case B_RGB32: { 618 uint8* dst = rowBuffer; 619 if (channelCount == 1) { 620 for (uint32 x = 0; x < width; x++) { 621 dst[0] = rows16[0][x] >> 8; 622 dst[1] = rows16[0][x] >> 8; 623 dst[2] = rows16[0][x] >> 8; 624 dst[3] = 255; 625 dst += 4; 626 } 627 } else { 628 for (uint32 x = 0; x < width; x++) { 629 dst[0] = rows16[2][x] >> 8; 630 dst[1] = rows16[1][x] >> 8; 631 dst[2] = rows16[0][x] >> 8; 632 dst[3] = 255; 633 dst += 4; 634 } 635 } 636 break; 637 } 638 case B_RGBA32: { 639 uint8* dst = rowBuffer; 640 if (channelCount == 2) { 641 for (uint32 x = 0; x < width; x++) { 642 dst[0] = rows16[0][x] >> 8; 643 dst[1] = rows16[0][x] >> 8; 644 dst[2] = rows16[0][x] >> 8; 645 dst[3] = rows16[1][x] >> 8; 646 dst += 4; 647 } 648 } else { 649 for (uint32 x = 0; x < width; x++) { 650 dst[0] = rows16[2][x] >> 8; 651 dst[1] = rows16[1][x] >> 8; 652 dst[2] = rows16[0][x] >> 8; 653 dst[3] = rows16[3][x] >> 8; 654 dst += 4; 655 } 656 } 657 break; 658 } 659 default: 660 // cannot be here 661 break; 662 } // switch (format) 663 ret = outDestination->Write(rowBuffer, bytesPerRow); 664 } // 16 bit version 665 } // for (uint32 y = 0; y < height && ret >= B_OK; y++) 666 if (ret >= B_OK) 667 ret = B_OK; 668 } else // if (rows && rows[0] && rowBuffer) 669 ret = B_NO_MEMORY; 670 delete[] rows[0]; 671 delete[] rows; 672 delete[] rowBuffer; 673 } // if (ret >= B_OK && !bheaderonly) 674 } // if (ret >= B_OK) 675 delete sgiImage; 676 677 return ret; 678 } 679 680 // --------------------------------------------------------------- 681 // DerivedTranslate 682 // 683 // Translates the data in inSource to the type outType and stores 684 // the translated data in outDestination. 685 // 686 // Preconditions: 687 // 688 // Parameters: inSource, the data to be translated 689 // 690 // inInfo, hint about the data in inSource (not used) 691 // 692 // ioExtension, configuration options for the 693 // translator 694 // 695 // outType, the type to convert inSource to 696 // 697 // outDestination, where the translated data is 698 // put 699 // 700 // baseType, indicates whether inSource is in the 701 // bits format, not in the bits format or 702 // is unknown 703 // 704 // Postconditions: 705 // 706 // Returns: B_BAD_VALUE, if the options in ioExtension are bad 707 // 708 // B_NO_TRANSLATOR, if this translator doesn't understand the data 709 // 710 // B_ERROR, if there was an error allocating memory or converting 711 // data 712 // 713 // B_OK, if all went well 714 // --------------------------------------------------------------- 715 status_t 716 SGITranslator::DerivedTranslate(BPositionIO *inSource, 717 const translator_info *inInfo, BMessage *ioExtension, 718 uint32 outType, BPositionIO *outDestination, int32 baseType) 719 { 720 if (baseType == 1) 721 // if inSource is in bits format 722 return translate_from_bits(inSource, outType, outDestination); 723 else if (baseType == 0) 724 // if inSource is NOT in bits format 725 return translate_from_sgi(inSource, outType, outDestination); 726 else 727 // if BaseTranslator did not properly identify the data as 728 // bits or not bits 729 return B_NO_TRANSLATOR; 730 } 731 732 BView * 733 SGITranslator::NewConfigView(TranslatorSettings *settings) 734 { 735 return new SGIView(BRect(0, 0, 225, 175), "SGITranslator Settings", 736 B_FOLLOW_ALL, B_WILL_DRAW, settings); 737 } 738