1/* 2 * Copyright (c) 2001-2007 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * BLGenerateOFLabel.c 25 * bless 26 * 27 * Created by Shantonu Sen <ssen@apple.com> on Sat Feb 23 2002. 28 * Copyright (c) 2002-2007 Apple Inc. All Rights Reserved. 29 * 30 */ 31 32#include <CoreFoundation/CoreFoundation.h> 33 34#include <sys/types.h> 35 36#include "bless.h" 37#include "bless_private.h" 38 39static const char clut[] = 40 { 41 0x00, /* 0x00 0x00 0x00 white */ 42 0xF6, /* 0x11 0x11 0x11 */ 43 0xF7, /* 0x22 0x22 0x22 */ 44 45 0x2A, /* 0x33 = 1*6^2 + 1*6 + 1 = 43 colors */ 46 47 0xF8, /* 0x44 */ 48 0xF9, /* 0x55 */ 49 50 0x55, /* 0x66 = 2*(36 + 6 + 1) = 86 colors */ 51 52 0xFA, /* 0x77 */ 53 0xFB, /* 0x88 */ 54 55 0x80, /* 0x99 = (3*43) = 129 colors*/ 56 57 0xFC, /* 0xAA */ 58 0xFD, /* 0xBB */ 59 60 0xAB, /* 0xCC = 4*43 = 172 colors */ 61 62 0xFE, /* 0xDD */ 63 0xFF, /* 0xEE */ 64 65 0xD6, /* 0xFF = 5*43 = 215 */ 66 }; 67 68static int makeLabelOfSize(const char *label, unsigned char *bitmapData, 69 uint16_t width, uint16_t height, int scale, uint16_t *newwidth); 70 71static int refitToWidth(unsigned char *bitmapData, 72 uint16_t width, uint16_t height, uint16_t newwidth); 73 74 75 76int BLGenerateLabelData(BLContextPtr context, const char *label, int scale, CFDataRef *data) 77{ 78 uint16_t width = 340 * scale; 79 uint16_t height = 12 * scale; 80 uint16_t newwidth; 81 int err; 82 int i; 83 CFDataRef bits = NULL; 84 unsigned char *bitmapData; 85 86 contextprintf(context, kBLLogLevelError, 87 "CoreGraphics is not available for rendering\n"); 88 return 1; 89 90 bitmapData = (unsigned char *)malloc(width*height+5); 91 if (!bitmapData) { 92 contextprintf(context, kBLLogLevelError, 93 "Could not alloc CoreGraphics backing store\n"); 94 return 1; 95 } 96 bzero(bitmapData, width*height+5); 97 98 err = makeLabelOfSize(label, bitmapData+5, width, height, scale, &newwidth); 99 if (err) { 100 free(bitmapData); 101 *data = NULL; 102 return 2; 103 } 104 105 // cap at 340*scale pixels wide. 106 if (newwidth > width) newwidth = width; 107 108 contextprintf(context, kBLLogLevelVerbose, "Refitting to width %d\n", newwidth); 109 110 err = refitToWidth(bitmapData+5, width, height, newwidth); 111 if (err) { 112 free(bitmapData); 113 *data = NULL; 114 return 3; 115 } 116 117 bitmapData = realloc(bitmapData, newwidth*height+5); 118 if (!bitmapData) { 119 contextprintf(context, kBLLogLevelError, 120 "Could not realloc to shrink CoreGraphics backing store\n"); 121 122 return 4; 123 } 124 125 bitmapData[0] = 1; 126 *(uint16_t *)&bitmapData[1] = CFSwapInt16HostToBig(newwidth); 127 *(uint16_t *)&bitmapData[3] = CFSwapInt16HostToBig(height); 128 129 for(i=5; i < newwidth*height+5; i++) { 130 bitmapData[i] = clut[bitmapData[i] >> 4]; 131 } 132 133 // bits = CFDataCreate(kCFAllocatorDefault, bitmapData, newwidth*height+5); 134 bits = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *)bitmapData, newwidth*height+5, kCFAllocatorMalloc); 135 // free(bitmapData); 136 137 if(bits == NULL) { 138 contextprintf(context, kBLLogLevelError, 139 "Could not create CFDataRef\n"); 140 return 6; 141 } 142 143 *data = (void *)bits; 144 145 return 0; 146} 147 148 149int BLGenerateOFLabel(BLContextPtr context, 150 const char label[], 151CFDataRef* data) { 152 153 154 uint16_t width = 340; 155 uint16_t height = 12; 156 uint16_t newwidth; 157 int err; 158 int i; 159 CFDataRef bits = NULL; 160 unsigned char *bitmapData; 161 162 contextprintf(context, kBLLogLevelError, 163 "CoreGraphics is not available for rendering\n"); 164 return 1; 165 166 bitmapData = (unsigned char *)malloc(width*height+5); 167 if(!bitmapData) { 168 contextprintf(context, kBLLogLevelError, 169 "Could not alloc CoreGraphics backing store\n"); 170 return 1; 171 } 172 bzero(bitmapData, width*height+5); 173 174 err = makeLabelOfSize(label, bitmapData+5, width, height, 1, &newwidth); 175 if(err) { 176 free(bitmapData); 177 *data = NULL; 178 return 2; 179 } 180 181 // cap at 300 pixels wide. 182 if(newwidth > width) newwidth = width; 183 184 contextprintf(context, kBLLogLevelVerbose, "Refitting to width %d\n", newwidth); 185 186 187 err = refitToWidth(bitmapData+5, width, height, newwidth); 188 if(err) { 189 free(bitmapData); 190 *data = NULL; 191 return 3; 192 } 193 194 bitmapData = realloc(bitmapData, newwidth*height+5); 195 if(NULL == bitmapData) { 196 contextprintf(context, kBLLogLevelError, 197 "Could not realloc to shrink CoreGraphics backing store\n"); 198 199 return 4; 200 } 201 202 bitmapData[0] = 1; 203 *(uint16_t *)&bitmapData[1] = CFSwapInt16HostToBig(newwidth); 204 *(uint16_t *)&bitmapData[3] = CFSwapInt16HostToBig(height); 205 206 for(i=5; i < newwidth*height+5; i++) { 207 bitmapData[i] = clut[bitmapData[i] >> 4]; 208 } 209 210 // bits = CFDataCreate(kCFAllocatorDefault, bitmapData, newwidth*height+5); 211 bits = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *)bitmapData, newwidth*height+5, kCFAllocatorMalloc); 212 // free(bitmapData); 213 214 if(bits == NULL) { 215 contextprintf(context, kBLLogLevelError, 216 "Could not create CFDataRef\n"); 217 return 6; 218 } 219 220 *data = (void *)bits; 221 222 return 0; 223} 224 225#undef USE_COREGRAPHICS 226#define USE_COREGRAPHICS 0 227 228#if USE_COREGRAPHICS 229#include <ApplicationServices/ApplicationServices.h> 230 231static int makeLabelOfSize(const char *label, unsigned char *bitmapData, 232uint16_t width, uint16_t height, int scale, uint16_t *newwidth) { 233 234 int bitmapByteCount; 235 int bitmapBytesPerRow; 236 237 CGContextRef context = NULL; 238 CGColorSpaceRef colorSpace = NULL; 239 240 241 bitmapBytesPerRow = width*1; 242 bitmapByteCount = bitmapBytesPerRow * height; 243 244 colorSpace = CGColorSpaceCreateDeviceGray(); 245 246 247 context = CGBitmapContextCreate( bitmapData, 248 width, 249 height, 250 8, 251 bitmapBytesPerRow, 252 colorSpace, 253 kCGImageAlphaNone); 254 255 if(context == NULL) { 256 fprintf(stderr, "Could not init CoreGraphics context\n"); 257 return 1; 258 } 259 260 261#if USE_CORETEXT 262 { 263 CFStringRef s1; 264 CFAttributedStringRef s2; 265 CTLineRef ct1; 266 CGRect rect; 267 CFMutableDictionaryRef dict; 268 CGColorRef color; 269 CTFontRef fontRef; 270 271 // white text on black background, for OF/EFI bitmap 272 const CGFloat components[] = { 273 (CGFloat)1.0, (CGFloat)1.0 274 }; 275 276 /* set to white background for testing 277 CGContextSetGrayFillColor(context, 1.0, 1.0); 278 CGContextFillRect(context,CGRectInfinite); 279 */ 280 281 color = CGColorCreate(colorSpace, components); 282 if(color == NULL) return 1; 283 284 fontRef = CTFontCreateWithName(CFSTR("Helvetica"), 10.0 * scale, NULL); 285 if(fontRef == NULL) return 1; 286 287 dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 288 CFDictionarySetValue(dict, kCTForegroundColorAttributeName, color); 289 CFDictionarySetValue(dict, kCTFontAttributeName, fontRef); 290 CFRelease(color); 291 CFRelease(fontRef); 292 293 s1 = CFStringCreateWithCString(kCFAllocatorDefault, label, kCFStringEncodingUTF8); 294 s2 = CFAttributedStringCreate(kCFAllocatorDefault,s1,dict); 295 CFRelease(s1); 296 CFRelease(dict); 297 298 ct1 = CTLineCreateWithAttributedString(s2); 299 CFRelease(s2); 300 if(ct1 == NULL) return 2; 301 302 rect = CTLineGetImageBounds(ct1, context); 303 304 CGContextSetTextPosition(context, 2.0 * scale, 2.0 * scale); 305 306 CTLineDraw(ct1, context); 307 308 CGContextFlush(context); 309 310 CFRelease(ct1); 311 312 if(newwidth) { *newwidth = (int)rect.size.width + 4 * scale; } 313 // printf("[%f,%f] (%f,%f)\n", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); 314 315 } 316#else 317 { 318 CGPoint pt; 319 320 CGContextSetTextDrawingMode(context, kCGTextFill); 321 CGContextSelectFont(context, "Helvetica", 10.0 * scale, kCGEncodingMacRoman); 322 CGContextSetGrayFillColor(context, 1.0, 1.0); 323 CGContextSetShouldAntialias(context, 1); 324 CGContextSetCharacterSpacing(context, 0.5 * scale); 325 326 pt = CGContextGetTextPosition(context); 327 328 CGContextShowTextAtPoint(context, 2.0 * scale, 2.0 * scale, label, strlen(label)); 329 330 pt = CGContextGetTextPosition(context); 331 332 if(newwidth) { *newwidth = (int)pt.x + 2; } 333 334 } 335#endif 336 337 338#if 0 339// CFShow(CGImageDestinationCopyTypeIdentifiers()); 340 CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, bitmapData, height*width, NULL); 341 CGImageRef imageRef = CGImageCreate(width,height,8,8,bitmapBytesPerRow,colorSpace,0, dataProvider, NULL, 0, 0); 342 CFURLRef output = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)"foo.tiff", strlen("foo.tiff"), 0); 343 CGImageDestinationRef dest = CGImageDestinationCreateWithURL(output, CFSTR("public.tiff"), 1, NULL); 344 345 CGImageDestinationAddImage(dest, imageRef, NULL); 346 347 CGImageDestinationFinalize(dest); 348 349 CFRelease(dest); 350 CFRelease(output); 351 CFRelease(imageRef); 352 CFRelease(dataProvider); 353 // write(1, bitmapData, height*width); 354 355#endif 356 357 CGColorSpaceRelease(colorSpace); 358 CGContextRelease(context); 359 360 361 return 0; 362 363} 364 365#else // !USE_COREGRAPHICS 366static int makeLabelOfSize(const char *label, unsigned char *bitmapData, 367 uint16_t width, uint16_t height, int scale, uint16_t *newwidth) { 368 369 // just make a blank label 370 *newwidth = 10; 371 return 0; 372} 373#endif // !USE_COREGRAPHICS 374 375/* 376 * data is of the form: 377 * 111111000111111000111111000 -> 378 * 111111111111111111 379 */ 380 381static int refitToWidth(unsigned char *bitmapData, 382 uint16_t width, uint16_t height, uint16_t newwidth) 383{ 384 uint16_t row; 385 for(row=1; row < height; row++) { 386 bcopy(&bitmapData[row*width], &bitmapData[row*newwidth], newwidth); 387 } 388 389 return 0; 390} 391