1 /*****************************************************************************/ 2 // BaseTranslator 3 // Written by Michael Wilber, OBOS Translation Kit Team 4 // 5 // BaseTranslator.cpp 6 // 7 // The BaseTranslator class implements functionality common to most 8 // Translators so that this functionality need not be implemented over and 9 // over in each Translator. 10 // 11 // 12 // Copyright (c) 2004 OpenBeOS Project 13 // 14 // Permission is hereby granted, free of charge, to any person obtaining a 15 // copy of this software and associated documentation files (the "Software"), 16 // to deal in the Software without restriction, including without limitation 17 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 // and/or sell copies of the Software, and to permit persons to whom the 19 // Software is furnished to do so, subject to the following conditions: 20 // 21 // The above copyright notice and this permission notice shall be included 22 // in all copies or substantial portions of the Software. 23 // 24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30 // DEALINGS IN THE SOFTWARE. 31 /*****************************************************************************/ 32 33 #include <string.h> 34 #include <stdio.h> 35 #include "BaseTranslator.h" 36 37 // --------------------------------------------------------------- 38 // Constructor 39 // 40 // Sets up the version info and the name of the translator so that 41 // these values can be returned when they are requested. 42 // 43 // Preconditions: 44 // 45 // Parameters: 46 // 47 // Postconditions: 48 // 49 // Returns: 50 // --------------------------------------------------------------- 51 BaseTranslator::BaseTranslator(const char *name, const char *info, 52 const int32 version, const translation_format *inFormats, 53 int32 inCount, const translation_format *outFormats, int32 outCount, 54 const char *settingsFile, TranSetting *defaults, int32 defCount, 55 uint32 tranGroup, uint32 tranType) 56 : BTranslator() 57 { 58 fSettings = new TranslatorSettings(settingsFile, defaults, defCount); 59 fSettings->LoadSettings(); 60 // load settings from the Base Translator settings file 61 62 fVersion = version; 63 fName = new char[strlen(name) + 1]; 64 strcpy(fName, name); 65 fInfo = new char[strlen(info) + 41]; 66 sprintf(fInfo, "%s v%d.%d.%d %s", info, 67 static_cast<int>(B_TRANSLATION_MAJOR_VER(fVersion)), 68 static_cast<int>(B_TRANSLATION_MINOR_VER(fVersion)), 69 static_cast<int>(B_TRANSLATION_REVSN_VER(fVersion)), 70 __DATE__); 71 72 fInputFormats = inFormats; 73 fInputCount = (fInputFormats) ? inCount : 0; 74 fOutputFormats = outFormats; 75 fOutputCount = (fOutputFormats) ? outCount : 0; 76 fTranGroup = tranGroup; 77 fTranType = tranType; 78 } 79 80 // --------------------------------------------------------------- 81 // Destructor 82 // 83 // Does nothing 84 // 85 // Preconditions: 86 // 87 // Parameters: 88 // 89 // Postconditions: 90 // 91 // Returns: 92 // --------------------------------------------------------------- 93 // 94 // NOTE: It may be the case, that under Be's libtranslation.so, 95 // that this destructor will never be called 96 BaseTranslator::~BaseTranslator() 97 { 98 fSettings->Release(); 99 delete[] fName; 100 delete[] fInfo; 101 } 102 103 // --------------------------------------------------------------- 104 // TranslatorName 105 // 106 // Returns the short name of the translator. 107 // 108 // Preconditions: 109 // 110 // Parameters: 111 // 112 // Postconditions: 113 // 114 // Returns: a const char * to the short name of the translator 115 // --------------------------------------------------------------- 116 const char * 117 BaseTranslator::TranslatorName() const 118 { 119 return fName; 120 } 121 122 // --------------------------------------------------------------- 123 // TranslatorInfo 124 // 125 // Returns a more verbose name for the translator than the one 126 // TranslatorName() returns. This usually includes version info. 127 // 128 // Preconditions: 129 // 130 // Parameters: 131 // 132 // Postconditions: 133 // 134 // Returns: a const char * to the verbose name of the translator 135 // --------------------------------------------------------------- 136 const char * 137 BaseTranslator::TranslatorInfo() const 138 { 139 return fInfo; 140 } 141 142 // --------------------------------------------------------------- 143 // TranslatorVersion 144 // 145 // Returns the integer representation of the current version of 146 // this translator. 147 // 148 // Preconditions: 149 // 150 // Parameters: 151 // 152 // Postconditions: 153 // 154 // Returns: 155 // --------------------------------------------------------------- 156 int32 157 BaseTranslator::TranslatorVersion() const 158 { 159 return fVersion; 160 } 161 162 // --------------------------------------------------------------- 163 // InputFormats 164 // 165 // Returns a list of input formats supported by this translator. 166 // 167 // Preconditions: 168 // 169 // Parameters: out_count, The number of input formats 170 // support is returned here. 171 // 172 // Postconditions: 173 // 174 // Returns: the array of input formats and the number of input 175 // formats through the out_count parameter 176 // --------------------------------------------------------------- 177 const translation_format * 178 BaseTranslator::InputFormats(int32 *out_count) const 179 { 180 if (out_count) { 181 *out_count = fInputCount; 182 return fInputFormats; 183 } else 184 return NULL; 185 } 186 187 // --------------------------------------------------------------- 188 // OutputFormats 189 // 190 // Returns a list of output formats supported by this translator. 191 // 192 // Preconditions: 193 // 194 // Parameters: out_count, The number of output formats 195 // support is returned here. 196 // 197 // Postconditions: 198 // 199 // Returns: the array of output formats and the number of output 200 // formats through the out_count parameter 201 // --------------------------------------------------------------- 202 const translation_format * 203 BaseTranslator::OutputFormats(int32 *out_count) const 204 { 205 if (out_count) { 206 *out_count = fOutputCount; 207 return fOutputFormats; 208 } else 209 return NULL; 210 } 211 212 // --------------------------------------------------------------- 213 // identify_bits_header 214 // 215 // Determines if the data in inSource is in the 216 // B_TRANSLATOR_BITMAP ('bits') format. If it is, it returns 217 // info about the data in inSource to outInfo and pheader. 218 // 219 // Preconditions: 220 // 221 // Parameters: inSource, The source of the image data 222 // 223 // outInfo, Information about the translator 224 // is copied here 225 // 226 // amtread, Amount of data read from inSource 227 // before this function was called 228 // 229 // read, Pointer to the data that was read 230 // in before this function was called 231 // 232 // pheader, The bits header is copied here after 233 // it is read in from inSource 234 // 235 // Postconditions: 236 // 237 // Returns: B_NO_TRANSLATOR, if the data does not look like 238 // bits format data 239 // 240 // B_ERROR, if the header data could not be converted to host 241 // format 242 // 243 // B_OK, if the data looks like bits data and no errors were 244 // encountered 245 // --------------------------------------------------------------- 246 status_t 247 BaseTranslator::identify_bits_header(BPositionIO *inSource, 248 translator_info *outInfo, TranslatorBitmap *pheader = NULL) 249 { 250 TranslatorBitmap header; 251 252 // read in the header 253 ssize_t size = sizeof(TranslatorBitmap); 254 if (inSource->Read( 255 (reinterpret_cast<uint8 *> (&header)), size) != size) 256 return B_NO_TRANSLATOR; 257 258 // convert to host byte order 259 if (swap_data(B_UINT32_TYPE, &header, sizeof(TranslatorBitmap), 260 B_SWAP_BENDIAN_TO_HOST) != B_OK) 261 return B_ERROR; 262 263 // check if header values are reasonable 264 if (header.colors != B_RGB32 && 265 header.colors != B_RGB32_BIG && 266 header.colors != B_RGBA32 && 267 header.colors != B_RGBA32_BIG && 268 header.colors != B_RGB24 && 269 header.colors != B_RGB24_BIG && 270 header.colors != B_RGB16 && 271 header.colors != B_RGB16_BIG && 272 header.colors != B_RGB15 && 273 header.colors != B_RGB15_BIG && 274 header.colors != B_RGBA15 && 275 header.colors != B_RGBA15_BIG && 276 header.colors != B_CMAP8 && 277 header.colors != B_GRAY8 && 278 header.colors != B_GRAY1 && 279 header.colors != B_CMYK32 && 280 header.colors != B_CMY32 && 281 header.colors != B_CMYA32 && 282 header.colors != B_CMY24) 283 return B_NO_TRANSLATOR; 284 if (header.rowBytes * (header.bounds.Height() + 1) != header.dataSize) 285 return B_NO_TRANSLATOR; 286 287 if (outInfo) { 288 outInfo->type = B_TRANSLATOR_BITMAP; 289 outInfo->group = B_TRANSLATOR_BITMAP; 290 outInfo->quality = 0.2; 291 outInfo->capability = 0.2; 292 strcpy(outInfo->name, "Be Bitmap Format"); 293 strcpy(outInfo->MIME, "image/x-be-bitmap"); 294 295 // Look for quality / capability info in fInputFormats 296 for (int32 i = 0; i < fInputCount; i++) { 297 if (fInputFormats[i].type == B_TRANSLATOR_BITMAP && 298 fInputFormats[i].group == B_TRANSLATOR_BITMAP) { 299 outInfo->quality = fInputFormats[i].quality; 300 outInfo->capability = fInputFormats[i].capability; 301 strcpy(outInfo->name, fInputFormats[i].name); 302 break; 303 } 304 } 305 } 306 307 if (pheader) { 308 pheader->magic = header.magic; 309 pheader->bounds = header.bounds; 310 pheader->rowBytes = header.rowBytes; 311 pheader->colors = header.colors; 312 pheader->dataSize = header.dataSize; 313 } 314 315 return B_OK; 316 } 317 318 // --------------------------------------------------------------- 319 // BitsCheck 320 // 321 // Examines the input stream for B_TRANSLATOR_BITMAP format 322 // information and determines if BaseTranslator can handle 323 // the translation entirely, if it must pass the task of 324 // translation to the derived translator or if the stream cannot 325 // be decoded by the BaseTranslator or the derived translator. 326 // 327 // Preconditions: 328 // 329 // Parameters: inSource, where the data to examine is 330 // 331 // ioExtension, configuration settings for the 332 // translator 333 // 334 // outType, The format that the user wants 335 // the data in inSource to be 336 // converted to. NOTE: This is passed by 337 // reference so that it can modify the 338 // outType that is seen by the 339 // BaseTranslator and the derived 340 // translator 341 // 342 // Postconditions: 343 // 344 // Returns: B_NO_TRANSLATOR, if this translator can't handle 345 // the data in inSource 346 // 347 // B_ERROR, if there was an error converting the data to the host 348 // format 349 // 350 // B_BAD_VALUE, if the settings in ioExtension are bad 351 // 352 // B_OK, if this translator understand the data and there were 353 // no errors found 354 // --------------------------------------------------------------- 355 status_t 356 BaseTranslator::BitsCheck(BPositionIO *inSource, BMessage *ioExtension, 357 uint32 &outType) 358 { 359 if (!outType) 360 outType = B_TRANSLATOR_BITMAP; 361 if (outType != B_TRANSLATOR_BITMAP && outType != fTranType) 362 return B_NO_TRANSLATOR; 363 364 // Convert the magic numbers to the various byte orders so that 365 // I won't have to convert the data read in to see whether or not 366 // it is a supported type 367 const uint32 kBitsMagic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP); 368 369 // Read in the magic number and determine if it 370 // is a supported type 371 uint8 ch[4]; 372 if (inSource->Read(ch, 4) != 4) 373 return B_NO_TRANSLATOR; 374 inSource->Seek(-4, SEEK_CUR); 375 // seek backward becuase functions used after this one 376 // expect the stream to be at the beginning 377 378 // Read settings from ioExtension 379 if (ioExtension && fSettings->LoadSettings(ioExtension) < B_OK) 380 return B_BAD_VALUE; 381 382 uint32 sourceMagic; 383 memcpy(&sourceMagic, ch, sizeof(uint32)); 384 if (sourceMagic == kBitsMagic) 385 return B_OK; 386 else 387 return B_OK + 1; 388 } 389 390 status_t 391 BaseTranslator::BitsIdentify(BPositionIO *inSource, 392 const translation_format *inFormat, BMessage *ioExtension, 393 translator_info *outInfo, uint32 outType) 394 { 395 status_t result; 396 397 result = BitsCheck(inSource, ioExtension, outType); 398 if (result == B_OK) 399 result = identify_bits_header(inSource, outInfo); 400 else if (result == B_OK + 1) 401 // if NOT B_TRANSLATOR_BITMAP, it could be an image in the 402 // derived format 403 result = DerivedIdentify(inSource, inFormat, ioExtension, 404 outInfo, outType); 405 406 return result; 407 } 408 409 // --------------------------------------------------------------- 410 // Identify 411 // 412 // Examines the data from inSource and determines if it is in a 413 // format that this translator knows how to work with. 414 // 415 // Preconditions: 416 // 417 // Parameters: inSource, where the data to examine is 418 // 419 // inFormat, a hint about the data in inSource, 420 // it is ignored since it is only a hint 421 // 422 // ioExtension, configuration settings for the 423 // translator 424 // 425 // outInfo, information about what data is in 426 // inSource and how well this translator 427 // can handle that data is stored here 428 // 429 // outType, The format that the user wants 430 // the data in inSource to be 431 // converted to 432 // 433 // Postconditions: 434 // 435 // Returns: B_NO_TRANSLATOR, if this translator can't handle 436 // the data in inSource 437 // 438 // B_ERROR, if there was an error converting the data to the host 439 // format 440 // 441 // B_BAD_VALUE, if the settings in ioExtension are bad 442 // 443 // B_OK, if this translator understand the data and there were 444 // no errors found 445 // --------------------------------------------------------------- 446 status_t 447 BaseTranslator::Identify(BPositionIO *inSource, 448 const translation_format *inFormat, BMessage *ioExtension, 449 translator_info *outInfo, uint32 outType) 450 { 451 switch (fTranGroup) { 452 case B_TRANSLATOR_BITMAP: 453 return BitsIdentify(inSource, inFormat, ioExtension, 454 outInfo, outType); 455 456 default: 457 return DerivedIdentify(inSource, inFormat, ioExtension, 458 outInfo, outType); 459 } 460 } 461 462 // --------------------------------------------------------------- 463 // translate_from_bits_to_bits 464 // 465 // Convert the data in inSource from the Be Bitmap format ('bits') 466 // to the format specified in outType (either bits or Base). 467 // 468 // Preconditions: 469 // 470 // Parameters: inSource, the bits data to translate 471 // 472 // amtread, the amount of data already read from 473 // inSource 474 // 475 // read, pointer to the data already read from 476 // inSource 477 // 478 // outType, the type of data to convert to 479 // 480 // outDestination, where the output is written to 481 // 482 // Postconditions: 483 // 484 // Returns: B_NO_TRANSLATOR, if the data is not in a supported 485 // format 486 // 487 // B_ERROR, if there was an error allocating memory or some other 488 // error 489 // 490 // B_OK, if successfully translated the data from the bits format 491 // --------------------------------------------------------------- 492 status_t 493 BaseTranslator::translate_from_bits_to_bits(BPositionIO *inSource, 494 uint32 outType, BPositionIO *outDestination) 495 { 496 TranslatorBitmap bitsHeader; 497 bool bheaderonly = false, bdataonly = false; 498 499 status_t result; 500 result = identify_bits_header(inSource, NULL, &bitsHeader); 501 if (result != B_OK) 502 return result; 503 504 // Translate B_TRANSLATOR_BITMAP to B_TRANSLATOR_BITMAP, easy enough :) 505 if (outType == B_TRANSLATOR_BITMAP) { 506 // write out bitsHeader (only if configured to) 507 if (bheaderonly || (!bheaderonly && !bdataonly)) { 508 if (swap_data(B_UINT32_TYPE, &bitsHeader, 509 sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) 510 return B_ERROR; 511 if (outDestination->Write(&bitsHeader, 512 sizeof(TranslatorBitmap)) != sizeof(TranslatorBitmap)) 513 return B_ERROR; 514 } 515 516 // write out the data (only if configured to) 517 if (bdataonly || (!bheaderonly && !bdataonly)) { 518 uint8 buf[1024]; 519 uint32 remaining = B_BENDIAN_TO_HOST_INT32(bitsHeader.dataSize); 520 ssize_t rd, writ; 521 rd = inSource->Read(buf, 1024); 522 while (rd > 0) { 523 writ = outDestination->Write(buf, rd); 524 if (writ < 0) 525 break; 526 remaining -= static_cast<uint32>(writ); 527 rd = inSource->Read(buf, min(1024, remaining)); 528 } 529 530 if (remaining > 0) 531 return B_ERROR; 532 else 533 return B_OK; 534 } else 535 return B_OK; 536 537 } else 538 return B_NO_TRANSLATOR; 539 } 540 541 status_t 542 BaseTranslator::BitsTranslate(BPositionIO *inSource, 543 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 544 BPositionIO *outDestination) 545 { 546 status_t result; 547 548 result = BitsCheck(inSource, ioExtension, outType); 549 if (result == B_OK && outType == B_TRANSLATOR_BITMAP) 550 result = translate_from_bits_to_bits(inSource, outType, 551 outDestination); 552 else if (result >= B_OK) 553 // If NOT B_TRANSLATOR_BITMAP type it could be the derived format 554 result = DerivedTranslate(inSource, inInfo, ioExtension, outType, 555 outDestination, (result == B_OK)); 556 557 return result; 558 } 559 560 // --------------------------------------------------------------- 561 // Translate 562 // 563 // Translates the data in inSource to the type outType and stores 564 // the translated data in outDestination. 565 // 566 // Preconditions: 567 // 568 // Parameters: inSource, the data to be translated 569 // 570 // inInfo, hint about the data in inSource (not used) 571 // 572 // ioExtension, configuration options for the 573 // translator 574 // 575 // outType, the type to convert inSource to 576 // 577 // outDestination, where the translated data is 578 // put 579 // 580 // Postconditions: 581 // 582 // Returns: B_BAD_VALUE, if the options in ioExtension are bad 583 // 584 // B_NO_TRANSLATOR, if this translator doesn't understand the data 585 // 586 // B_ERROR, if there was an error allocating memory or converting 587 // data 588 // 589 // B_OK, if all went well 590 // --------------------------------------------------------------- 591 status_t 592 BaseTranslator::Translate(BPositionIO *inSource, 593 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 594 BPositionIO *outDestination) 595 { 596 switch (fTranGroup) { 597 case B_TRANSLATOR_BITMAP: 598 return BitsTranslate(inSource, inInfo, ioExtension, outType, 599 outDestination); 600 601 default: 602 return DerivedTranslate(inSource, inInfo, ioExtension, outType, 603 outDestination, -1); 604 } 605 } 606 607 // returns the current translator settings into ioExtension 608 status_t 609 BaseTranslator::GetConfigurationMessage(BMessage *ioExtension) 610 { 611 return fSettings->GetConfigurationMessage(ioExtension); 612 } 613 614 // --------------------------------------------------------------- 615 // MakeConfigurationView 616 // 617 // Makes a BView object for configuring / displaying info about 618 // this translator. 619 // 620 // Preconditions: 621 // 622 // Parameters: ioExtension, configuration options for the 623 // translator 624 // 625 // outView, the view to configure the 626 // translator is stored here 627 // 628 // outExtent, the bounds of the view are 629 // stored here 630 // 631 // Postconditions: 632 // 633 // Returns: 634 // --------------------------------------------------------------- 635 status_t 636 BaseTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, 637 BRect *outExtent) 638 { 639 if (!outView || !outExtent) 640 return B_BAD_VALUE; 641 if (ioExtension && fSettings->LoadSettings(ioExtension) != B_OK) 642 return B_BAD_VALUE; 643 644 BView *view = NewConfigView(AcquireSettings()); 645 // implemented in derived class 646 if (view) { 647 *outView = view; 648 *outExtent = view->Bounds(); 649 650 return B_OK; 651 } else 652 return BTranslator::MakeConfigurationView(ioExtension, outView, 653 outExtent); 654 } 655 656 TranslatorSettings * 657 BaseTranslator::AcquireSettings() 658 { 659 return fSettings->Acquire(); 660 } 661 662 /////////////////////////////////////////////////////////// 663 // Functions to be implemented by derived classes 664 665 status_t 666 BaseTranslator::DerivedIdentify(BPositionIO *inSource, 667 const translation_format *inFormat, BMessage *ioExtension, 668 translator_info *outInfo, uint32 outType) 669 { 670 return B_NO_TRANSLATOR; 671 } 672 673 status_t 674 BaseTranslator::DerivedTranslate(BPositionIO *inSource, 675 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 676 BPositionIO *outDestination, int32 baseType) 677 { 678 return B_NO_TRANSLATOR; 679 } 680 681 682 BView * 683 BaseTranslator::NewConfigView(TranslatorSettings *settings) 684 { 685 return NULL; 686 } 687 688 void 689 translate_direct_copy(BPositionIO *inSource, BPositionIO *outDestination) 690 { 691 const size_t kbufsize = 2048; 692 uint8 buffer[kbufsize]; 693 ssize_t ret = inSource->Read(buffer, kbufsize); 694 while (ret > 0) { 695 outDestination->Write(buffer, ret); 696 ret = inSource->Read(buffer, kbufsize); 697 } 698 } 699