old-android-fonthost.patch (19269B)
1 # HG changeset patch 2 # Parent 9ee29e4aace683ddf6cf8ddb2893cd34fcfc772c 3 # User James Willcox <jwillcox@mozilla.com> 4 diff --git a/gfx/skia/Makefile.in b/gfx/skia/Makefile.in 5 --- a/gfx/skia/Makefile.in 6 +++ b/gfx/skia/Makefile.in 7 @@ -305,21 +305,20 @@ CPPSRCS += \ 8 SkFontHost_mac_coretext.cpp \ 9 SkTime_Unix.cpp \ 10 $(NULL) 11 endif 12 13 ifeq (android,$(MOZ_WIDGET_TOOLKIT)) 14 CPPSRCS += \ 15 SkFontHost_FreeType.cpp \ 16 SkFontHost_android.cpp \ 17 SkFontHost_gamma.cpp \ 18 - FontHostConfiguration_android.cpp \ 19 SkMMapStream.cpp \ 20 SkTime_Unix.cpp \ 21 $(NULL) 22 23 DEFINES += -DSK_BUILD_FOR_ANDROID_NDK 24 OS_CXXFLAGS += $(CAIRO_FT_CFLAGS) 25 endif 26 27 ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT)) 28 CPPSRCS += \ 29 diff --git a/gfx/skia/src/ports/SkFontHost_android.cpp b/gfx/skia/src/ports/SkFontHost_android.cpp 30 --- a/gfx/skia/src/ports/SkFontHost_android.cpp 31 +++ b/gfx/skia/src/ports/SkFontHost_android.cpp 32 @@ -1,38 +1,31 @@ 33 + 34 /* 35 -** 36 -** Copyright 2006, The Android Open Source Project 37 -** 38 -** Licensed under the Apache License, Version 2.0 (the "License"); 39 -** you may not use this file except in compliance with the License. 40 -** You may obtain a copy of the License at 41 -** 42 -** http://www.apache.org/licenses/LICENSE-2.0 43 -** 44 -** Unless required by applicable law or agreed to in writing, software 45 -** distributed under the License is distributed on an "AS IS" BASIS, 46 -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 47 -** See the License for the specific language governing permissions and 48 -** limitations under the License. 49 -*/ 50 + * Copyright 2006 The Android Open Source Project 51 + * 52 + * Use of this source code is governed by a BSD-style license that can be 53 + * found in the LICENSE file. 54 + */ 55 + 56 57 #include "SkFontHost.h" 58 #include "SkDescriptor.h" 59 #include "SkMMapStream.h" 60 #include "SkPaint.h" 61 #include "SkString.h" 62 #include "SkStream.h" 63 #include "SkThread.h" 64 #include "SkTSearch.h" 65 -#include "FontHostConfiguration_android.h" 66 #include <stdio.h> 67 68 +#define FONT_CACHE_MEMORY_BUDGET (768 * 1024) 69 + 70 #ifndef SK_FONT_FILE_PREFIX 71 #define SK_FONT_FILE_PREFIX "/fonts/" 72 #endif 73 74 SkTypeface::Style find_name_and_attributes(SkStream* stream, SkString* name, 75 bool* isFixedWidth); 76 77 static void GetFullPathForSysFonts(SkString* full, const char name[]) { 78 full->set(getenv("ANDROID_ROOT")); 79 full->append(SK_FONT_FILE_PREFIX); 80 @@ -99,21 +92,21 @@ static SkTypeface* find_best_face(const 81 if (faces[SkTypeface::kNormal] != NULL) { 82 return faces[SkTypeface::kNormal]; 83 } 84 // look for anything 85 for (int i = 0; i < 4; i++) { 86 if (faces[i] != NULL) { 87 return faces[i]; 88 } 89 } 90 // should never get here, since the faces list should not be empty 91 - SkDEBUGFAIL("faces list is empty"); 92 + SkASSERT(!"faces list is empty"); 93 return NULL; 94 } 95 96 static FamilyRec* find_family(const SkTypeface* member) { 97 FamilyRec* curr = gFamilyHead; 98 while (curr != NULL) { 99 for (int i = 0; i < 4; i++) { 100 if (curr->fFaces[i] == member) { 101 return curr; 102 } 103 @@ -138,31 +131,27 @@ static SkTypeface* find_from_uniqueID(ui 104 curr = curr->fNext; 105 } 106 return NULL; 107 } 108 109 /* Remove reference to this face from its family. If the resulting family 110 is empty (has no faces), return that family, otherwise return NULL 111 */ 112 static FamilyRec* remove_from_family(const SkTypeface* face) { 113 FamilyRec* family = find_family(face); 114 - if (family) { 115 - SkASSERT(family->fFaces[face->style()] == face); 116 - family->fFaces[face->style()] = NULL; 117 + SkASSERT(family->fFaces[face->style()] == face); 118 + family->fFaces[face->style()] = NULL; 119 120 - for (int i = 0; i < 4; i++) { 121 - if (family->fFaces[i] != NULL) { // family is non-empty 122 - return NULL; 123 - } 124 + for (int i = 0; i < 4; i++) { 125 + if (family->fFaces[i] != NULL) { // family is non-empty 126 + return NULL; 127 } 128 - } else { 129 -// SkDebugf("remove_from_family(%p) face not found", face); 130 } 131 return family; // return the empty family 132 } 133 134 // maybe we should make FamilyRec be doubly-linked 135 static void detach_and_delete_family(FamilyRec* family) { 136 FamilyRec* curr = gFamilyHead; 137 FamilyRec* prev = NULL; 138 139 while (curr != NULL) { 140 @@ -172,21 +161,21 @@ static void detach_and_delete_family(Fam 141 gFamilyHead = next; 142 } else { 143 prev->fNext = next; 144 } 145 SkDELETE(family); 146 return; 147 } 148 prev = curr; 149 curr = next; 150 } 151 - SkDEBUGFAIL("Yikes, couldn't find family in our list to remove/delete"); 152 + SkASSERT(!"Yikes, couldn't find family in our list to remove/delete"); 153 } 154 155 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { 156 NameFamilyPair* list = gNameList.begin(); 157 int count = gNameList.count(); 158 159 int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); 160 161 if (index >= 0) { 162 return find_best_face(list[index].fFamily, style); 163 @@ -387,111 +376,90 @@ static bool get_name_and_style(const cha 164 } 165 return false; 166 } 167 168 // used to record our notion of the pre-existing fonts 169 struct FontInitRec { 170 const char* fFileName; 171 const char* const* fNames; // null-terminated list 172 }; 173 174 +static const char* gSansNames[] = { 175 + "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL 176 +}; 177 + 178 +static const char* gSerifNames[] = { 179 + "serif", "times", "times new roman", "palatino", "georgia", "baskerville", 180 + "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL 181 +}; 182 + 183 +static const char* gMonoNames[] = { 184 + "monospace", "courier", "courier new", "monaco", NULL 185 +}; 186 + 187 // deliberately empty, but we use the address to identify fallback fonts 188 static const char* gFBNames[] = { NULL }; 189 190 +/* Fonts must be grouped by family, with the first font in a family having the 191 + list of names (even if that list is empty), and the following members having 192 + null for the list. The names list must be NULL-terminated 193 +*/ 194 +static const FontInitRec gSystemFonts[] = { 195 + { "DroidSans.ttf", gSansNames }, 196 + { "DroidSans-Bold.ttf", NULL }, 197 + { "DroidSerif-Regular.ttf", gSerifNames }, 198 + { "DroidSerif-Bold.ttf", NULL }, 199 + { "DroidSerif-Italic.ttf", NULL }, 200 + { "DroidSerif-BoldItalic.ttf", NULL }, 201 + { "DroidSansMono.ttf", gMonoNames }, 202 + /* These are optional, and can be ignored if not found in the file system. 203 + These are appended to gFallbackFonts[] as they are seen, so we list 204 + them in the order we want them to be accessed by NextLogicalFont(). 205 + */ 206 + { "DroidSansArabic.ttf", gFBNames }, 207 + { "DroidSansHebrew.ttf", gFBNames }, 208 + { "DroidSansThai.ttf", gFBNames }, 209 + { "MTLmr3m.ttf", gFBNames }, // Motoya Japanese Font 210 + { "MTLc3m.ttf", gFBNames }, // Motoya Japanese Font 211 + { "DroidSansJapanese.ttf", gFBNames }, 212 + { "DroidSansFallback.ttf", gFBNames } 213 +}; 214 215 -/* Fonts are grouped by family, with the first font in a family having the 216 - list of names (even if that list is empty), and the following members having 217 - null for the list. The names list must be NULL-terminated. 218 -*/ 219 -static FontInitRec *gSystemFonts; 220 -static size_t gNumSystemFonts = 0; 221 - 222 -#define SYSTEM_FONTS_FILE "/system/etc/system_fonts.cfg" 223 +#define DEFAULT_NAMES gSansNames 224 225 // these globals are assigned (once) by load_system_fonts() 226 static FamilyRec* gDefaultFamily; 227 static SkTypeface* gDefaultNormal; 228 -static char** gDefaultNames = NULL; 229 -static uint32_t *gFallbackFonts; 230 231 -/* Load info from a configuration file that populates the system/fallback font structures 232 -*/ 233 -static void load_font_info() { 234 -// load_font_info_xml("/system/etc/system_fonts.xml"); 235 - SkTDArray<FontFamily*> fontFamilies; 236 - getFontFamilies(fontFamilies); 237 - 238 - SkTDArray<FontInitRec> fontInfo; 239 - bool firstInFamily = false; 240 - for (int i = 0; i < fontFamilies.count(); ++i) { 241 - FontFamily *family = fontFamilies[i]; 242 - firstInFamily = true; 243 - for (int j = 0; j < family->fFileNames.count(); ++j) { 244 - FontInitRec fontInfoRecord; 245 - fontInfoRecord.fFileName = family->fFileNames[j]; 246 - if (j == 0) { 247 - if (family->fNames.count() == 0) { 248 - // Fallback font 249 - fontInfoRecord.fNames = (char **)gFBNames; 250 - } else { 251 - SkTDArray<const char*> names = family->fNames; 252 - const char **nameList = (const char**) 253 - malloc((names.count() + 1) * sizeof(char*)); 254 - if (nameList == NULL) { 255 - // shouldn't get here 256 - break; 257 - } 258 - if (gDefaultNames == NULL) { 259 - gDefaultNames = (char**) nameList; 260 - } 261 - for (int i = 0; i < names.count(); ++i) { 262 - nameList[i] = names[i]; 263 - } 264 - nameList[names.count()] = NULL; 265 - fontInfoRecord.fNames = nameList; 266 - } 267 - } else { 268 - fontInfoRecord.fNames = NULL; 269 - } 270 - *fontInfo.append() = fontInfoRecord; 271 - } 272 - } 273 - gNumSystemFonts = fontInfo.count(); 274 - gSystemFonts = (FontInitRec*) malloc(gNumSystemFonts * sizeof(FontInitRec)); 275 - gFallbackFonts = (uint32_t*) malloc((gNumSystemFonts + 1) * sizeof(uint32_t)); 276 - if (gSystemFonts == NULL) { 277 - // shouldn't get here 278 - gNumSystemFonts = 0; 279 - } 280 - for (size_t i = 0; i < gNumSystemFonts; ++i) { 281 - gSystemFonts[i].fFileName = fontInfo[i].fFileName; 282 - gSystemFonts[i].fNames = fontInfo[i].fNames; 283 - } 284 - fontFamilies.deleteAll(); 285 -} 286 +/* This is sized conservatively, assuming that it will never be a size issue. 287 + It will be initialized in load_system_fonts(), and will be filled with the 288 + fontIDs that can be used for fallback consideration, in sorted order (sorted 289 + meaning element[0] should be used first, then element[1], etc. When we hit 290 + a fontID==0 in the array, the list is done, hence our allocation size is 291 + +1 the total number of possible system fonts. Also see NextLogicalFont(). 292 + */ 293 +static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1]; 294 295 /* Called once (ensured by the sentinel check at the beginning of our body). 296 Initializes all the globals, and register the system fonts. 297 */ 298 static void load_system_fonts() { 299 // check if we've already be called 300 if (NULL != gDefaultNormal) { 301 return; 302 } 303 304 - load_font_info(); 305 - 306 const FontInitRec* rec = gSystemFonts; 307 SkTypeface* firstInFamily = NULL; 308 int fallbackCount = 0; 309 310 - for (size_t i = 0; i < gNumSystemFonts; i++) { 311 + for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) { 312 // if we're the first in a new family, clear firstInFamily 313 if (rec[i].fNames != NULL) { 314 firstInFamily = NULL; 315 } 316 317 bool isFixedWidth; 318 SkString name; 319 SkTypeface::Style style; 320 321 // we expect all the fonts, except the "fallback" fonts 322 @@ -515,120 +483,75 @@ static void load_system_fonts() { 323 // SkDebugf("---- adding %s as fallback[%d] fontID %d\n", 324 // rec[i].fFileName, fallbackCount, tf->uniqueID()); 325 gFallbackFonts[fallbackCount++] = tf->uniqueID(); 326 } 327 328 firstInFamily = tf; 329 FamilyRec* family = find_family(tf); 330 const char* const* names = rec[i].fNames; 331 332 // record the default family if this is it 333 - if (names == gDefaultNames) { 334 + if (names == DEFAULT_NAMES) { 335 gDefaultFamily = family; 336 } 337 // add the names to map to this family 338 while (*names) { 339 add_name(*names, family); 340 names += 1; 341 } 342 } 343 } 344 345 // do this after all fonts are loaded. This is our default font, and it 346 // acts as a sentinel so we only execute load_system_fonts() once 347 gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal); 348 // now terminate our fallback list with the sentinel value 349 gFallbackFonts[fallbackCount] = 0; 350 } 351 352 /////////////////////////////////////////////////////////////////////////////// 353 354 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { 355 - // lookup and record if the font is custom (i.e. not a system font) 356 - bool isCustomFont = !((FamilyTypeface*)face)->isSysFont(); 357 - stream->writeBool(isCustomFont); 358 + const char* name = ((FamilyTypeface*)face)->getUniqueString(); 359 360 - if (isCustomFont) { 361 - SkStream* fontStream = ((FamilyTypeface*)face)->openStream(); 362 + stream->write8((uint8_t)face->style()); 363 364 - // store the length of the custom font 365 - uint32_t len = fontStream->getLength(); 366 - stream->write32(len); 367 - 368 - // store the entire font in the serialized stream 369 - void* fontData = malloc(len); 370 - 371 - fontStream->read(fontData, len); 372 - stream->write(fontData, len); 373 - 374 - fontStream->unref(); 375 - free(fontData); 376 -// SkDebugf("--- fonthost custom serialize %d %d\n", face->style(), len); 377 - 378 + if (NULL == name || 0 == *name) { 379 + stream->writePackedUInt(0); 380 +// SkDebugf("--- fonthost serialize null\n"); 381 } else { 382 - const char* name = ((FamilyTypeface*)face)->getUniqueString(); 383 - 384 - stream->write8((uint8_t)face->style()); 385 - 386 - if (NULL == name || 0 == *name) { 387 - stream->writePackedUInt(0); 388 -// SkDebugf("--- fonthost serialize null\n"); 389 - } else { 390 - uint32_t len = strlen(name); 391 - stream->writePackedUInt(len); 392 - stream->write(name, len); 393 -// SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style()); 394 - } 395 + uint32_t len = strlen(name); 396 + stream->writePackedUInt(len); 397 + stream->write(name, len); 398 +// SkDebugf("--- fonthost serialize <%s> %d\n", name, face->style()); 399 } 400 } 401 402 SkTypeface* SkFontHost::Deserialize(SkStream* stream) { 403 load_system_fonts(); 404 405 - // check if the font is a custom or system font 406 - bool isCustomFont = stream->readBool(); 407 + int style = stream->readU8(); 408 409 - if (isCustomFont) { 410 + int len = stream->readPackedUInt(); 411 + if (len > 0) { 412 + SkString str; 413 + str.resize(len); 414 + stream->read(str.writable_str(), len); 415 416 - // read the length of the custom font from the stream 417 - uint32_t len = stream->readU32(); 418 - 419 - // generate a new stream to store the custom typeface 420 - SkMemoryStream* fontStream = new SkMemoryStream(len); 421 - stream->read((void*)fontStream->getMemoryBase(), len); 422 - 423 - SkTypeface* face = CreateTypefaceFromStream(fontStream); 424 - 425 - fontStream->unref(); 426 - 427 -// SkDebugf("--- fonthost custom deserialize %d %d\n", face->style(), len); 428 - return face; 429 - 430 - } else { 431 - int style = stream->readU8(); 432 - 433 - int len = stream->readPackedUInt(); 434 - if (len > 0) { 435 - SkString str; 436 - str.resize(len); 437 - stream->read(str.writable_str(), len); 438 - 439 - const FontInitRec* rec = gSystemFonts; 440 - for (size_t i = 0; i < gNumSystemFonts; i++) { 441 - if (strcmp(rec[i].fFileName, str.c_str()) == 0) { 442 - // backup until we hit the fNames 443 - for (int j = i; j >= 0; --j) { 444 - if (rec[j].fNames != NULL) { 445 - return SkFontHost::CreateTypeface(NULL, 446 - rec[j].fNames[0], NULL, 0, 447 - (SkTypeface::Style)style); 448 - } 449 + const FontInitRec* rec = gSystemFonts; 450 + for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) { 451 + if (strcmp(rec[i].fFileName, str.c_str()) == 0) { 452 + // backup until we hit the fNames 453 + for (int j = i; j >= 0; --j) { 454 + if (rec[j].fNames != NULL) { 455 + return SkFontHost::CreateTypeface(NULL, 456 + rec[j].fNames[0], NULL, 0, (SkTypeface::Style)style); 457 } 458 } 459 } 460 } 461 } 462 return NULL; 463 } 464 465 /////////////////////////////////////////////////////////////////////////////// 466 467 @@ -697,49 +620,32 @@ size_t SkFontHost::GetFileName(SkFontID 468 } 469 return size; 470 } else { 471 return 0; 472 } 473 } 474 475 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { 476 load_system_fonts(); 477 478 - const SkTypeface* origTypeface = find_from_uniqueID(origFontID); 479 - const SkTypeface* currTypeface = find_from_uniqueID(currFontID); 480 - 481 - SkASSERT(origTypeface != 0); 482 - SkASSERT(currTypeface != 0); 483 - 484 - // Our fallback list always stores the id of the plain in each fallback 485 - // family, so we transform currFontID to its plain equivalent. 486 - currFontID = find_typeface(currTypeface, SkTypeface::kNormal)->uniqueID(); 487 - 488 /* First see if fontID is already one of our fallbacks. If so, return 489 its successor. If fontID is not in our list, then return the first one 490 in our list. Note: list is zero-terminated, and returning zero means 491 we have no more fonts to use for fallbacks. 492 */ 493 const uint32_t* list = gFallbackFonts; 494 for (int i = 0; list[i] != 0; i++) { 495 if (list[i] == currFontID) { 496 - if (list[i+1] == 0) 497 - return 0; 498 - const SkTypeface* nextTypeface = find_from_uniqueID(list[i+1]); 499 - return find_typeface(nextTypeface, origTypeface->style())->uniqueID(); 500 + return list[i+1]; 501 } 502 } 503 - 504 - // If we get here, currFontID was not a fallback, so we start at the 505 - // beginning of our list. 506 - const SkTypeface* firstTypeface = find_from_uniqueID(list[0]); 507 - return find_typeface(firstTypeface, origTypeface->style())->uniqueID(); 508 + return list[0]; 509 } 510 511 /////////////////////////////////////////////////////////////////////////////// 512 513 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 514 if (NULL == stream || stream->getLength() <= 0) { 515 return NULL; 516 } 517 518 bool isFixedWidth; 519 @@ -754,10 +660,11 @@ SkTypeface* SkFontHost::CreateTypefaceFr 520 } 521 522 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 523 SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path)); 524 SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream); 525 // since we created the stream, we let go of our ref() here 526 stream->unref(); 527 return face; 528 } 529 530 +///////////////////////////////////////////////////////////////////////////////