From a8f2223a1d044f1bd7e18d912d79360306734818 Mon Sep 17 00:00:00 2001 From: "ftang%netscape.com" Date: Tue, 21 Aug 2001 22:14:56 +0000 Subject: [PATCH] new file for 90804. not part of the build yet --- gfx/src/mac/nsMacUnicodeFontInfo.cpp | 413 +++++++++++++++++++++++++++ gfx/src/mac/nsMacUnicodeFontInfo.h | 37 +++ 2 files changed, 450 insertions(+) create mode 100644 gfx/src/mac/nsMacUnicodeFontInfo.cpp create mode 100644 gfx/src/mac/nsMacUnicodeFontInfo.h diff --git a/gfx/src/mac/nsMacUnicodeFontInfo.cpp b/gfx/src/mac/nsMacUnicodeFontInfo.cpp new file mode 100644 index 000000000000..ce8398e42548 --- /dev/null +++ b/gfx/src/mac/nsMacUnicodeFontInfo.cpp @@ -0,0 +1,413 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ +#include "nsMacUnicodeFontInfo.h" +#include "nsCRT.h" +#include "prmem.h" +#include +#include "nsICharRepresentable.h" + +//#define TTDEBUG +//#define TTDEBUG1 +//#define TTDEBUG2 +//#define TRACK_INIT_PERFORMANCE + +#ifdef TRACK_INIT_PERFORMANCE +#include +#endif + +// this is an big endian version, not good for little endian machine +#undef GET_SHORT +#define GET_SHORT(p) (*((PRUint16*)p)) +#undef GET_LONG +#define GET_LONG(p) (*((PRUint32*)p)) + +#define ADD_GLYPH(a,b) SET_REPRESENTABLE(a,b) +#define FONT_HAS_GLYPH(a,b) IS_REPRESENTABLE(a,b) + +#undef SET_SPACE +#define SET_SPACE(c) ADD_GLYPH(spaces, c) +#undef SHOULD_BE_SPACE +#define SHOULD_BE_SPACE(c) FONT_HAS_GLYPH(spaces, c) + + +#define HEAD FOUR_CHAR_CODE('head') +#define LOCA FOUR_CHAR_CODE('loca') +#define CMAP FOUR_CHAR_CODE('cmap') + +#if TARGET_CARBON +static PRInt32 +GetIndexToLocFormat(FMFont aFont) +{ + PRUint16 indexToLocFormat; + ByteCount len = 0; + OSStatus err = FMGetFontTable(aFont, HEAD, 50, 2, &indexToLocFormat,nsnull); + if (err != noErr) { + return -1; + } + if (!indexToLocFormat) { + return 0; + } + return 1; +} + +static PRUint8* +GetSpaces(FMFont aFont, PRUint32* aMaxGlyph) +{ + int isLong = GetIndexToLocFormat(aFont); + if (isLong < 0) { + return nsnull; + } + ByteCount len; + OSStatus err = FMGetFontTable(aFont, LOCA, 0, 0, NULL, &len); + + if((err != noErr) || (!len)) { + return nsnull; + } + PRUint8* buf = (PRUint8*) PR_Malloc(len); + if (!buf) { + return nsnull; + } + ByteCount newLen; + err = FMGetFontTable(aFont, LOCA, 0, len, buf, &newLen); + if (newLen != len) { + PR_Free(buf); + return nsnull; + } + if (isLong) { + PRUint32 longLen = ((len / 4) - 1); + *aMaxGlyph = longLen; + PRUint32* longBuf = (PRUint32*) buf; + for (PRUint32 i = 0; i < longLen; i++) { + if (longBuf[i] == longBuf[i+1]) { + buf[i] = 1; + } + else { + buf[i] = 0; + } + } + } + else { + PRUint32 shortLen = ((len / 2) - 1); + *aMaxGlyph = shortLen; + PRUint16* shortBuf = (PRUint16*) buf; + for (PRUint16 i = 0; i < shortLen; i++) { + if (shortBuf[i] == shortBuf[i+1]) { + buf[i] = 1; + } + else { + buf[i] = 0; + } + } + } + + return buf; +} + +static PRBool FillFontInfoFromCMAP(FMFont aFont, PRUint32 *aFontInfo) +{ + ByteCount len; + OSErr err = FMGetFontTable(aFont, CMAP, 0, 0, NULL, &len); + if((err!=noErr) || (!len)) + { + return PR_FALSE; + } + PRUint8* buf = (PRUint8*) PR_Malloc(len); + if (!buf) { + return PR_FALSE; + } + ByteCount newLen; + err = FMGetFontTable(aFont, CMAP, 0, len, buf, &newLen); + if (newLen != len) { + PR_Free(buf); + return PR_FALSE; + } + PRUint8* p = buf + 2; + PRUint16 n = GET_SHORT(p); + p += 2; + PRUint16 i; + PRUint32 offset; + PRUint32 platformUnicodeOffset = 0; + // we look for platform =3 and encoding =1, + // if we cannot find it but there are a platform = 0 there, we + // remmeber that one and use it. + + for (i = 0; i < n; i++) { + PRUint16 platformID = GET_SHORT(p); + p += 2; + PRUint16 encodingID = GET_SHORT(p); + p += 2; + offset = GET_LONG(p); + p += 4; + +#ifdef TTDEBUG + printf("platformID = %d encodingID = %d\n", platformID, encodingID); +#endif + + if (platformID == 3) { + if (encodingID == 1) { // Unicode + // Some fonts claim to be unicode when they are actually + // 'pseudo-unicode' fonts that require a converter... +#ifdef TTDEBUG + printf("Get a font which have Window Unicode CMAP\n"); +#endif + break; // break out from for(;;) loop + } //if (encodingID == 1) + else if (encodingID == 0) { // symbol + PR_Free(buf); +#ifdef TTDEBUG + printf("Get a Symbol font\n"); +#endif + return PR_FALSE; + } + } // if (platformID == 3) + else { + if (platformID == 0) { // Unicode +#ifdef TTDEBUG + printf("Get a font which have Unicode CMAP\n"); +#endif + platformUnicodeOffset = offset; + } + } + } // for loop + + if ((i == n) && ( 0 == platformUnicodeOffset)) { +#ifdef TTDEBUG + printf("Get a font which do not have Window Unicode CMAP\n"); +#endif + PR_Free(buf); + return PR_FALSE; + } + + // usually, we come here for the entry platform = 3 encoding = 1 + // or if we don't have it but we have a platform = 0 (platformUnicodeOffset != 0) + if(platformUnicodeOffset) + offset = platformUnicodeOffset; + + p = buf + offset; + PRUint16 format = GET_SHORT(p); + if (format != 4) { +#ifdef TTDEBUG + printf("Unknow CMAP format\n"); +#endif + PR_Free(buf); + return PR_FALSE; + } + PRUint8* end = buf + len; + +#if 0 + // XXX byte swapping only required for little endian (ifdef?) + while (p < end) { + PRUint8 tmp = p[0]; + p[0] = p[1]; + p[1] = tmp; + p += 2; + } +#endif + + + PRUint16* s = (PRUint16*) (buf + offset); + PRUint16 segCount = s[3] / 2; + PRUint16* endCode = &s[7]; + PRUint16* startCode = endCode + segCount + 1; + PRUint16* idDelta = startCode + segCount; + PRUint16* idRangeOffset = idDelta + segCount; + PRUint16* glyphIdArray = idRangeOffset + segCount; + + static int spacesInitialized = 0; + static PRUint32 spaces[2048]; + if (!spacesInitialized) { + spacesInitialized = 1; + SET_SPACE(0x0020); + SET_SPACE(0x00A0); + for (PRUint16 c = 0x2000; c <= 0x200B; c++) { + SET_SPACE(c); + } + SET_SPACE(0x3000); + } + PRUint32 maxGlyph; + PRUint8* isSpace = GetSpaces(aFont, &maxGlyph); + if (!isSpace) { + PR_Free(buf); +#ifdef TTDEBUG + printf("Cannot get LOCA table\n"); +#endif + return PR_FALSE; + } + + for (i = 0; i < segCount; i++) { + if (idRangeOffset[i]) { + PRUint16 startC = startCode[i]; + PRUint16 endC = endCode[i]; + for (PRUint32 c = startC; c <= endC; c++) { + PRUint16* g = + (idRangeOffset[i]/2 + (c - startC) + &idRangeOffset[i]); + if ((PRUint8*) g < end) { + if (*g) { + PRUint16 glyph = idDelta[i] + *g; + if (glyph < maxGlyph) { + if (isSpace[glyph]) { + if (SHOULD_BE_SPACE(c)) { + ADD_GLYPH(aFontInfo, c); +#ifdef TTDEBUG1 + printf("%4x\n", c); +#endif + } + } + else { + ADD_GLYPH(aFontInfo, c); +#ifdef TTDEBUG1 + printf("%4x\n", c); +#endif + } + } + } + } + else { + // XXX should we trust this font at all if it does this? + } + } +#ifdef TTDEBUG + printf("0x%04X-0x%04X ", startC, endC); +#endif + } + else { + PRUint16 endC = endCode[i]; + for (PRUint32 c = startCode[i]; c <= endC; c++) { + PRUint16 glyph = idDelta[i] + c; + if (glyph < maxGlyph) { + if (isSpace[glyph]) { + if (SHOULD_BE_SPACE(c)) { + ADD_GLYPH(aFontInfo, c); +#ifdef TTDEBUG1 + printf("%4x\n", c); +#endif + } + } + else { + ADD_GLYPH(aFontInfo, c); +#ifdef TTDEBUG1 + printf("%4x\n", c); +#endif + } + } + } +#ifdef TTDEBUG + printf("0x%04X-0x%04X ", startCode[i], endC); +#endif + } + } +#ifdef TTDEBUG + printf("\n"); +#endif + + PR_Free(buf); + PR_Free(isSpace); + return PR_TRUE; +} +#endif + +PRBool nsMacUnicodeFontInfo::gGlobalFontInfoInit = PR_FALSE; +PRUint32 nsMacUnicodeFontInfo::gFontsCount = 0; +PRUint32 nsMacUnicodeFontInfo::gTTFFontsCount = 0; +PRUint32 nsMacUnicodeFontInfo::gGlyphCount = 0; +PRUint32 nsMacUnicodeFontInfo::gGlobalFontInfo[2048]; + +void nsMacUnicodeFontInfo::InitGolbal() +{ + if(gGlobalFontInfoInit) + return; + nsCRT::zero(gGlobalFontInfo, sizeof(gGlobalFontInfo)); + +#if TARGET_CARBON + +#ifdef TRACK_INIT_PERFORMANCE + AbsoluteTime startTime; + AbsoluteTime endTime; + startTime = UpTime(); +#endif + + FMFontFamilyIterator aFontIterator; + OSStatus status = 0; + FMFont aFont; + FourCharCode aFormat; + FMFontFamily aFontFamily; + status = FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, + &aFontIterator); + while (status == noErr) + { + status = FMGetNextFontFamily (&aFontIterator, &aFontFamily); + OSStatus status2; + FMFontStyle aStyle; + status2 = FMGetFontFromFontFamilyInstance(aFontFamily, 0, &aFont, &aStyle); + status2 = FMGetFontFormat (aFont, &aFormat); +#ifdef TTDEBUG + Str255 familyName; + status2 = FMGetFontFamilyName (aFontFamily, familyName); + const char *four = (const char*)&aFormat; + familyName[familyName[0]+1] = '\0'; + printf("%d %s format = %c%c%c%c\n", gFontsCount, familyName+1, *four, *(four+1) , *(four+2), *(four+3)); +#endif + gFontsCount++; + PRBool ret = FillFontInfoFromCMAP(aFont,gGlobalFontInfo); + + } + // Dispose of the contents of the font iterator. + status = FMDisposeFontFamilyIterator (&aFontIterator); +#ifdef TTDEBUG2 + printf("=== The following Unicode Could be render ===\n"); +#endif + + PRUint32 i; + for(i=0;i < 0x10000; i++) + { + if(IS_REPRESENTABLE(gGlobalFontInfo, i)) { + gGlyphCount++; +#ifdef TTDEBUG2 + printf("%4X ", i); + if(gGlyphCount % 16 == 0) + printf("\n"); +#endif + } + } +#ifdef TTDEBUG2 + printf("\n"); + printf("Total Glyph = %d\n", gGlyphCount); +#endif + + +#ifdef TRACK_INIT_PERFORMANCE + endTime = UpTime(); + Nanoseconds diff = + AbsoluteToNanoseconds( SubAbsoluteFromAbsolute(endTime, startTime) ); + printf("nsMacUnicodeFontInfo::InitGolbal take %d %d nanosecond\n", diff.hi, diff.lo); + +#endif + +#endif + gGlobalFontInfoInit = PR_TRUE; + return; +} +PRUint32* nsMacUnicodeFontInfo::GetGlobalFontInfo() +{ + InitGolbal(); + return gGlobalFontInfo; +} \ No newline at end of file diff --git a/gfx/src/mac/nsMacUnicodeFontInfo.h b/gfx/src/mac/nsMacUnicodeFontInfo.h new file mode 100644 index 000000000000..814b85034391 --- /dev/null +++ b/gfx/src/mac/nsMacUnicodeFontInfo.h @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1999 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ +#ifndef nsMacUnicodeFontInfo_h__ +#define nsMacUnicodeFontInfo_h__ +#include "nscore.h" +class nsMacUnicodeFontInfo { + public: + PRUint32* GetGlobalFontInfo(); + protected: + void InitGolbal(); + private: + static PRUint32 gGlobalFontInfo[2048]; + static PRBool gGlobalFontInfoInit; + static PRUint32 gFontsCount; + static PRUint32 gTTFFontsCount; + static PRUint32 gGlyphCount; +}; +#endif \ No newline at end of file