short nsUnicodeFontMappingMac::GetFontID(PRUnichar aChar) { // initialize to bogus values short firstSymbolicFont = BAD_FONT_NUM, firstNonSymbolicFont = BAD_FONT_NUM; PRInt32 firstSymbolicFontIndex = -1; // Trap invisible chars if (CCMAP_HAS_CHAR_EXT(gIgnorableCCMapExt, aChar)) { return IGNORABLE_FONT_NUM; } // find the first symbolic font that has a glyph for aChar // and if there is one, remember it's index in the font list for(PRInt32 i = 0; i < mFontList.Count(); i++) { nsUnicodeFontMappingEntry* entry = (nsUnicodeFontMappingEntry*) mFontList[i]; PRUint16 *ccmap = entry->GetCCMap(); if(ccmap && CCMAP_HAS_CHAR(ccmap, aChar)) { firstSymbolicFontIndex = i; firstSymbolicFont = entry->GetFontNum(); break; } } // find the first non-symbolic font that has a glyph for aChar nsUnicodeBlock block = GetBlock(aChar); if(block < kUnicodeBlockFixedScriptMax) { firstNonSymbolicFont = mScriptFallbackFontIDs[gUtil->BlockToScript(block)]; // if there was no symbolic font we don't need to loop through the list again if(firstSymbolicFont == BAD_FONT_NUM) return firstNonSymbolicFont; // find the index of the first non symbolic font in the list and return the // first font (symbolic or non symbolic) in the list that has a glyph for this char for(PRInt32 i = 0; i < mFontList.Count(); i++) { nsUnicodeFontMappingEntry* entry = (nsUnicodeFontMappingEntry*) mFontList[i]; if(entry->GetFontNum() == firstNonSymbolicFont) { return (firstSymbolicFontIndex < i ? firstSymbolicFont : firstNonSymbolicFont); } } return firstNonSymbolicFont; } return (firstSymbolicFont != BAD_FONT_NUM ? firstSymbolicFont : mScriptFallbackFontIDs[ mPrivBlockToScript[ block - kUnicodeBlockFixedScriptMax] ]); }
void nsCompressedCharMap::SetChars(PRUint16* aCCMap) { int i, j; if(mExtended){ PRUint32 page = CCMAP_BEGIN_AT_START_OF_MAP; while (NextNonEmptyCCMapPage(aCCMap, &page)) { PRUint32 pagechar = page; for (i=0; i<(CCMAP_BITS_PER_PAGE/8); i++) { for (j=0; j<8; j++) { if (CCMAP_HAS_CHAR_EXT(aCCMap, pagechar)) { SetChar(pagechar); } pagechar++; } } } } else { // // Copy the input CCMap // // walk thru the upper pointers PRUint16 *upper = &aCCMap[0]; for (i=0; i<CCMAP_NUM_UPPER_POINTERS; i++) { if (upper[i] == CCMAP_EMPTY_MID) continue; // walk the mid array PRUint16 *mid = &aCCMap[upper[i]]; for (j=0; j<CCMAP_NUM_MID_POINTERS; j++) { if (mid[j] == CCMAP_EMPTY_PAGE) continue; PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE); NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address"); ALU_TYPE *page = (ALU_TYPE*)&aCCMap[mid[j]]; SetChars((PRUint16)base, page); } } } }
// Non-BMP unicode support extension, create ccmap for both BMP and extended planes PRUint16* MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOtherPlaneNum) { nsCompressedCharMap* otherPlaneObj[EXTENDED_UNICODE_PLANES]; PRUint32 totalSize; PRUint16 i; PRUint32 *planeCCMapOffsets; PRUint32 currOffset; NS_ASSERTION(aOtherPlaneNum <= EXTENDED_UNICODE_PLANES, "illegal argument value"); if (aOtherPlaneNum > EXTENDED_UNICODE_PLANES) return nsnull; // Put the data into a temp map nsCompressedCharMap bmpCcmapObj; bmpCcmapObj.SetChars(aBmpPlaneMap); // Add bmp size totalSize = bmpCcmapObj.GetSize(); // Add bmp length field totalSize += CCMAP_EXTRA; // Add Plane array totalSize += EXTENDED_UNICODE_PLANES * sizeof(PRUint32)/sizeof(PRUint16); // Add an empty plane ccmap // A totally empty plane ccmap can be represented by 16 *(PRUint16)0. totalSize += CCMAP_EMPTY_SIZE_PER_INT16; // Create ccmap for other planes for (i = 0; i < aOtherPlaneNum; i++) { if (aOtherPlaneMaps[i]) { otherPlaneObj[i] = new nsCompressedCharMap(); NS_ASSERTION(otherPlaneObj, "unable to create new nsCompressedCharMap"); if(otherPlaneObj) { otherPlaneObj[i]->SetChars(aOtherPlaneMaps[i]); totalSize += otherPlaneObj[i]->GetSize(); } } else { otherPlaneObj[i] = nsnull; } } PRUint16 *ccmap = (PRUint16*)PR_Malloc(totalSize * sizeof(PRUint16)); NS_ASSERTION(ccmap, "failed to alloc new CCMap"); if (!ccmap) return nsnull; // Assign BMP ccmap size ccmap += CCMAP_EXTRA; CCMAP_SIZE(ccmap) = bmpCcmapObj.GetSize(); CCMAP_FLAG(ccmap) = CCMAP_SURROGATE_FLAG; // Fill bmp plane ccmap bmpCcmapObj.FillCCMap(ccmap); // Get pointer for plane ccmap offset array currOffset = bmpCcmapObj.GetSize(); planeCCMapOffsets = (PRUint32*)(ccmap+currOffset); currOffset += sizeof(PRUint32)/sizeof(PRUint16)*EXTENDED_UNICODE_PLANES; // Put a empty ccmap there memset(ccmap+currOffset, '\0', sizeof(PRUint16)*16); PRUint32 emptyCCMapOffset = currOffset; currOffset += CCMAP_EMPTY_SIZE_PER_INT16; // Now fill all rest of the planes' ccmap and put off in array for (i = 0; i <aOtherPlaneNum; i++) { if (aOtherPlaneMaps[i] && otherPlaneObj[i]) { *(planeCCMapOffsets+i) = currOffset; otherPlaneObj[i]->FillCCMap(ccmap+currOffset); currOffset += otherPlaneObj[i]->GetSize(); } else *(planeCCMapOffsets+i) = emptyCCMapOffset; } for (; i < EXTENDED_UNICODE_PLANES; i++) { *(planeCCMapOffsets+i) = emptyCCMapOffset; } // remove all nsCompressedCharMap objects allocated for (i = 0; i < aOtherPlaneNum; i++) { if (otherPlaneObj[i]) delete otherPlaneObj[i]; } #ifdef DEBUG PRUint32 k, h, l, plane, offset; PRBool oldb; PRBool newb; // testing for BMP plane for (k=0; k<NUM_UNICODE_CHARS; k++) { oldb = IS_REPRESENTABLE(aBmpPlaneMap, k); newb = CCMAP_HAS_CHAR_EXT(ccmap, k); NS_ASSERTION(oldb==newb,"failed to generate map correctly"); } //testing for extension plane for (k = 0x10000; k < 0x100000; k++) { plane = k/0x10000; if (plane > aOtherPlaneNum) break; if (aOtherPlaneMaps[plane-1]) oldb = IS_REPRESENTABLE(aOtherPlaneMaps[plane-1], k&0xffff); else oldb = 0; newb = CCMAP_HAS_CHAR_EXT(ccmap, k); NS_ASSERTION(oldb==newb, "failed to generate extension map correctly"); } // testing for non-BMP plane for (h = 0; h < 0x400; h++) { for (l = 0; l < 0x400; l++) { plane = h >> 6; offset = (h*0x400 + l) & 0xffff; if (aOtherPlaneMaps[plane]) oldb = IS_REPRESENTABLE(aOtherPlaneMaps[plane], offset); else oldb = 0; newb = CCMAP_HAS_CHAR_EXT2(ccmap, h+0xd800, l+0xdc00); NS_ASSERTION(oldb==newb, "failed to generate extension map correctly"); } } #endif return ccmap; }