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 #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_VERSION(fVersion)), 68 static_cast<int>(B_TRANSLATION_MINOR_VERSION(fVersion)), 69 static_cast<int>(B_TRANSLATION_REVISION_VERSION(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) 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 return B_OK + 1; 387 } 388 389 status_t 390 BaseTranslator::BitsIdentify(BPositionIO *inSource, 391 const translation_format *inFormat, BMessage *ioExtension, 392 translator_info *outInfo, uint32 outType) 393 { 394 status_t result = BitsCheck(inSource, ioExtension, outType); 395 if (result == B_OK) { 396 TranslatorBitmap bitmap; 397 result = identify_bits_header(inSource, outInfo, &bitmap); 398 if (result == B_OK) 399 result = DerivedCanHandleImageSize(bitmap.bounds.Width() + 1.0, 400 bitmap.bounds.Height() + 1.0); 401 } else if (result >= B_OK) { 402 // if NOT B_TRANSLATOR_BITMAP, it could be an image in the 403 // derived format 404 result = DerivedIdentify(inSource, inFormat, ioExtension, 405 outInfo, outType); 406 } 407 return result; 408 } 409 410 // --------------------------------------------------------------- 411 // Identify 412 // 413 // Examines the data from inSource and determines if it is in a 414 // format that this translator knows how to work with. 415 // 416 // Preconditions: 417 // 418 // Parameters: inSource, where the data to examine is 419 // 420 // inFormat, a hint about the data in inSource, 421 // it is ignored since it is only a hint 422 // 423 // ioExtension, configuration settings for the 424 // translator 425 // 426 // outInfo, information about what data is in 427 // inSource and how well this translator 428 // can handle that data is stored here 429 // 430 // outType, The format that the user wants 431 // the data in inSource to be 432 // converted to 433 // 434 // Postconditions: 435 // 436 // Returns: B_NO_TRANSLATOR, if this translator can't handle 437 // the data in inSource 438 // 439 // B_ERROR, if there was an error converting the data to the host 440 // format 441 // 442 // B_BAD_VALUE, if the settings in ioExtension are bad 443 // 444 // B_OK, if this translator understand the data and there were 445 // no errors found 446 // --------------------------------------------------------------- 447 status_t 448 BaseTranslator::Identify(BPositionIO *inSource, 449 const translation_format *inFormat, BMessage *ioExtension, 450 translator_info *outInfo, uint32 outType) 451 { 452 switch (fTranGroup) { 453 case B_TRANSLATOR_BITMAP: 454 return BitsIdentify(inSource, inFormat, ioExtension, 455 outInfo, outType); 456 457 default: 458 return DerivedIdentify(inSource, inFormat, ioExtension, 459 outInfo, outType); 460 } 461 } 462 463 // --------------------------------------------------------------- 464 // translate_from_bits_to_bits 465 // 466 // Convert the data in inSource from the Be Bitmap format ('bits') 467 // to the format specified in outType (either bits or Base). 468 // 469 // Preconditions: 470 // 471 // Parameters: inSource, the bits data to translate 472 // 473 // amtread, the amount of data already read from 474 // inSource 475 // 476 // read, pointer to the data already read from 477 // inSource 478 // 479 // outType, the type of data to convert to 480 // 481 // outDestination, where the output is written to 482 // 483 // Postconditions: 484 // 485 // Returns: B_NO_TRANSLATOR, if the data is not in a supported 486 // format 487 // 488 // B_ERROR, if there was an error allocating memory or some other 489 // error 490 // 491 // B_OK, if successfully translated the data from the bits format 492 // --------------------------------------------------------------- 493 status_t 494 BaseTranslator::translate_from_bits_to_bits(BPositionIO *inSource, 495 uint32 outType, BPositionIO *outDestination) 496 { 497 TranslatorBitmap bitsHeader; 498 bool bheaderonly = false, bdataonly = false; 499 500 status_t result; 501 result = identify_bits_header(inSource, NULL, &bitsHeader); 502 if (result != B_OK) 503 return result; 504 505 // Translate B_TRANSLATOR_BITMAP to B_TRANSLATOR_BITMAP, easy enough :) 506 if (outType == B_TRANSLATOR_BITMAP) { 507 // write out bitsHeader (only if configured to) 508 if (bheaderonly || (!bheaderonly && !bdataonly)) { 509 if (swap_data(B_UINT32_TYPE, &bitsHeader, 510 sizeof(TranslatorBitmap), B_SWAP_HOST_TO_BENDIAN) != B_OK) 511 return B_ERROR; 512 if (outDestination->Write(&bitsHeader, 513 sizeof(TranslatorBitmap)) != sizeof(TranslatorBitmap)) 514 return B_ERROR; 515 } 516 517 // write out the data (only if configured to) 518 if (bdataonly || (!bheaderonly && !bdataonly)) { 519 uint8 buf[1024]; 520 uint32 remaining = B_BENDIAN_TO_HOST_INT32(bitsHeader.dataSize); 521 ssize_t rd, writ; 522 rd = inSource->Read(buf, 1024); 523 while (rd > 0) { 524 writ = outDestination->Write(buf, rd); 525 if (writ < 0) 526 break; 527 remaining -= static_cast<uint32>(writ); 528 rd = inSource->Read(buf, min(1024, remaining)); 529 } 530 531 if (remaining > 0) 532 return B_ERROR; 533 else 534 return B_OK; 535 } else 536 return B_OK; 537 538 } else 539 return B_NO_TRANSLATOR; 540 } 541 542 status_t 543 BaseTranslator::BitsTranslate(BPositionIO *inSource, 544 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 545 BPositionIO *outDestination) 546 { 547 status_t result = BitsCheck(inSource, ioExtension, outType); 548 if (result == B_OK && outType == B_TRANSLATOR_BITMAP) { 549 result = translate_from_bits_to_bits(inSource, outType, 550 outDestination); 551 } else if (result >= B_OK) { 552 // If NOT B_TRANSLATOR_BITMAP type it could be the derived format 553 result = DerivedTranslate(inSource, inInfo, ioExtension, outType, 554 outDestination, (result == B_OK)); 555 } 556 return result; 557 } 558 559 // --------------------------------------------------------------- 560 // Translate 561 // 562 // Translates the data in inSource to the type outType and stores 563 // the translated data in outDestination. 564 // 565 // Preconditions: 566 // 567 // Parameters: inSource, the data to be translated 568 // 569 // inInfo, hint about the data in inSource (not used) 570 // 571 // ioExtension, configuration options for the 572 // translator 573 // 574 // outType, the type to convert inSource to 575 // 576 // outDestination, where the translated data is 577 // put 578 // 579 // Postconditions: 580 // 581 // Returns: B_BAD_VALUE, if the options in ioExtension are bad 582 // 583 // B_NO_TRANSLATOR, if this translator doesn't understand the data 584 // 585 // B_ERROR, if there was an error allocating memory or converting 586 // data 587 // 588 // B_OK, if all went well 589 // --------------------------------------------------------------- 590 status_t 591 BaseTranslator::Translate(BPositionIO *inSource, 592 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 593 BPositionIO *outDestination) 594 { 595 switch (fTranGroup) { 596 case B_TRANSLATOR_BITMAP: 597 return BitsTranslate(inSource, inInfo, ioExtension, outType, 598 outDestination); 599 600 default: 601 return DerivedTranslate(inSource, inInfo, ioExtension, outType, 602 outDestination, -1); 603 } 604 } 605 606 // returns the current translator settings into ioExtension 607 status_t 608 BaseTranslator::GetConfigurationMessage(BMessage *ioExtension) 609 { 610 return fSettings->GetConfigurationMessage(ioExtension); 611 } 612 613 // --------------------------------------------------------------- 614 // MakeConfigurationView 615 // 616 // Makes a BView object for configuring / displaying info about 617 // this translator. 618 // 619 // Preconditions: 620 // 621 // Parameters: ioExtension, configuration options for the 622 // translator 623 // 624 // outView, the view to configure the 625 // translator is stored here 626 // 627 // outExtent, the bounds of the view are 628 // stored here 629 // 630 // Postconditions: 631 // 632 // Returns: 633 // --------------------------------------------------------------- 634 status_t 635 BaseTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView, 636 BRect *outExtent) 637 { 638 if (!outView || !outExtent) 639 return B_BAD_VALUE; 640 if (ioExtension && fSettings->LoadSettings(ioExtension) != B_OK) 641 return B_BAD_VALUE; 642 643 BView *view = NewConfigView(AcquireSettings()); 644 // implemented in derived class 645 if (view) { 646 *outView = view; 647 *outExtent = view->Bounds(); 648 649 return B_OK; 650 } else 651 return BTranslator::MakeConfigurationView(ioExtension, outView, 652 outExtent); 653 } 654 655 TranslatorSettings * 656 BaseTranslator::AcquireSettings() 657 { 658 return fSettings->Acquire(); 659 } 660 661 /////////////////////////////////////////////////////////// 662 // Functions to be implemented by derived classes 663 664 status_t 665 BaseTranslator::DerivedIdentify(BPositionIO *inSource, 666 const translation_format *inFormat, BMessage *ioExtension, 667 translator_info *outInfo, uint32 outType) 668 { 669 return B_NO_TRANSLATOR; 670 } 671 672 status_t 673 BaseTranslator::DerivedTranslate(BPositionIO *inSource, 674 const translator_info *inInfo, BMessage *ioExtension, uint32 outType, 675 BPositionIO *outDestination, int32 baseType) 676 { 677 return B_NO_TRANSLATOR; 678 } 679 680 681 status_t 682 BaseTranslator::DerivedCanHandleImageSize(float width, float height) const 683 { 684 return B_OK; 685 } 686 687 688 BView * 689 BaseTranslator::NewConfigView(TranslatorSettings *settings) 690 { 691 return NULL; 692 } 693 694 void 695 translate_direct_copy(BPositionIO *inSource, BPositionIO *outDestination) 696 { 697 const size_t kbufsize = 2048; 698 uint8 buffer[kbufsize]; 699 ssize_t ret = inSource->Read(buffer, kbufsize); 700 while (ret > 0) { 701 outDestination->Write(buffer, ret); 702 ret = inSource->Read(buffer, kbufsize); 703 } 704 } 705