Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
10 #include "SkFontDescriptor.h"
11 #include "SkFontHost.h"
12 #include "SkFontHost_FreeType_common.h"
13 #include "SkDescriptor.h"
14 #include "SkStream.h"
15 #include "SkPaint.h"
16 #include "SkString.h"
17 #include "SkStream.h"
18 #include "SkThread.h"
19 #include "SkTSearch.h"
20 #include <stdio.h>
22 #define FONT_CACHE_MEMORY_BUDGET (768 * 1024)
24 #ifndef SK_FONT_FILE_PREFIX
25 #define SK_FONT_FILE_PREFIX "/fonts/"
26 #endif
28 bool find_name_and_attributes(SkStream* stream, SkString* name, SkTypeface::Style* style,
29 bool* isFixedWidth);
31 static void GetFullPathForSysFonts(SkString* full, const char name[]) {
32 full->set(getenv("ANDROID_ROOT"));
33 full->append(SK_FONT_FILE_PREFIX);
34 full->append(name);
35 }
37 ///////////////////////////////////////////////////////////////////////////////
39 struct FamilyRec;
41 /* This guy holds a mapping of a name -> family, used for looking up fonts.
42 Since it is stored in a stretchy array that doesn't preserve object
43 semantics, we don't use constructor/destructors, but just have explicit
44 helpers to manage our internal bookkeeping.
45 */
46 struct NameFamilyPair {
47 const char* fName; // we own this
48 FamilyRec* fFamily; // we don't own this, we just reference it
50 void construct(const char name[], FamilyRec* family) {
51 fName = strdup(name);
52 fFamily = family; // we don't own this, so just record the referene
53 }
55 void destruct() {
56 free((char*)fName);
57 // we don't own family, so just ignore our reference
58 }
59 };
61 // we use atomic_inc to grow this for each typeface we create
62 static int32_t gUniqueFontID;
64 // this is the mutex that protects these globals
65 static SkMutex gFamilyMutex;
66 static FamilyRec* gFamilyHead;
67 static SkTDArray<NameFamilyPair> gNameList;
69 struct FamilyRec {
70 FamilyRec* fNext;
71 SkTypeface* fFaces[4];
73 FamilyRec()
74 {
75 fNext = gFamilyHead;
76 memset(fFaces, 0, sizeof(fFaces));
77 gFamilyHead = this;
78 }
79 };
81 static SkTypeface* find_best_face(const FamilyRec* family,
82 SkTypeface::Style style) {
83 SkTypeface* const* faces = family->fFaces;
85 if (faces[style] != NULL) { // exact match
86 return faces[style];
87 }
88 // look for a matching bold
89 style = (SkTypeface::Style)(style ^ SkTypeface::kItalic);
90 if (faces[style] != NULL) {
91 return faces[style];
92 }
93 // look for the plain
94 if (faces[SkTypeface::kNormal] != NULL) {
95 return faces[SkTypeface::kNormal];
96 }
97 // look for anything
98 for (int i = 0; i < 4; i++) {
99 if (faces[i] != NULL) {
100 return faces[i];
101 }
102 }
103 // should never get here, since the faces list should not be empty
104 SkASSERT(!"faces list is empty");
105 return NULL;
106 }
108 static FamilyRec* find_family(const SkTypeface* member) {
109 FamilyRec* curr = gFamilyHead;
110 while (curr != NULL) {
111 for (int i = 0; i < 4; i++) {
112 if (curr->fFaces[i] == member) {
113 return curr;
114 }
115 }
116 curr = curr->fNext;
117 }
118 return NULL;
119 }
121 /* Returns the matching typeface, or NULL. If a typeface is found, its refcnt
122 is not modified.
123 */
124 static SkTypeface* find_from_uniqueID(uint32_t uniqueID) {
125 FamilyRec* curr = gFamilyHead;
126 while (curr != NULL) {
127 for (int i = 0; i < 4; i++) {
128 SkTypeface* face = curr->fFaces[i];
129 if (face != NULL && face->uniqueID() == uniqueID) {
130 return face;
131 }
132 }
133 curr = curr->fNext;
134 }
135 return NULL;
136 }
138 /* Remove reference to this face from its family. If the resulting family
139 is empty (has no faces), return that family, otherwise return NULL
140 */
141 static FamilyRec* remove_from_family(const SkTypeface* face) {
142 FamilyRec* family = find_family(face);
143 SkASSERT(family->fFaces[face->style()] == face);
144 family->fFaces[face->style()] = NULL;
146 for (int i = 0; i < 4; i++) {
147 if (family->fFaces[i] != NULL) { // family is non-empty
148 return NULL;
149 }
150 }
151 return family; // return the empty family
152 }
154 // maybe we should make FamilyRec be doubly-linked
155 static void detach_and_delete_family(FamilyRec* family) {
156 FamilyRec* curr = gFamilyHead;
157 FamilyRec* prev = NULL;
159 while (curr != NULL) {
160 FamilyRec* next = curr->fNext;
161 if (curr == family) {
162 if (prev == NULL) {
163 gFamilyHead = next;
164 } else {
165 prev->fNext = next;
166 }
167 SkDELETE(family);
168 return;
169 }
170 prev = curr;
171 curr = next;
172 }
173 SkASSERT(!"Yikes, couldn't find family in our list to remove/delete");
174 }
176 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
177 NameFamilyPair* list = gNameList.begin();
178 int count = gNameList.count();
180 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
182 if (index >= 0) {
183 return find_best_face(list[index].fFamily, style);
184 }
185 return NULL;
186 }
188 static SkTypeface* find_typeface(const SkTypeface* familyMember,
189 SkTypeface::Style style) {
190 const FamilyRec* family = find_family(familyMember);
191 return family ? find_best_face(family, style) : NULL;
192 }
194 static void add_name(const char name[], FamilyRec* family) {
195 SkAutoAsciiToLC tolc(name);
196 name = tolc.lc();
198 NameFamilyPair* list = gNameList.begin();
199 int count = gNameList.count();
201 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
203 if (index < 0) {
204 list = gNameList.insert(~index);
205 list->construct(name, family);
206 }
207 }
209 static void remove_from_names(FamilyRec* emptyFamily)
210 {
211 #ifdef SK_DEBUG
212 for (int i = 0; i < 4; i++) {
213 SkASSERT(emptyFamily->fFaces[i] == NULL);
214 }
215 #endif
217 SkTDArray<NameFamilyPair>& list = gNameList;
219 // must go backwards when removing
220 for (int i = list.count() - 1; i >= 0; --i) {
221 NameFamilyPair* pair = &list[i];
222 if (pair->fFamily == emptyFamily) {
223 pair->destruct();
224 list.remove(i);
225 }
226 }
227 }
229 ///////////////////////////////////////////////////////////////////////////////
231 class FamilyTypeface : public SkTypeface_FreeType {
232 public:
233 FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember,
234 bool isFixedWidth)
235 : SkTypeface_FreeType(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
236 fIsSysFont = sysFont;
238 SkAutoMutexAcquire ac(gFamilyMutex);
240 FamilyRec* rec = NULL;
241 if (familyMember) {
242 rec = find_family(familyMember);
243 SkASSERT(rec);
244 } else {
245 rec = SkNEW(FamilyRec);
246 }
247 rec->fFaces[style] = this;
248 }
250 virtual ~FamilyTypeface() {
251 SkAutoMutexAcquire ac(gFamilyMutex);
253 // remove us from our family. If the family is now empty, we return
254 // that and then remove that family from the name list
255 FamilyRec* family = remove_from_family(this);
256 if (NULL != family) {
257 remove_from_names(family);
258 detach_and_delete_family(family);
259 }
260 }
262 bool isSysFont() const { return fIsSysFont; }
264 virtual const char* getUniqueString() const = 0;
265 virtual const char* getFilePath() const = 0;
267 protected:
268 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
270 private:
271 bool fIsSysFont;
273 typedef SkTypeface INHERITED;
274 };
276 ///////////////////////////////////////////////////////////////////////////////
278 class StreamTypeface : public FamilyTypeface {
279 public:
280 StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember,
281 SkStream* stream, bool isFixedWidth)
282 : INHERITED(style, sysFont, familyMember, isFixedWidth) {
283 SkASSERT(stream);
284 stream->ref();
285 fStream = stream;
286 }
287 virtual ~StreamTypeface() {
288 fStream->unref();
289 }
291 // overrides
292 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
293 *ttcIndex = 0;
294 // we just ref our existing stream, since the caller will call unref()
295 // when they are through
296 fStream->ref();
297 // must rewind each time, since the caller assumes a "new" stream
298 fStream->rewind();
299 return fStream;
300 }
301 virtual const char* getUniqueString() const { return NULL; }
302 virtual const char* getFilePath() const { return NULL; }
304 private:
305 SkStream* fStream;
307 typedef FamilyTypeface INHERITED;
308 };
310 class FileTypeface : public FamilyTypeface {
311 public:
312 FileTypeface(Style style, bool sysFont, SkTypeface* familyMember,
313 const char path[], bool isFixedWidth)
314 : INHERITED(style, sysFont, familyMember, isFixedWidth) {
315 SkString fullpath;
317 if (sysFont) {
318 GetFullPathForSysFonts(&fullpath, path);
319 path = fullpath.c_str();
320 }
321 fPath.set(path);
322 }
324 // overrides
325 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
326 *ttcIndex = 0;
327 SkStream* stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str()));
329 // check for failure
330 if (stream->getLength() <= 0) {
331 SkDELETE(stream);
332 stream = NULL;
333 }
334 return stream;
335 }
336 virtual const char* getUniqueString() const {
337 const char* str = strrchr(fPath.c_str(), '/');
338 if (str) {
339 str += 1; // skip the '/'
340 }
341 return str;
342 }
343 virtual const char* getFilePath() const {
344 return fPath.c_str();
345 }
347 private:
348 SkString fPath;
350 typedef FamilyTypeface INHERITED;
351 };
353 ///////////////////////////////////////////////////////////////////////////////
354 ///////////////////////////////////////////////////////////////////////////////
356 static bool get_name_and_style(const char path[], SkString* name,
357 SkTypeface::Style* style,
358 bool* isFixedWidth, bool isExpected) {
359 SkString fullpath;
360 GetFullPathForSysFonts(&fullpath, path);
362 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(fullpath.c_str()));
363 if (stream.get()) {
364 find_name_and_attributes(stream, name, style, isFixedWidth);
365 return true;
366 }
368 if (isExpected) {
369 SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
370 }
371 return false;
372 }
374 // used to record our notion of the pre-existing fonts
375 struct FontInitRec {
376 const char* fFileName;
377 const char* const* fNames; // null-terminated list
378 };
380 static const char* gSansNames[] = {
381 "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
382 };
384 static const char* gSerifNames[] = {
385 "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
386 "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
387 };
389 static const char* gMonoNames[] = {
390 "monospace", "courier", "courier new", "monaco", NULL
391 };
393 // deliberately empty, but we use the address to identify fallback fonts
394 static const char* gFBNames[] = { NULL };
396 /* Fonts must be grouped by family, with the first font in a family having the
397 list of names (even if that list is empty), and the following members having
398 null for the list. The names list must be NULL-terminated
399 */
400 static const FontInitRec gSystemFonts[] = {
401 { "DroidSans.ttf", gSansNames },
402 { "DroidSans-Bold.ttf", NULL },
403 { "DroidSerif-Regular.ttf", gSerifNames },
404 { "DroidSerif-Bold.ttf", NULL },
405 { "DroidSerif-Italic.ttf", NULL },
406 { "DroidSerif-BoldItalic.ttf", NULL },
407 { "DroidSansMono.ttf", gMonoNames },
408 /* These are optional, and can be ignored if not found in the file system.
409 These are appended to gFallbackFonts[] as they are seen, so we list
410 them in the order we want them to be accessed by NextLogicalFont().
411 */
412 { "DroidSansArabic.ttf", gFBNames },
413 { "DroidSansHebrew.ttf", gFBNames },
414 { "DroidSansThai.ttf", gFBNames },
415 { "MTLmr3m.ttf", gFBNames }, // Motoya Japanese Font
416 { "MTLc3m.ttf", gFBNames }, // Motoya Japanese Font
417 { "DroidSansJapanese.ttf", gFBNames },
418 { "DroidSansFallback.ttf", gFBNames }
419 };
421 #define DEFAULT_NAMES gSansNames
423 // these globals are assigned (once) by load_system_fonts()
424 static FamilyRec* gDefaultFamily;
425 static SkTypeface* gDefaultNormal;
427 /* This is sized conservatively, assuming that it will never be a size issue.
428 It will be initialized in load_system_fonts(), and will be filled with the
429 fontIDs that can be used for fallback consideration, in sorted order (sorted
430 meaning element[0] should be used first, then element[1], etc. When we hit
431 a fontID==0 in the array, the list is done, hence our allocation size is
432 +1 the total number of possible system fonts. Also see NextLogicalFont().
433 */
434 static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
436 /* Called once (ensured by the sentinel check at the beginning of our body).
437 Initializes all the globals, and register the system fonts.
438 */
439 static void load_system_fonts() {
440 // check if we've already be called
441 if (NULL != gDefaultNormal) {
442 return;
443 }
445 const FontInitRec* rec = gSystemFonts;
446 SkTypeface* firstInFamily = NULL;
447 int fallbackCount = 0;
449 for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
450 // if we're the first in a new family, clear firstInFamily
451 if (rec[i].fNames != NULL) {
452 firstInFamily = NULL;
453 }
455 bool isFixedWidth;
456 SkString name;
457 SkTypeface::Style style;
459 // we expect all the fonts, except the "fallback" fonts
460 bool isExpected = (rec[i].fNames != gFBNames);
461 if (!get_name_and_style(rec[i].fFileName, &name, &style,
462 &isFixedWidth, isExpected)) {
463 continue;
464 }
466 SkTypeface* tf = SkNEW_ARGS(FileTypeface,
467 (style,
468 true, // system-font (cannot delete)
469 firstInFamily, // what family to join
470 rec[i].fFileName,
471 isFixedWidth) // filename
472 );
474 if (rec[i].fNames != NULL) {
475 // see if this is one of our fallback fonts
476 if (rec[i].fNames == gFBNames) {
477 // SkDebugf("---- adding %s as fallback[%d] fontID %d\n",
478 // rec[i].fFileName, fallbackCount, tf->uniqueID());
479 gFallbackFonts[fallbackCount++] = tf->uniqueID();
480 }
482 firstInFamily = tf;
483 FamilyRec* family = find_family(tf);
484 const char* const* names = rec[i].fNames;
486 // record the default family if this is it
487 if (names == DEFAULT_NAMES) {
488 gDefaultFamily = family;
489 }
490 // add the names to map to this family
491 while (*names) {
492 add_name(*names, family);
493 names += 1;
494 }
495 }
496 }
498 // do this after all fonts are loaded. This is our default font, and it
499 // acts as a sentinel so we only execute load_system_fonts() once
500 gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal);
501 // now terminate our fallback list with the sentinel value
502 gFallbackFonts[fallbackCount] = 0;
503 }
505 void FamilyTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
506 bool* isLocalStream) const {
507 {
508 SkAutoMutexAcquire ac(gFamilyMutex);
509 //desc->setFamilyName(find_family_name(this));
510 desc->setFontFileName(this->getUniqueString());
511 }
512 *isLocalStream = !this->isSysFont();
513 }
515 ///////////////////////////////////////////////////////////////////////////////
517 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
518 const char familyName[],
519 SkTypeface::Style style) {
520 load_system_fonts();
522 SkAutoMutexAcquire ac(gFamilyMutex);
524 // clip to legal style bits
525 style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
527 SkTypeface* tf = NULL;
529 if (NULL != familyFace) {
530 tf = find_typeface(familyFace, style);
531 } else if (NULL != familyName) {
532 // SkDebugf("======= familyName <%s>\n", familyName);
533 tf = find_typeface(familyName, style);
534 }
536 if (NULL == tf) {
537 tf = find_best_face(gDefaultFamily, style);
538 }
540 // we ref(), since the symantic is to return a new instance
541 tf->ref();
542 return tf;
543 }
545 SkTypeface* SkAndroidNextLogicalTypeface(SkFontID currFontID, SkFontID origFontID,
546 const SkPaintOptionsAndroid& options) {
547 load_system_fonts();
549 /* First see if fontID is already one of our fallbacks. If so, return
550 its successor. If fontID is not in our list, then return the first one
551 in our list. Note: list is zero-terminated, and returning zero means
552 we have no more fonts to use for fallbacks.
553 */
554 const uint32_t* list = gFallbackFonts;
555 for (int i = 0; list[i] != 0; i++) {
556 if (list[i] == currFontID) {
557 return find_from_uniqueID(list[i+1]);
558 }
559 }
560 return find_from_uniqueID(list[0]);
561 }
563 ///////////////////////////////////////////////////////////////////////////////
565 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
566 if (NULL == stream || stream->getLength() <= 0) {
567 return NULL;
568 }
570 bool isFixedWidth;
571 SkString name;
572 SkTypeface::Style style;
573 find_name_and_attributes(stream, &name, &style, &isFixedWidth);
575 if (!name.isEmpty()) {
576 return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth));
577 } else {
578 return NULL;
579 }
580 }
582 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
583 SkStream* stream = SkNEW_ARGS(SkFILEStream, (path));
584 SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
585 // since we created the stream, we let go of our ref() here
586 stream->unref();
587 return face;
588 }