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