| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 ** Copyright 2006, The Android Open Source Project | |
| 3 ** | |
| 4 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 ** you may not use this file except in compliance with the License. | |
| 6 ** You may obtain a copy of the License at | |
| 7 ** | |
| 8 ** http://www.apache.org/licenses/LICENSE-2.0 | |
| 9 ** | |
| 10 ** Unless required by applicable law or agreed to in writing, software | |
| 11 ** distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 ** See the License for the specific language governing permissions and | |
| 14 ** limitations under the License. | |
| 15 */ | |
| 16 | |
| 17 #include "SkFontHost.h" | |
| 18 #include "SkDescriptor.h" | |
| 19 | |
| 20 // Give 1MB font cache budget | |
| 21 #define FONT_CACHE_MEMORY_BUDGET (1024 * 1024) | |
| 22 | |
| 23 const char* gDefaultfont = "Arial"; // hard code for now | |
| 24 static SkMutex gFTMutex; | |
| 25 | |
| 26 inline SkPoint F32PtToSkPoint(const Float32Point p) | |
| 27 { | |
| 28 SkPoint sp = { SkFloatToFixed(p.x),SkFloatToFixed(p.y) }; | |
| 29 return sp; | |
| 30 } | |
| 31 | |
| 32 static inline uint32_t _rotl(uint32_t v, uint32_t r) | |
| 33 { | |
| 34 return (v << r | v >> (32 - r)); | |
| 35 } | |
| 36 | |
| 37 // This will generate a unique ID based on the fontname + fontstyle | |
| 38 // and also used by upper layer | |
| 39 uint32_t FontFaceChecksum(const char *name,SkTypeface::Style style) | |
| 40 { | |
| 41 if (!name) return style; | |
| 42 | |
| 43 char* q = (char*)name; | |
| 44 | |
| 45 // From "Performance in Practice of String Hashing Functions" | |
| 46 // Ramakrishna & Zobel | |
| 47 const uint32_t L = 5; | |
| 48 const uint32_t R = 2; | |
| 49 | |
| 50 uint32_t h = 0x12345678; | |
| 51 while (*q) { | |
| 52 uint32_t ql = tolower(*q); | |
| 53 h ^= ((h << L) + (h >> R) + ql); | |
| 54 q ++; | |
| 55 } | |
| 56 | |
| 57 // add style | |
| 58 h = _rotl(h, 3) ^ style; | |
| 59 | |
| 60 return h; | |
| 61 } | |
| 62 | |
| 63 #pragma mark - | |
| 64 struct SkFaceRec { | |
| 65 SkFaceRec* fNext; | |
| 66 uint32_t fRefCnt; | |
| 67 ATSUFontID fFontID; | |
| 68 ATSUStyle fStyle; | |
| 69 | |
| 70 SkFaceRec() : fFontID(0), fRefCnt(0), fStyle(NULL) {}; | |
| 71 | |
| 72 ~SkFaceRec() { | |
| 73 if (fStyle) { | |
| 74 ::ATSUDisposeStyle(fStyle); | |
| 75 fStyle = NULL; | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 uint32_t ref() { | |
| 80 return ++fRefCnt; | |
| 81 } | |
| 82 }; | |
| 83 | |
| 84 // Font Face list | |
| 85 static SkFaceRec* gFaceRecHead = NULL; | |
| 86 | |
| 87 static SkFaceRec* find_ft_face(const ATSUFontID fontID) { | |
| 88 SkFaceRec* rec = gFaceRecHead; | |
| 89 while (rec) { | |
| 90 if (rec->fFontID == fontID) { | |
| 91 return rec; | |
| 92 } | |
| 93 rec = rec->fNext; | |
| 94 } | |
| 95 | |
| 96 return NULL; | |
| 97 } | |
| 98 | |
| 99 static SkFaceRec* insert_ft_face(const ATSUFontID afontID, const ATSUStyle atsuS
tyle) { | |
| 100 SkFaceRec* rec = find_ft_face(afontID); | |
| 101 if (rec) { | |
| 102 return rec; // found? | |
| 103 } | |
| 104 | |
| 105 rec = SkNEW(SkFaceRec); | |
| 106 rec->fFontID = afontID; | |
| 107 rec->fStyle = atsuStyle; | |
| 108 rec->fNext = gFaceRecHead; | |
| 109 gFaceRecHead = rec; | |
| 110 | |
| 111 return rec; | |
| 112 } | |
| 113 | |
| 114 static void unref_ft_face(const ATSUFontID fontID) { | |
| 115 | |
| 116 SkFaceRec* rec = gFaceRecHead; | |
| 117 SkFaceRec* prev = NULL; | |
| 118 while (rec) { | |
| 119 SkFaceRec* next = rec->fNext; | |
| 120 if (rec->fFontID == fontID) { | |
| 121 if (--rec->fRefCnt == 0) { | |
| 122 if (prev) | |
| 123 prev->fNext = next; | |
| 124 else | |
| 125 gFaceRecHead = next; | |
| 126 | |
| 127 SkDELETE(rec); | |
| 128 } | |
| 129 return; | |
| 130 } | |
| 131 prev = rec; | |
| 132 rec = next; | |
| 133 } | |
| 134 SkASSERT("shouldn't get here, face not in list"); | |
| 135 } | |
| 136 | |
| 137 #pragma mark - | |
| 138 | |
| 139 // have to do this because SkTypeface::SkTypeface() is protected | |
| 140 class SkTypeface_Mac : public SkTypeface { | |
| 141 public: | |
| 142 SkTypeface_Mac(SkTypeface::Style style, uint32_t id) : SkTypeface(style, id)
{} | |
| 143 | |
| 144 ~SkTypeface_Mac() {} | |
| 145 }; | |
| 146 | |
| 147 #pragma mark - | |
| 148 | |
| 149 static SkTypeface* CreateTypeface_(const char *name, const SkTypeface::Style sty
le) { | |
| 150 | |
| 151 OSStatus err; | |
| 152 ATSUStyle atsuStyle; | |
| 153 ::ATSUCreateStyle(&atsuStyle); | |
| 154 if (name != NULL) { | |
| 155 static const ATSUAttributeTag fontTag = kATSUFontTag; | |
| 156 static const ByteCount fontTagSize = sizeof(ATSUFontID); | |
| 157 | |
| 158 ATSUFontID fontID = 0; | |
| 159 #if 1 | |
| 160 err = ::ATSUFindFontFromName( | |
| 161 name,strlen(name),kFontNoNameCode, /* instead of regular, kFo
ntFamilyName returns bold and/or italic sometimes, but why this works?? */ | |
| 162 kFontMacintoshPlatform,kFontNoScriptCode,kFontNoLanguageCode,&fo
ntID); | |
| 163 #else | |
| 164 CFStringRef cfontName = CFStringCreateWithCString(NULL, name, kCFStringE
ncodingASCII); | |
| 165 ATSFontRef fontRef = ::ATSFontFindFromName(cfontName,kATSOptionFlagsDefa
ult); | |
| 166 fontID = ::FMGetFontFromATSFontRef(fontRef); | |
| 167 CFRelease(cfontName); | |
| 168 #endif | |
| 169 if (0 != fontID) { | |
| 170 const ATSUAttributeValuePtr values[] = { &fontID }; | |
| 171 err = ::ATSUSetAttributes(atsuStyle,1,&fontTag,&fontTagSize,values); | |
| 172 } | |
| 173 else { | |
| 174 } | |
| 175 } | |
| 176 if (style != SkTypeface::kNormal) { | |
| 177 Boolean fontItalic = ((style & SkTypeface::kItalic) != 0); | |
| 178 Boolean fontBold = ((style & SkTypeface::kBold) != 0); | |
| 179 const ATSUAttributeTag tags[2] = { kATSUQDBoldfaceTag, kATSUQDIta
licTag }; | |
| 180 const ATSUAttributeValuePtr values[2] = { &fontBold, &fontItalic }; | |
| 181 const ByteCount sizes[2] = { sizeof(Boolean), sizeof(Bool
ean) }; | |
| 182 err = ::ATSUSetAttributes(atsuStyle,2,tags,sizes,values); | |
| 183 } | |
| 184 | |
| 185 uint32_t cs = FontFaceChecksum(name,style); | |
| 186 SkTypeface_Mac* ptypeface = new SkTypeface_Mac(style,cs); | |
| 187 | |
| 188 if (NULL == ptypeface) { | |
| 189 SkASSERT(false); | |
| 190 return NULL; | |
| 191 } | |
| 192 | |
| 193 SkFaceRec* rec = insert_ft_face(cs, atsuStyle); | |
| 194 SkASSERT(rec); | |
| 195 | |
| 196 return ptypeface; | |
| 197 } | |
| 198 | |
| 199 static SkTypeface* CreateTypeface_(const SkFaceRec* rec, const SkTypeface::Style
style) { | |
| 200 | |
| 201 OSStatus err; | |
| 202 ATSUStyle atsuStyle; | |
| 203 err = ::ATSUCreateAndCopyStyle(rec->fStyle, &atsuStyle); | |
| 204 | |
| 205 Boolean fontItalic = ((style & SkTypeface::kItalic) != 0); | |
| 206 Boolean fontBold = ((style & SkTypeface::kBold) != 0); | |
| 207 const ATSUAttributeTag tags[2] = { kATSUQDBoldfaceTag, kATSUQDItalicT
ag }; | |
| 208 const ATSUAttributeValuePtr values[2] = { &fontBold, &fontItalic }; | |
| 209 const ByteCount sizes[2] = { sizeof(Boolean), sizeof(Boolean)
}; | |
| 210 err = ::ATSUSetAttributes(atsuStyle,2,tags,sizes,values); | |
| 211 | |
| 212 // get old font id and name | |
| 213 ATSUFontID fontID = 0; | |
| 214 ByteCount actual = 0; | |
| 215 err = ::ATSUGetAttribute(rec->fStyle,kATSUFontTag,sizeof(ATSUFontID),&fontID
,&actual); | |
| 216 | |
| 217 ByteCount actualLength = 0; | |
| 218 char *fontname = NULL; | |
| 219 err = ::ATSUFindFontName(fontID , kFontFamilyName, kFontUnicodePlatform, kFo
ntNoScriptCode, | |
| 220 kFontNoLanguageCode , 0 , NULL , &actualLength , NULL ); | |
| 221 if ( err == noErr) | |
| 222 { | |
| 223 actualLength += 1 ; | |
| 224 fontname = (char*)malloc( actualLength ); | |
| 225 err = ::ATSUFindFontName(fontID, kFontFamilyName, kFontUnicodePlatform,
kFontNoScriptCode, | |
| 226 kFontNoLanguageCode, actualLength, fontname , NULL, NULL); | |
| 227 } | |
| 228 | |
| 229 SkTypeface_Mac* ptypeface = NULL; | |
| 230 if (fontname == NULL) { | |
| 231 ptypeface = new SkTypeface_Mac(style,rec->fFontID); | |
| 232 return ptypeface; | |
| 233 } | |
| 234 else { | |
| 235 uint32_t cs = FontFaceChecksum(fontname,style); | |
| 236 ptypeface = new SkTypeface_Mac(style, cs); | |
| 237 | |
| 238 if (NULL == ptypeface) { | |
| 239 SkASSERT(false); | |
| 240 return NULL; | |
| 241 } | |
| 242 | |
| 243 free(fontname); | |
| 244 | |
| 245 insert_ft_face(cs,atsuStyle); | |
| 246 } | |
| 247 return ptypeface; | |
| 248 } | |
| 249 | |
| 250 #pragma mark - | |
| 251 | |
| 252 class SkScalerContext_Mac : public SkScalerContext { | |
| 253 public: | |
| 254 SkScalerContext_Mac(const SkDescriptor* desc); | |
| 255 virtual ~SkScalerContext_Mac(); | |
| 256 | |
| 257 protected: | |
| 258 virtual unsigned generateGlyphCount() const; | |
| 259 virtual uint16_t generateCharToGlyph(SkUnichar uni); | |
| 260 virtual void generateAdvance(SkGlyph* glyph); | |
| 261 virtual void generateMetrics(SkGlyph* glyph); | |
| 262 virtual void generateImage(const SkGlyph& glyph); | |
| 263 virtual void generatePath(const SkGlyph& glyph, SkPath* path); | |
| 264 virtual void generateLineHeight(SkPoint* ascent, SkPoint* descent); | |
| 265 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetr
ics* mY); | |
| 266 virtual SkDeviceContext getDC() { return NULL; } // not implemented on Mac | |
| 267 | |
| 268 private: | |
| 269 ATSUTextLayout fLayout; | |
| 270 ATSUStyle fStyle; | |
| 271 | |
| 272 static OSStatus MoveTo(const Float32Point *pt, void *cb); | |
| 273 static OSStatus Line(const Float32Point *pt, void *cb); | |
| 274 static OSStatus Curve(const Float32Point *pt1, const Float32Point *pt2, cons
t Float32Point *pt3, void *cb); | |
| 275 static OSStatus Close(void *cb); | |
| 276 }; | |
| 277 | |
| 278 SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc) | |
| 279 : SkScalerContext(desc), fLayout(0), fStyle(0) | |
| 280 { | |
| 281 SkAutoMutexAcquire ac(gFTMutex); | |
| 282 OSStatus err; | |
| 283 | |
| 284 SkFaceRec* rec = find_ft_face(fRec.fFontID); | |
| 285 if (rec) { | |
| 286 rec->ref(); | |
| 287 err = ::ATSUCreateAndCopyStyle(rec->fStyle, &fStyle); | |
| 288 } | |
| 289 else { | |
| 290 SkASSERT(false); | |
| 291 // create a default | |
| 292 err = ::ATSUCreateStyle(&fStyle); | |
| 293 } | |
| 294 | |
| 295 uint32_t size = SkFixedFloor(fRec.fTextSize); | |
| 296 Fixed fixedSize = IntToFixed(size); | |
| 297 static const ATSUAttributeTag sizeTag = kATSUSizeTag; | |
| 298 static const ByteCount sizeTagSize = sizeof(Fixed); | |
| 299 const ATSUAttributeValuePtr values[] = { &fixedSize }; | |
| 300 err = ::ATSUSetAttributes(fStyle,1,&sizeTag,&sizeTagSize,values); | |
| 301 | |
| 302 err = ::ATSUCreateTextLayout(&fLayout); | |
| 303 } | |
| 304 | |
| 305 SkScalerContext_Mac::~SkScalerContext_Mac() | |
| 306 { | |
| 307 unref_ft_face(fRec.fFontID); | |
| 308 | |
| 309 ::ATSUDisposeTextLayout(fLayout); | |
| 310 ::ATSUDisposeStyle(fStyle); | |
| 311 } | |
| 312 | |
| 313 unsigned SkScalerContext_Mac::generateGlyphCount() const | |
| 314 { | |
| 315 return 0xFFFF; | |
| 316 } | |
| 317 | |
| 318 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) | |
| 319 { | |
| 320 SkAutoMutexAcquire ac(gFTMutex); | |
| 321 | |
| 322 OSStatus err; | |
| 323 UniChar achar = uni; | |
| 324 err = ::ATSUSetTextPointerLocation(fLayout,&achar,0,1,1); | |
| 325 err = ::ATSUSetRunStyle(fLayout,fStyle,kATSUFromTextBeginning,kATSUToTextEnd
); | |
| 326 | |
| 327 ATSLayoutRecord *layoutPtr; | |
| 328 ItemCount count; | |
| 329 ATSGlyphRef glyph; | |
| 330 | |
| 331 err = ::ATSUDirectGetLayoutDataArrayPtrFromTextLayout(fLayout,0,kATSUDirectD
ataLayoutRecordATSLayoutRecordCurrent,(void**)&layoutPtr,&count); | |
| 332 glyph = layoutPtr->glyphID; | |
| 333 ::ATSUDirectReleaseLayoutDataArrayPtr(NULL,kATSUDirectDataLayoutRecordATSLay
outRecordCurrent,(void**)&layoutPtr); | |
| 334 return glyph; | |
| 335 } | |
| 336 | |
| 337 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { | |
| 338 this->generateMetrics(glyph); | |
| 339 } | |
| 340 | |
| 341 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) | |
| 342 { | |
| 343 GlyphID glyphID = glyph->fID; | |
| 344 ATSGlyphScreenMetrics metrics= { 0 }; | |
| 345 | |
| 346 glyph->fRsbDelta = 0; | |
| 347 glyph->fLsbDelta = 0; | |
| 348 | |
| 349 OSStatus err = ATSUGlyphGetScreenMetrics(fStyle,1,&glyphID,0,true,true,&metr
ics); | |
| 350 if (err == noErr) { | |
| 351 glyph->fAdvanceX = SkFloatToFixed(metrics.deviceAdvance.x); | |
| 352 glyph->fAdvanceY = SkFloatToFixed(metrics.deviceAdvance.y); | |
| 353 //glyph->fWidth = metrics.width; | |
| 354 //glyph->fHeight = metrics.height; | |
| 355 glyph->fWidth = metrics.width + ceil(metrics.sideBearing.x - metrics.oth
erSideBearing.x); | |
| 356 glyph->fHeight = metrics.height + ceil(metrics.sideBearing.y - metrics.o
therSideBearing.y) + 1; | |
| 357 | |
| 358 glyph->fTop = -metrics.topLeft.y; | |
| 359 glyph->fLeft = metrics.topLeft.x; | |
| 360 } | |
| 361 } | |
| 362 | |
| 363 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint:
:FontMetrics* my) { | |
| 364 //SkASSERT(false); | |
| 365 if (mx) | |
| 366 memset(mx, 0, sizeof(SkPaint::FontMetrics)); | |
| 367 if (my) | |
| 368 memset(my, 0, sizeof(SkPaint::FontMetrics)); | |
| 369 return; | |
| 370 } | |
| 371 | |
| 372 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) | |
| 373 { | |
| 374 SkAutoMutexAcquire ac(gFTMutex); | |
| 375 | |
| 376 GlyphID glyphID = glyph.fID; | |
| 377 ATSGlyphScreenMetrics metrics= { 0 }; | |
| 378 | |
| 379 SkASSERT(fLayout); | |
| 380 OSStatus err = ::ATSUGlyphGetScreenMetrics(fStyle,1,&glyphID,0,true,true,&me
trics); | |
| 381 | |
| 382 // uint32_t w = metrics.width; | |
| 383 // uint32_t h = metrics.height; | |
| 384 // uint32_t pitch = (w + 3) & ~0x3; | |
| 385 // if (pitch != glyph.rowBytes()) { | |
| 386 // SkASSERT(false); // it's different from previously cacluated in genera
teMetrics(), so the size of glyph.fImage buffer is incorrect! | |
| 387 // } | |
| 388 | |
| 389 CGColorSpaceRef greyColorSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceG
enericGray); | |
| 390 CGContextRef contextRef = ::CGBitmapContextCreate((uint8_t*)glyph.fImage, gl
yph.fWidth, glyph.fHeight, 8, glyph.rowBytes(), greyColorSpace, kCGImageAlphaNon
e); | |
| 391 if (!contextRef) { | |
| 392 SkASSERT(false); | |
| 393 return; | |
| 394 } | |
| 395 | |
| 396 ::CGContextSetFillColorSpace(contextRef, greyColorSpace); | |
| 397 ::CGContextSetStrokeColorSpace(contextRef, greyColorSpace); | |
| 398 | |
| 399 ::CGContextSetGrayFillColor(contextRef, 0.0, 1.0); | |
| 400 ::CGContextFillRect(contextRef, ::CGRectMake(0, 0, glyph.fWidth, glyph.fHeig
ht)); | |
| 401 | |
| 402 ::CGContextSetGrayFillColor(contextRef, 1.0, 1.0); | |
| 403 ::CGContextSetGrayStrokeColor(contextRef, 1.0, 1.0); | |
| 404 ::CGContextSetTextDrawingMode(contextRef, kCGTextFill); | |
| 405 | |
| 406 ATSUAttributeTag tag = kATSUCGContextTag; | |
| 407 ByteCount size = sizeof(CGContextRef); | |
| 408 ATSUAttributeValuePtr value = &contextRef; | |
| 409 err = ::ATSUSetLayoutControls(fLayout,1,&tag,&size,&value); | |
| 410 err = ::ATSUDrawText(fLayout,kATSUFromTextBeginning,kATSUToTextEnd,FloatToFi
xed(-metrics.topLeft.x),FloatToFixed(glyph.fHeight-metrics.topLeft.y)); | |
| 411 ::CGContextRelease(contextRef); | |
| 412 } | |
| 413 | |
| 414 void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) | |
| 415 { | |
| 416 SkAutoMutexAcquire ac(gFTMutex); | |
| 417 OSStatus err,result; | |
| 418 | |
| 419 err = ::ATSUGlyphGetCubicPaths( | |
| 420 fStyle,glyph.fID, | |
| 421 &SkScalerContext_Mac::MoveTo, | |
| 422 &SkScalerContext_Mac::Line, | |
| 423 &SkScalerContext_Mac::Curve, | |
| 424 &SkScalerContext_Mac::Close, | |
| 425 path,&result); | |
| 426 SkASSERT(err == noErr); | |
| 427 } | |
| 428 | |
| 429 void SkScalerContext_Mac::generateLineHeight(SkPoint* ascent, SkPoint* descent) | |
| 430 { | |
| 431 ATSUTextMeasurement textAscent, textDescent; | |
| 432 ByteCount actual = 0; | |
| 433 OSStatus err = ::ATSUGetAttribute(fStyle,kATSULineAscentTag,sizeof(ATSUTextM
easurement),&textAscent,&actual); | |
| 434 ascent->set(0,textAscent); | |
| 435 err = ::ATSUGetAttribute(fStyle,kATSULineDescentTag,sizeof(ATSUTextMeasureme
nt),&textDescent,&actual); | |
| 436 descent->set(0,textDescent); | |
| 437 } | |
| 438 | |
| 439 OSStatus SkScalerContext_Mac::MoveTo(const Float32Point *pt, void *cb) | |
| 440 { | |
| 441 reinterpret_cast<SkPath*>(cb)->moveTo(F32PtToSkPoint(*pt)); | |
| 442 return noErr; | |
| 443 } | |
| 444 | |
| 445 OSStatus SkScalerContext_Mac::Line(const Float32Point *pt, void *cb) | |
| 446 { | |
| 447 reinterpret_cast<SkPath*>(cb)->lineTo(F32PtToSkPoint(*pt)); | |
| 448 return noErr; | |
| 449 } | |
| 450 | |
| 451 OSStatus SkScalerContext_Mac::Curve(const Float32Point *pt1, const Float32Point
*pt2, const Float32Point *pt3, void *cb) | |
| 452 { | |
| 453 reinterpret_cast<SkPath*>(cb)->cubicTo(F32PtToSkPoint(*pt1),F32PtToSkPoint(*
pt2),F32PtToSkPoint(*pt3)); | |
| 454 return noErr; | |
| 455 } | |
| 456 | |
| 457 OSStatus SkScalerContext_Mac::Close(void *cb) | |
| 458 { | |
| 459 reinterpret_cast<SkPath*>(cb)->close(); | |
| 460 return noErr; | |
| 461 } | |
| 462 | |
| 463 #pragma mark - | |
| 464 | |
| 465 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { | |
| 466 SkASSERT(!"SkFontHost::Serialize unimplemented"); | |
| 467 } | |
| 468 | |
| 469 SkTypeface* SkFontHost::Deserialize(SkStream* stream) { | |
| 470 SkASSERT(!"SkFontHost::Deserialize unimplemented"); | |
| 471 return NULL; | |
| 472 } | |
| 473 | |
| 474 SkTypeface* SkFontHost::CreateTypeface(SkStream* stream) { | |
| 475 | |
| 476 //Should not be used on Mac, keep linker happy | |
| 477 SkASSERT(false); | |
| 478 return CreateTypeface_(gDefaultfont,SkTypeface::kNormal); | |
| 479 } | |
| 480 | |
| 481 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) | |
| 482 { | |
| 483 return new SkScalerContext_Mac(desc); | |
| 484 } | |
| 485 | |
| 486 SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::
Rec& rec) | |
| 487 { | |
| 488 SkAutoDescriptor ad(sizeof(rec) + sizeof(gDefaultfont) + SkDescriptor::Co
mputeOverhead(2)); | |
| 489 SkDescriptor* desc = ad.getDesc(); | |
| 490 | |
| 491 desc->init(); | |
| 492 SkScalerContext::Rec* newRec = | |
| 493 (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, sizeof(rec),
&rec); | |
| 494 | |
| 495 CreateTypeface_(gDefaultfont,SkTypeface::kNormal); | |
| 496 newRec->fFontID = FontFaceChecksum(gDefaultfont,SkTypeface::kNormal); | |
| 497 desc->computeChecksum(); | |
| 498 | |
| 499 return SkFontHost::CreateScalerContext(desc); | |
| 500 } | |
| 501 | |
| 502 | |
| 503 /** Return the closest matching typeface given either an existing family | |
| 504 (specified by a typeface in that family) or by a familyName, and a | |
| 505 requested style. | |
| 506 1) If familyFace is null, use famillyName. | |
| 507 2) If famillyName is null, use familyFace. | |
| 508 3) If both are null, return the default font that best matches style | |
| 509 This MUST not return NULL. | |
| 510 */ | |
| 511 | |
| 512 SkTypeface* SkFontHost::FindTypeface(const SkTypeface* familyFace, const char fa
milyName[], SkTypeface::Style style) { | |
| 513 | |
| 514 SkAutoMutexAcquire ac(gFTMutex); | |
| 515 | |
| 516 // clip to legal style bits | |
| 517 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); | |
| 518 | |
| 519 SkTypeface* tf = NULL; | |
| 520 | |
| 521 if (NULL == familyFace && NULL == familyName) { | |
| 522 tf = CreateTypeface_(gDefaultfont,style); | |
| 523 } | |
| 524 else { | |
| 525 if (NULL != familyFace) { | |
| 526 uint32_t id = familyFace->uniqueID(); | |
| 527 SkFaceRec* rec = find_ft_face(id); | |
| 528 if (!rec) { | |
| 529 SkASSERT(false); | |
| 530 tf = CreateTypeface_(gDefaultfont,style); | |
| 531 } | |
| 532 else { | |
| 533 tf = CreateTypeface_(rec,style); | |
| 534 } | |
| 535 } | |
| 536 else { | |
| 537 tf = CreateTypeface_(familyName,style); | |
| 538 } | |
| 539 } | |
| 540 | |
| 541 if (NULL == tf) { | |
| 542 tf = CreateTypeface_(gDefaultfont,style); | |
| 543 } | |
| 544 return tf; | |
| 545 | |
| 546 } | |
| 547 | |
| 548 size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) { | |
| 549 if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET) | |
| 550 return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET; | |
| 551 else | |
| 552 return 0; // nothing to do | |
| 553 } | |
| 554 | |
| 555 int SkFontHost::ComputeGammaFlag(const SkPaint& paint) { | |
| 556 return 0; | |
| 557 } | |
| 558 | |
| 559 void SkFontHost::GetGammaTables(const uint8_t* tables[2]) { | |
| 560 tables[0] = NULL; // black gamma (e.g. exp=1.4) | |
| 561 tables[1] = NULL; // white gamma (e.g. exp= 1/1.4) | |
| 562 } | |
| OLD | NEW |