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