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_TRANSLATION_CONTEXT 42 #define B_TRANSLATION_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 strlcpy(outInfo->name, B_TRANSLATE("Be Bitmap Format"), 309 sizeof(outInfo->name)); 310 strcpy(outInfo->MIME, "image/x-be-bitmap"); 311 312 // Look for quality / capability info in fInputFormats 313 for (int32 i = 0; i < fInputCount; i++) { 314 if (fInputFormats[i].type == B_TRANSLATOR_BITMAP && 315 fInputFormats[i].group == B_TRANSLATOR_BITMAP) { 316 outInfo->quality = fInputFormats[i].quality; 317 outInfo->capability = fInputFormats[i].capability; 318 strcpy(outInfo->name, fInputFormats[i].name); 319 break; 320 } 321 } 322 } 323 324 if (pheader) { 325 pheader->magic = header.magic; 326 pheader->bounds = header.bounds; 327 pheader->rowBytes = header.rowBytes; 328 pheader->colors = header.colors; 329 pheader->dataSize = header.dataSize; 330 } 331 332 return B_OK; 333 } 334 335 336 // --------------------------------------------------------------- 337 // BitsCheck 338 // 339 // Examines the input stream for B_TRANSLATOR_BITMAP format 340 // information and determines if BaseTranslator can handle 341 // the translation entirely, if it must pass the task of 342 // translation to the derived translator or if the stream cannot 343 // be decoded by the BaseTranslator or the derived translator. 344 // 345 // Preconditions: 346 // 347 // Parameters: inSource, where the data to examine is 348 // 349 // ioExtension, configuration settings for the 350 // translator 351 // 352 // outType, The format that the user wants 353 // the data in inSource to be 354 // converted to. NOTE: This is passed by 355 // reference so that it can modify the 356 // outType that is seen by the 357 // BaseTranslator and the derived 358 // translator 359 // 360 // Postconditions: 361 // 362 // Returns: B_NO_TRANSLATOR, if this translator can't handle 363 // the data in inSource 364 // 365 // B_ERROR, if there was an error converting the data to the host 366 // format 367 // 368 // B_BAD_VALUE, if the settings in ioExtension are bad 369 // 370 // B_OK, if this translator understand the data and there were 371 // no errors found 372 // --------------------------------------------------------------- 373 status_t 374 BaseTranslator::BitsCheck(BPositionIO *inSource, BMessage *ioExtension, 375 uint32 &outType) 376 { 377 if (!outType) 378 outType = B_TRANSLATOR_BITMAP; 379 if (outType != B_TRANSLATOR_BITMAP && outType != fTranType) 380 return B_NO_TRANSLATOR; 381 382 // Convert the magic numbers to the various byte orders so that 383 // I won't have to convert the data read in to see whether or not 384 // it is a supported type 385 const uint32 kBitsMagic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP); 386 387 // Read in the magic number and determine if it 388 // is a supported type 389 uint8 ch[4]; 390 if (inSource->Read(ch, 4) != 4) 391 return B_NO_TRANSLATOR; 392 inSource->Seek(-4, SEEK_CUR); 393 // seek backward becuase functions used after this one 394 // expect the stream to be at the beginning 395 396 // Read settings from ioExtension 397 if (ioExtension && fSettings->LoadSettings(ioExtension) < B_OK) 398 return B_BAD_VALUE; 399 400 uint32 sourceMagic; 401 memcpy(&sourceMagic, ch, sizeof(uint32)); 402 if (sourceMagic == kBitsMagic) 403 return B_OK; 404 return B_OK + 1; 405 } 406 407 408 status_t 409 BaseTranslator::BitsIdentify(BPositionIO *inSource, 410 const translation_format *inFormat, BMessage *ioExtension, 411 translator_info *outInfo, uint32 outType) 412 { 413 status_t result = BitsCheck(inSource, ioExtension, outType); 414 if (result == B_OK) { 415 TranslatorBitmap bitmap; 416 result = identify_bits_header(inSource, outInfo, &bitmap); 417 if (result == B_OK) 418 result = DerivedCanHandleImageSize(bitmap.bounds.Width() + 1.0, 419 bitmap.bounds.Height() + 1.0); 420 } else if (result >= B_OK) { 421 // if NOT B_TRANSLATOR_BITMAP, it could be an image in the 422 // derived format 423 result = DerivedIdentify(inSource, inFormat, ioExtension, 424 outInfo, outType); 425 } 426 return result; 427 } 428 429 430 // --------------------------------------------------------------- 431 // Identify 432 // 433 // Examines the data from inSource and determines if it is in a 434 // format that this translator knows how to work with. 435 // 436 // Preconditions: 437 // 438 // Parameters: inSource, where the data to examine is 439 // 440 // inFormat, a hint about the data in inSource, 441 // it is ignored since it is only a hint 442 // 443 // ioExtension, configuration settings for the 444 // translator 445 // 446 // outInfo, information about what data is in 447 // inSource and how well this translator 448 // can handle that data is stored here 449 // 450 // outType, The format that the user wants 451 // the data in inSource to be 452 // converted to 453 // 454 // Postconditions: 455 // 456 // Returns: B_NO_TRANSLATOR, if this translator can't handle 457 // the data in inSource 458 // 459 // B_ERROR, if there was an error converting the data to the host 460 // format 461 // 462 // B_BAD_VALUE, if the settings in ioExtension are bad 463 // 464 // B_OK, if this translator understand the data and there were 465 // no errors found 466 // --------------------------------------------------------------- 467 status_t 468 BaseTranslator::Identify(BPositionIO *inSource, 469 const translation_format *inFormat, BMessage *ioExtension, 470 translator_info *outInfo, uint32 outType) 471 { 472 switch (fTranGroup) { 473 case B_TRANSLATOR_BITMAP: 474 return BitsIdentify(inSource, inFormat, ioExtension, 475 outInfo, outType); 476 477 default: 478 return DerivedIdentify(inSource, inFormat, ioExtension, 479 outInfo, outType); 480 } 481 } 482 483 484 // --------------------------------------------------------------- 485 // translate_from_bits_to_bits 486 // 487 // Convert the data in inSource from the Be Bitmap format ('bits') 488 // to the format specified in outType (either bits or Base). 489 // 490 // Preconditions: 491 // 492 // Parameters: inSource, the bits data to translate 493 // 494 // amtread, the amount of data already read from 495 // inSource 496 // 497 // read, pointer to the data already read from 498 // inSource 499 // 500 // outType, the type of data to convert to 501 // 502 // outDestination, where the output is written to 503 // 504 // Postconditions: 505 // 506 // Returns: B_NO_TRANSLATOR, if the data is not in a supported 507 // format 508 // 509 // B_ERROR, if there was an error allocating memory or some other 510 // error 511 // 512 // B_OK, if successfully translated the data from the bits format 513 // --------------------------------------------------------------- 514 status_t 515 BaseTranslator::translate_from_bits_to_bits(BPositionIO *inSource, 516 uint32 outType, BPositionIO *outDestination) 517 { 518 TranslatorBitmap bitsHeader; 519 bool bheaderonly = false, bdataonly = false; 520 521 status_t result; 522 result = identify_bits_header(inSource, NULL, &bitsHeader); 523 if (result != B_OK) 524 return result; 525 526 // Translate B_TRANSLATOR_BITMAP to B_TRANSLATOR_BITMAP, easy enough :) 527 if (outType == B_TRANSLATOR_BITMAP) { 528 // write out bitsHeader (only if configured to) 529 if (bheaderonly || (!bheaderonly && !bdataonly)) { 530 if (swap_data(B_UINT32_TYPE, &bitsHeader, 531 sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) 532 return B_ERROR; 533 if (outDestination->Write(&bitsHeader, 534 sizeof(TranslatorBitmap)) != sizeof(TranslatorBitmap)) 535 return B_ERROR; 536 } 537 538 // write out the data (only if configured to) 539 if (bdataonly || (!bheaderonly && !bdataonly)) { 540 uint8 buf[1024]; 541 uint32 remaining = B_BENDIAN_TO_HOST_INT32(bitsHeader.dataSize); 542 ssize_t rd, writ; 543 rd = inSource->Read(buf, 1024); 544 while (rd > 0) { 545 writ = outDestination->Write(buf, rd); 546 if (writ < 0) 547 break; 548 remaining -= static_cast<uint32>(writ); 549 rd = inSource->Read(buf, min(1024, remaining)); 550 } 551 552 if (remaining > 0) 553 return B_ERROR; 554 else 555 return B_OK; 556 } else 557 return B_OK; 558 559 } else 560 return B_NO_TRANSLATOR; 561 } 562 563 564 status_t 565 BaseTranslator::BitsTranslate(BPositionIO *inSource, 566 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 567 BPositionIO *outDestination) 568 { 569 status_t result = BitsCheck(inSource, ioExtension, outType); 570 if (result == B_OK && outType == B_TRANSLATOR_BITMAP) { 571 result = translate_from_bits_to_bits(inSource, outType, 572 outDestination); 573 } else if (result >= B_OK) { 574 // If NOT B_TRANSLATOR_BITMAP type it could be the derived format 575 result = DerivedTranslate(inSource, inInfo, ioExtension, outType, 576 outDestination, (result == B_OK)); 577 } 578 return result; 579 } 580 581 582 // --------------------------------------------------------------- 583 // Translate 584 // 585 // Translates the data in inSource to the type outType and stores 586 // the translated data in outDestination. 587 // 588 // Preconditions: 589 // 590 // Parameters: inSource, the data to be translated 591 // 592 // inInfo, hint about the data in inSource (not used) 593 // 594 // ioExtension, configuration options for the 595 // translator 596 // 597 // outType, the type to convert inSource to 598 // 599 // outDestination, where the translated data is 600 // put 601 // 602 // Postconditions: 603 // 604 // Returns: B_BAD_VALUE, if the options in ioExtension are bad 605 // 606 // B_NO_TRANSLATOR, if this translator doesn't understand the data 607 // 608 // B_ERROR, if there was an error allocating memory or converting 609 // data 610 // 611 // B_OK, if all went well 612 // --------------------------------------------------------------- 613 status_t 614 BaseTranslator::Translate(BPositionIO *inSource, 615 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 616 BPositionIO *outDestination) 617 { 618 switch (fTranGroup) { 619 case B_TRANSLATOR_BITMAP: 620 return BitsTranslate(inSource, inInfo, ioExtension, outType, 621 outDestination); 622 623 default: 624 return DerivedTranslate(inSource, inInfo, ioExtension, outType, 625 outDestination, -1); 626 } 627 } 628 629 630 // returns the current translator settings into ioExtension 631 status_t 632 BaseTranslator::GetConfigurationMessage(BMessage *ioExtension) 633 { 634 return fSettings->GetConfigurationMessage(ioExtension); 635 } 636 637 638 // --------------------------------------------------------------- 639 // MakeConfigurationView 640 // 641 // Makes a BView object for configuring / displaying info about 642 // this translator. 643 // 644 // Preconditions: 645 // 646 // Parameters: ioExtension, configuration options for the 647 // translator 648 // 649 // outView, the view to configure the 650 // translator is stored here 651 // 652 // outExtent, the bounds of the view are 653 // stored here 654 // 655 // Postconditions: 656 // 657 // Returns: 658 // --------------------------------------------------------------- 659 status_t 660 BaseTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, 661 BRect *outExtent) 662 { 663 if (!outView || !outExtent) 664 return B_BAD_VALUE; 665 if (ioExtension && fSettings->LoadSettings(ioExtension) != B_OK) 666 return B_BAD_VALUE; 667 668 BView *view = NewConfigView(AcquireSettings()); 669 // implemented in derived class 670 671 if (view) { 672 *outView = view; 673 if ((view->Flags() & B_SUPPORTS_LAYOUT) != 0) 674 view->ResizeTo(view->ExplicitPreferredSize()); 675 676 *outExtent = view->Bounds(); 677 678 return B_OK; 679 } else 680 return BTranslator::MakeConfigurationView(ioExtension, outView, 681 outExtent); 682 } 683 684 685 TranslatorSettings * 686 BaseTranslator::AcquireSettings() 687 { 688 return fSettings->Acquire(); 689 } 690 691 692 /////////////////////////////////////////////////////////// 693 // Functions to be implemented by derived classes 694 695 status_t 696 BaseTranslator::DerivedIdentify(BPositionIO *inSource, 697 const translation_format *inFormat, BMessage *ioExtension, 698 translator_info *outInfo, uint32 outType) 699 { 700 return B_NO_TRANSLATOR; 701 } 702 703 704 status_t 705 BaseTranslator::DerivedTranslate(BPositionIO *inSource, 706 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 707 BPositionIO *outDestination, int32 baseType) 708 { 709 return B_NO_TRANSLATOR; 710 } 711 712 713 status_t 714 BaseTranslator::DerivedCanHandleImageSize(float width, float height) const 715 { 716 return B_OK; 717 } 718 719 720 BView * 721 BaseTranslator::NewConfigView(TranslatorSettings *settings) 722 { 723 return NULL; 724 } 725 726 727 void 728 translate_direct_copy(BPositionIO *inSource, BPositionIO *outDestination) 729 { 730 const size_t kbufsize = 2048; 731 uint8 buffer[kbufsize]; 732 ssize_t ret = inSource->Read(buffer, kbufsize); 733 while (ret > 0) { 734 outDestination->Write(buffer, ret); 735 ret = inSource->Read(buffer, kbufsize); 736 } 737 } 738