Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1172)

Side by Side Diff: skia/ports/SkFontHost_mac.cpp

Issue 113827: Remove the remainder of the skia source code from the Chromium repo.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « skia/ports/SkFontHost_linux.cpp ('k') | skia/ports/SkFontHost_none.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « skia/ports/SkFontHost_linux.cpp ('k') | skia/ports/SkFontHost_none.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698