/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Brian Stell * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include #include "prmem.h" #include "nsCRT.h" #include "nsICharRepresentable.h" #include "nsCompressedCharMap.h" void FreeCCMap(PRUint16* &aMap) { if (!aMap) return; PR_Free(aMap - CCMAP_EXTRA); aMap = nsnull; } PRUint16* MapToCCMap(PRUint32* aMap) { // put the data into a temp map nsCompressedCharMap ccmapObj; ccmapObj.SetChars(aMap); PRUint16 *ccmap = (PRUint16*)PR_Malloc((CCMAP_EXTRA + ccmapObj.GetSize()) * sizeof(PRUint16)); NS_ASSERTION(ccmap, "failed to alloc new CCMap"); if (!ccmap) return nsnull; ccmap += CCMAP_EXTRA; CCMAP_SIZE(ccmap) = ccmapObj.GetSize(); CCMAP_FLAG(ccmap) = CCMAP_NONE_FLAG; ccmapObj.FillCCMap(ccmap); #ifdef DEBUG for (int i=0; iFillInfo(map); if (NS_FAILED(res)) return nsnull; PRUint16* ccMap = MapToCCMap(map); return ccMap; } PRBool NextNonEmptyCCMapPage(const PRUint16* aCCMap, PRUint32 *aPageStart) { int i, j, l; int planeend = 0; int planestart = 0; unsigned int k; const PRUint16* ccmap; PRUint32 pagestart = *aPageStart; if(CCMAP_FLAG(aCCMap) & CCMAP_SURROGATE_FLAG) { // for SURROGATE planeend = EXTENDED_UNICODE_PLANES; } if(pagestart != CCMAP_BEGIN_AT_START_OF_MAP) { planestart = CCMAP_PLANE(pagestart); } // checking each plane for(l=planestart; l<=planeend; l++, pagestart = CCMAP_BEGIN_AT_START_OF_MAP) { if(l != 0 && CCMAP_FLAG(aCCMap) & CCMAP_SURROGATE_FLAG) { // for SURROGATE - get ccmap per plane ccmap = CCMAP_FOR_PLANE_EXT(aCCMap, l); } else { // only BMP ccmap = aCCMap; } // // Point to the next page // unsigned int upper_index; unsigned int mid_index; if (pagestart == CCMAP_BEGIN_AT_START_OF_MAP) { upper_index = 0; mid_index = 0; } else { upper_index = CCMAP_UPPER_INDEX(pagestart & 0xffff); mid_index = CCMAP_MID_INDEX(pagestart & 0xffff) + 1; } // walk thru the upper pointers const PRUint16 *upper = &ccmap[0]; for (i=upper_index; i CCMAP_BITS_PER_PRUINT32) int j, k = CCMAP_BITS_PER_PRUINT32; ALU_TYPE page[CCMAP_NUM_ALUS_PER_PAGE]; ALU_TYPE *p = page; for (j=0; j>= CCMAP_BITS_PER_ALU; } } SetChars(base, page); #endif base += CCMAP_NUM_UCHARS_PER_PAGE; } } #ifdef DEBUG void printCCMap(PRUint16* aCCMap) { PRUint32 page = CCMAP_BEGIN_AT_START_OF_MAP; while (NextNonEmptyCCMapPage(aCCMap, &page)) { //FONT_SCAN_PRINTF(("page starting at 0x%04x has chars", page)); int i; PRUint32 pagechar = page; printf("CCMap:0x%04lx=", (long)page); for (i=0; i<(CCMAP_BITS_PER_PAGE/8); i++) { unsigned char val = 0; for (int j=0; j<8; j++) { if (CCMAP_HAS_CHAR(aCCMap, pagechar)) { val |= 1 << j; } pagechar++; } printf("%02x", val); } printf("\n"); } } #endif // 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 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 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; }