1 /*****************************************************************************/
3 // Written by Michael Wilber, Haiku Translation Kit Team
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.
12 // Copyright (c) 2004 Haiku, Inc.
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:
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
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 /*****************************************************************************/
33 #include "BaseTranslator.h"
44 #undef B_TRANSLATION_CONTEXT
45 #define B_TRANSLATION_CONTEXT "BaseTranslator"
48 // ---------------------------------------------------------------
51 // Sets up the version info and the name of the translator so that
52 // these values can be returned when they are requested.
61 // ---------------------------------------------------------------
62 BaseTranslator::BaseTranslator(const char *name
, const char *info
,
63 const int32 version
, const translation_format
*inFormats
,
64 int32 inCount
, const translation_format
*outFormats
, int32 outCount
,
65 const char *settingsFile
, const TranSetting
*defaults
, int32 defCount
,
66 uint32 tranGroup
, uint32 tranType
)
70 fSettings
= new TranslatorSettings(settingsFile
, defaults
, defCount
);
71 fSettings
->LoadSettings();
72 // load settings from the Base Translator settings file
75 fName
= new char[strlen(name
) + 1];
77 fInfo
= new char[strlen(info
) + 41];
78 sprintf(fInfo
, "%s v%d.%d.%d %s", info
,
79 static_cast<int>(B_TRANSLATION_MAJOR_VERSION(fVersion
)),
80 static_cast<int>(B_TRANSLATION_MINOR_VERSION(fVersion
)),
81 static_cast<int>(B_TRANSLATION_REVISION_VERSION(fVersion
)),
84 fInputFormats
= inFormats
;
85 fInputCount
= (fInputFormats
) ? inCount
: 0;
86 fOutputFormats
= outFormats
;
87 fOutputCount
= (fOutputFormats
) ? outCount
: 0;
88 fTranGroup
= tranGroup
;
93 // ---------------------------------------------------------------
105 // ---------------------------------------------------------------
107 // NOTE: It may be the case, that under Be's libtranslation.so,
108 // that this destructor will never be called
109 BaseTranslator::~BaseTranslator()
111 fSettings
->Release();
117 // ---------------------------------------------------------------
120 // Returns the short name of the translator.
128 // Returns: a const char * to the short name of the translator
129 // ---------------------------------------------------------------
131 BaseTranslator::TranslatorName() const
137 // ---------------------------------------------------------------
140 // Returns a more verbose name for the translator than the one
141 // TranslatorName() returns. This usually includes version info.
149 // Returns: a const char * to the verbose name of the translator
150 // ---------------------------------------------------------------
152 BaseTranslator::TranslatorInfo() const
158 // ---------------------------------------------------------------
161 // Returns the integer representation of the current version of
171 // ---------------------------------------------------------------
173 BaseTranslator::TranslatorVersion() const
179 // ---------------------------------------------------------------
182 // Returns a list of input formats supported by this translator.
186 // Parameters: out_count, The number of input formats
187 // support is returned here.
191 // Returns: the array of input formats and the number of input
192 // formats through the out_count parameter
193 // ---------------------------------------------------------------
194 const translation_format
*
195 BaseTranslator::InputFormats(int32
*out_count
) const
198 *out_count
= fInputCount
;
199 return fInputFormats
;
205 // ---------------------------------------------------------------
208 // Returns a list of output formats supported by this translator.
212 // Parameters: out_count, The number of output formats
213 // support is returned here.
217 // Returns: the array of output formats and the number of output
218 // formats through the out_count parameter
219 // ---------------------------------------------------------------
220 const translation_format
*
221 BaseTranslator::OutputFormats(int32
*out_count
) const
224 *out_count
= fOutputCount
;
225 return fOutputFormats
;
231 // ---------------------------------------------------------------
232 // identify_bits_header
234 // Determines if the data in inSource is in the
235 // B_TRANSLATOR_BITMAP ('bits') format. If it is, it returns
236 // info about the data in inSource to outInfo and pheader.
240 // Parameters: inSource, The source of the image data
242 // outInfo, Information about the translator
245 // amtread, Amount of data read from inSource
246 // before this function was called
248 // read, Pointer to the data that was read
249 // in before this function was called
251 // pheader, The bits header is copied here after
252 // it is read in from inSource
256 // Returns: B_NO_TRANSLATOR, if the data does not look like
259 // B_ERROR, if the header data could not be converted to host
262 // B_OK, if the data looks like bits data and no errors were
264 // ---------------------------------------------------------------
266 BaseTranslator::identify_bits_header(BPositionIO
*inSource
,
267 translator_info
*outInfo
, TranslatorBitmap
*pheader
)
269 TranslatorBitmap header
;
271 // read in the header
272 ssize_t size
= sizeof(TranslatorBitmap
);
274 (reinterpret_cast<uint8
*> (&header
)), size
) != size
)
275 return B_NO_TRANSLATOR
;
277 // convert to host byte order
278 if (swap_data(B_UINT32_TYPE
, &header
, sizeof(TranslatorBitmap
),
279 B_SWAP_BENDIAN_TO_HOST
) != B_OK
)
282 // check if header values are reasonable
283 if (header
.colors
!= B_RGB32
&&
284 header
.colors
!= B_RGB32_BIG
&&
285 header
.colors
!= B_RGBA32
&&
286 header
.colors
!= B_RGBA32_BIG
&&
287 header
.colors
!= B_RGB24
&&
288 header
.colors
!= B_RGB24_BIG
&&
289 header
.colors
!= B_RGB16
&&
290 header
.colors
!= B_RGB16_BIG
&&
291 header
.colors
!= B_RGB15
&&
292 header
.colors
!= B_RGB15_BIG
&&
293 header
.colors
!= B_RGBA15
&&
294 header
.colors
!= B_RGBA15_BIG
&&
295 header
.colors
!= B_CMAP8
&&
296 header
.colors
!= B_GRAY8
&&
297 header
.colors
!= B_GRAY1
&&
298 header
.colors
!= B_CMYK32
&&
299 header
.colors
!= B_CMY32
&&
300 header
.colors
!= B_CMYA32
&&
301 header
.colors
!= B_CMY24
)
302 return B_NO_TRANSLATOR
;
303 if (header
.rowBytes
* (header
.bounds
.Height() + 1) != header
.dataSize
)
304 return B_NO_TRANSLATOR
;
307 outInfo
->type
= B_TRANSLATOR_BITMAP
;
308 outInfo
->group
= B_TRANSLATOR_BITMAP
;
309 outInfo
->quality
= 0.2;
310 outInfo
->capability
= 0.2;
311 strlcpy(outInfo
->name
, B_TRANSLATE("Be Bitmap Format"),
312 sizeof(outInfo
->name
));
313 strcpy(outInfo
->MIME
, "image/x-be-bitmap");
315 // Look for quality / capability info in fInputFormats
316 for (int32 i
= 0; i
< fInputCount
; i
++) {
317 if (fInputFormats
[i
].type
== B_TRANSLATOR_BITMAP
&&
318 fInputFormats
[i
].group
== B_TRANSLATOR_BITMAP
) {
319 outInfo
->quality
= fInputFormats
[i
].quality
;
320 outInfo
->capability
= fInputFormats
[i
].capability
;
321 strcpy(outInfo
->name
, fInputFormats
[i
].name
);
328 pheader
->magic
= header
.magic
;
329 pheader
->bounds
= header
.bounds
;
330 pheader
->rowBytes
= header
.rowBytes
;
331 pheader
->colors
= header
.colors
;
332 pheader
->dataSize
= header
.dataSize
;
339 // ---------------------------------------------------------------
342 // Examines the input stream for B_TRANSLATOR_BITMAP format
343 // information and determines if BaseTranslator can handle
344 // the translation entirely, if it must pass the task of
345 // translation to the derived translator or if the stream cannot
346 // be decoded by the BaseTranslator or the derived translator.
350 // Parameters: inSource, where the data to examine is
352 // ioExtension, configuration settings for the
355 // outType, The format that the user wants
356 // the data in inSource to be
357 // converted to. NOTE: This is passed by
358 // reference so that it can modify the
359 // outType that is seen by the
360 // BaseTranslator and the derived
365 // Returns: B_NO_TRANSLATOR, if this translator can't handle
366 // the data in inSource
368 // B_ERROR, if there was an error converting the data to the host
371 // B_BAD_VALUE, if the settings in ioExtension are bad
373 // B_OK, if this translator understand the data and there were
375 // ---------------------------------------------------------------
377 BaseTranslator::BitsCheck(BPositionIO
*inSource
, BMessage
*ioExtension
,
381 outType
= B_TRANSLATOR_BITMAP
;
382 if (outType
!= B_TRANSLATOR_BITMAP
&& outType
!= fTranType
)
383 return B_NO_TRANSLATOR
;
385 // Convert the magic numbers to the various byte orders so that
386 // I won't have to convert the data read in to see whether or not
387 // it is a supported type
388 const uint32 kBitsMagic
= B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP
);
390 // Read in the magic number and determine if it
391 // is a supported type
393 if (inSource
->Read(ch
, 4) != 4)
394 return B_NO_TRANSLATOR
;
395 inSource
->Seek(-4, SEEK_CUR
);
396 // seek backward becuase functions used after this one
397 // expect the stream to be at the beginning
399 // Read settings from ioExtension
400 if (ioExtension
&& fSettings
->LoadSettings(ioExtension
) < B_OK
)
404 memcpy(&sourceMagic
, ch
, sizeof(uint32
));
405 if (sourceMagic
== kBitsMagic
)
412 BaseTranslator::BitsIdentify(BPositionIO
*inSource
,
413 const translation_format
*inFormat
, BMessage
*ioExtension
,
414 translator_info
*outInfo
, uint32 outType
)
416 status_t result
= BitsCheck(inSource
, ioExtension
, outType
);
417 if (result
== B_OK
) {
418 TranslatorBitmap bitmap
;
419 result
= identify_bits_header(inSource
, outInfo
, &bitmap
);
421 result
= DerivedCanHandleImageSize(bitmap
.bounds
.Width() + 1.0,
422 bitmap
.bounds
.Height() + 1.0);
423 } else if (result
>= B_OK
) {
424 // if NOT B_TRANSLATOR_BITMAP, it could be an image in the
426 result
= DerivedIdentify(inSource
, inFormat
, ioExtension
,
433 // ---------------------------------------------------------------
436 // Examines the data from inSource and determines if it is in a
437 // format that this translator knows how to work with.
441 // Parameters: inSource, where the data to examine is
443 // inFormat, a hint about the data in inSource,
444 // it is ignored since it is only a hint
446 // ioExtension, configuration settings for the
449 // outInfo, information about what data is in
450 // inSource and how well this translator
451 // can handle that data is stored here
453 // outType, The format that the user wants
454 // the data in inSource to be
459 // Returns: B_NO_TRANSLATOR, if this translator can't handle
460 // the data in inSource
462 // B_ERROR, if there was an error converting the data to the host
465 // B_BAD_VALUE, if the settings in ioExtension are bad
467 // B_OK, if this translator understand the data and there were
469 // ---------------------------------------------------------------
471 BaseTranslator::Identify(BPositionIO
*inSource
,
472 const translation_format
*inFormat
, BMessage
*ioExtension
,
473 translator_info
*outInfo
, uint32 outType
)
475 switch (fTranGroup
) {
476 case B_TRANSLATOR_BITMAP
:
477 return BitsIdentify(inSource
, inFormat
, ioExtension
,
481 return DerivedIdentify(inSource
, inFormat
, ioExtension
,
487 // ---------------------------------------------------------------
488 // translate_from_bits_to_bits
490 // Convert the data in inSource from the Be Bitmap format ('bits')
491 // to the format specified in outType (either bits or Base).
495 // Parameters: inSource, the bits data to translate
497 // amtread, the amount of data already read from
500 // read, pointer to the data already read from
503 // outType, the type of data to convert to
505 // outDestination, where the output is written to
509 // Returns: B_NO_TRANSLATOR, if the data is not in a supported
512 // B_ERROR, if there was an error allocating memory or some other
515 // B_OK, if successfully translated the data from the bits format
516 // ---------------------------------------------------------------
518 BaseTranslator::translate_from_bits_to_bits(BPositionIO
*inSource
,
519 uint32 outType
, BPositionIO
*outDestination
)
521 TranslatorBitmap bitsHeader
;
522 bool bheaderonly
= false, bdataonly
= false;
525 result
= identify_bits_header(inSource
, NULL
, &bitsHeader
);
529 // Translate B_TRANSLATOR_BITMAP to B_TRANSLATOR_BITMAP, easy enough :)
530 if (outType
== B_TRANSLATOR_BITMAP
) {
531 // write out bitsHeader (only if configured to)
532 if (bheaderonly
|| (!bheaderonly
&& !bdataonly
)) {
533 if (swap_data(B_UINT32_TYPE
, &bitsHeader
,
534 sizeof(TranslatorBitmap
), B_SWAP_HOST_TO_BENDIAN
) != B_OK
)
536 if (outDestination
->Write(&bitsHeader
,
537 sizeof(TranslatorBitmap
)) != sizeof(TranslatorBitmap
))
541 // write out the data (only if configured to)
542 if (bdataonly
|| (!bheaderonly
&& !bdataonly
)) {
544 uint32 remaining
= B_BENDIAN_TO_HOST_INT32(bitsHeader
.dataSize
);
546 rd
= inSource
->Read(buf
, 1024);
548 writ
= outDestination
->Write(buf
, rd
);
551 remaining
-= static_cast<uint32
>(writ
);
552 rd
= inSource
->Read(buf
, std::min((uint32
)1024,
564 return B_NO_TRANSLATOR
;
569 BaseTranslator::BitsTranslate(BPositionIO
*inSource
,
570 const translator_info
*inInfo
, BMessage
*ioExtension
, uint32 outType
,
571 BPositionIO
*outDestination
)
573 status_t result
= BitsCheck(inSource
, ioExtension
, outType
);
574 if (result
== B_OK
&& outType
== B_TRANSLATOR_BITMAP
) {
575 result
= translate_from_bits_to_bits(inSource
, outType
,
577 } else if (result
>= B_OK
) {
578 // If NOT B_TRANSLATOR_BITMAP type it could be the derived format
579 result
= DerivedTranslate(inSource
, inInfo
, ioExtension
, outType
,
580 outDestination
, (result
== B_OK
));
586 // ---------------------------------------------------------------
589 // Translates the data in inSource to the type outType and stores
590 // the translated data in outDestination.
594 // Parameters: inSource, the data to be translated
596 // inInfo, hint about the data in inSource (not used)
598 // ioExtension, configuration options for the
601 // outType, the type to convert inSource to
603 // outDestination, where the translated data is
608 // Returns: B_BAD_VALUE, if the options in ioExtension are bad
610 // B_NO_TRANSLATOR, if this translator doesn't understand the data
612 // B_ERROR, if there was an error allocating memory or converting
615 // B_OK, if all went well
616 // ---------------------------------------------------------------
618 BaseTranslator::Translate(BPositionIO
*inSource
,
619 const translator_info
*inInfo
, BMessage
*ioExtension
, uint32 outType
,
620 BPositionIO
*outDestination
)
622 switch (fTranGroup
) {
623 case B_TRANSLATOR_BITMAP
:
624 return BitsTranslate(inSource
, inInfo
, ioExtension
, outType
,
628 return DerivedTranslate(inSource
, inInfo
, ioExtension
, outType
,
634 // returns the current translator settings into ioExtension
636 BaseTranslator::GetConfigurationMessage(BMessage
*ioExtension
)
638 return fSettings
->GetConfigurationMessage(ioExtension
);
642 // ---------------------------------------------------------------
643 // MakeConfigurationView
645 // Makes a BView object for configuring / displaying info about
650 // Parameters: ioExtension, configuration options for the
653 // outView, the view to configure the
654 // translator is stored here
656 // outExtent, the bounds of the view are
662 // ---------------------------------------------------------------
664 BaseTranslator::MakeConfigurationView(BMessage
*ioExtension
, BView
**outView
,
667 if (!outView
|| !outExtent
)
669 if (ioExtension
&& fSettings
->LoadSettings(ioExtension
) != B_OK
)
672 BView
*view
= NewConfigView(AcquireSettings());
673 // implemented in derived class
677 if ((view
->Flags() & B_SUPPORTS_LAYOUT
) != 0)
678 view
->ResizeTo(view
->ExplicitPreferredSize());
680 *outExtent
= view
->Bounds();
684 return BTranslator::MakeConfigurationView(ioExtension
, outView
,
690 BaseTranslator::AcquireSettings()
692 return fSettings
->Acquire();
696 ///////////////////////////////////////////////////////////
697 // Functions to be implemented by derived classes
700 BaseTranslator::DerivedIdentify(BPositionIO
*inSource
,
701 const translation_format
*inFormat
, BMessage
*ioExtension
,
702 translator_info
*outInfo
, uint32 outType
)
704 return B_NO_TRANSLATOR
;
709 BaseTranslator::DerivedTranslate(BPositionIO
*inSource
,
710 const translator_info
*inInfo
, BMessage
*ioExtension
, uint32 outType
,
711 BPositionIO
*outDestination
, int32 baseType
)
713 return B_NO_TRANSLATOR
;
718 BaseTranslator::DerivedCanHandleImageSize(float width
, float height
) const
725 BaseTranslator::NewConfigView(TranslatorSettings
*settings
)
732 translate_direct_copy(BPositionIO
*inSource
, BPositionIO
*outDestination
)
734 const size_t kbufsize
= 2048;
735 uint8 buffer
[kbufsize
];
736 ssize_t ret
= inSource
->Read(buffer
, kbufsize
);
738 outDestination
->Write(buffer
, ret
);
739 ret
= inSource
->Read(buffer
, kbufsize
);