1 /* 2 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2012, Gerasim Troeglazov, 3dEyes@gmail.com. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 #include "ICNSTranslator.h" 8 9 #include <stdlib.h> 10 #include <stdio.h> 11 #include <string.h> 12 13 #include "ConfigView.h" 14 #include "ICNSLoader.h" 15 16 #include <Catalog.h> 17 18 #undef B_TRANSLATION_CONTEXT 19 #define B_TRANSLATION_CONTEXT "ICNSTranslator" 20 21 extern "C" { 22 #include "icns.h" 23 } 24 25 const char *kDocumentCount = "/documentCount"; 26 const char *kDocumentIndex = "/documentIndex"; 27 28 #define kICNSMimeType "image/icns" 29 #define kICNSName "Apple Icon" 30 31 // The input formats that this translator supports. 32 static const translation_format sInputFormats[] = { 33 { 34 ICNS_IMAGE_FORMAT, 35 B_TRANSLATOR_BITMAP, 36 ICNS_IN_QUALITY, 37 ICNS_IN_CAPABILITY, 38 kICNSMimeType, 39 kICNSName 40 }, 41 { 42 B_TRANSLATOR_BITMAP, 43 B_TRANSLATOR_BITMAP, 44 BITS_IN_QUALITY, 45 BITS_IN_CAPABILITY, 46 "image/x-be-bitmap", 47 "Be Bitmap Format (ICNSTranslator)" 48 }, 49 }; 50 51 // The output formats that this translator supports. 52 static const translation_format sOutputFormats[] = { 53 { 54 ICNS_IMAGE_FORMAT, 55 B_TRANSLATOR_BITMAP, 56 ICNS_OUT_QUALITY, 57 ICNS_OUT_CAPABILITY, 58 kICNSMimeType, 59 kICNSName 60 }, 61 { 62 B_TRANSLATOR_BITMAP, 63 B_TRANSLATOR_BITMAP, 64 BITS_OUT_QUALITY, 65 BITS_OUT_CAPABILITY, 66 "image/x-be-bitmap", 67 "Be Bitmap Format (ICNSTranslator)" 68 }, 69 }; 70 71 // Default settings for the Translator 72 static const TranSetting sDefaultSettings[] = { 73 {B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false}, 74 {B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false} 75 }; 76 77 const uint32 kNumInputFormats = sizeof(sInputFormats) 78 / sizeof(translation_format); 79 const uint32 kNumOutputFormats = sizeof(sOutputFormats) 80 / sizeof(translation_format); 81 const uint32 kNumDefaultSettings = sizeof(sDefaultSettings) 82 / sizeof(TranSetting); 83 84 85 ICNSTranslator::ICNSTranslator() 86 : BaseTranslator(B_TRANSLATE("Apple icons"), 87 B_TRANSLATE("Apple icon translator"), 88 ICNS_TRANSLATOR_VERSION, 89 sInputFormats, kNumInputFormats, 90 sOutputFormats, kNumOutputFormats, 91 "ICNSTranslator", 92 sDefaultSettings, kNumDefaultSettings, 93 B_TRANSLATOR_BITMAP, ICNS_IMAGE_FORMAT) 94 { 95 } 96 97 98 ICNSTranslator::~ICNSTranslator() 99 { 100 } 101 102 103 status_t 104 ICNSTranslator::DerivedIdentify(BPositionIO *stream, 105 const translation_format *format, BMessage *ioExtension, 106 translator_info *info, uint32 outType) 107 { 108 if (!outType) 109 outType = B_TRANSLATOR_BITMAP; 110 if (outType != B_TRANSLATOR_BITMAP && outType != ICNS_IMAGE_FORMAT) 111 return B_NO_TRANSLATOR; 112 113 uint32 signatureData; 114 ssize_t signatureSize = 4; 115 if (stream->Read(&signatureData, signatureSize) != signatureSize) 116 return B_IO_ERROR; 117 118 const uint32 kICNSMagic = B_HOST_TO_BENDIAN_INT32('icns'); 119 120 if (signatureData != kICNSMagic) 121 return B_ILLEGAL_DATA; 122 123 124 ICNSLoader icnsFile(stream); 125 if(!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0) 126 return B_ILLEGAL_DATA; 127 128 int32 documentCount = icnsFile.IconsCount(); 129 int32 documentIndex = 1; 130 131 if (ioExtension) { 132 if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK) 133 documentIndex = 1; 134 if (documentIndex < 1 || documentIndex > documentCount) 135 return B_NO_TRANSLATOR; 136 137 ioExtension->RemoveName(DOCUMENT_COUNT); 138 ioExtension->AddInt32(DOCUMENT_COUNT, documentCount); 139 } 140 141 info->type = ICNS_IMAGE_FORMAT; 142 info->group = B_TRANSLATOR_BITMAP; 143 info->quality = ICNS_IN_QUALITY; 144 info->capability = ICNS_IN_CAPABILITY; 145 BString iconName("Apple icon"); 146 if (documentCount > 1) 147 iconName << " #" << documentIndex; 148 snprintf(info->name, sizeof(info->name), iconName.String()); 149 strcpy(info->MIME, kICNSMimeType); 150 151 return B_OK; 152 } 153 154 155 status_t 156 ICNSTranslator::DerivedTranslate(BPositionIO *source, 157 const translator_info *info, BMessage *ioExtension, 158 uint32 outType, BPositionIO *target, int32 baseType) 159 { 160 if (!outType) 161 outType = B_TRANSLATOR_BITMAP; 162 if (outType != B_TRANSLATOR_BITMAP && outType != ICNS_IMAGE_FORMAT) 163 return B_NO_TRANSLATOR; 164 165 switch (baseType) { 166 case 1: 167 { 168 TranslatorBitmap bitsHeader; 169 status_t result; 170 result = identify_bits_header(source, NULL, &bitsHeader); 171 if (result != B_OK) 172 return B_NO_TRANSLATOR; 173 174 icns_type_t type = ICNSFormat(bitsHeader.bounds.Width() + 1, 175 bitsHeader.bounds.Height() + 1, bitsHeader.colors); 176 if (type == ICNS_NULL_TYPE) 177 return B_NO_TRANSLATOR; 178 179 if (outType == ICNS_IMAGE_FORMAT) { 180 ICNSSaver icnsFile(source, bitsHeader.rowBytes, type); 181 if (icnsFile.IsCreated()) 182 return icnsFile.SaveData(target); 183 } 184 185 return B_NO_TRANSLATOR; 186 } 187 188 case 0: 189 { 190 if (outType != B_TRANSLATOR_BITMAP) 191 return B_NO_TRANSLATOR; 192 193 ICNSLoader icnsFile(source); 194 if (!icnsFile.IsLoaded() || icnsFile.IconsCount() <= 0) 195 return B_NO_TRANSLATOR; 196 197 int32 documentIndex = 1; 198 199 if (ioExtension) { 200 if (ioExtension->FindInt32(DOCUMENT_INDEX, &documentIndex) != B_OK) 201 documentIndex = 1; 202 } 203 204 return icnsFile.GetIcon(target, documentIndex); 205 } 206 207 default: 208 return B_NO_TRANSLATOR; 209 } 210 } 211 212 213 status_t 214 ICNSTranslator::DerivedCanHandleImageSize(float width, float height) const 215 { 216 if (ICNSFormat(width, height, B_RGBA32) == ICNS_NULL_TYPE) 217 return B_NO_TRANSLATOR; 218 return B_OK; 219 } 220 221 222 BView * 223 ICNSTranslator::NewConfigView(TranslatorSettings *settings) 224 { 225 return new ConfigView(settings); 226 } 227 228 229 // #pragma mark - 230 231 232 BTranslator * 233 make_nth_translator(int32 n, image_id you, uint32 flags, ...) 234 { 235 if (n != 0) 236 return NULL; 237 238 return new ICNSTranslator(); 239 } 240 241