bug 144669 code to convert Truetype to subsetted Postscript

r=Louie.Zhao, sr=jst
This commit is contained in:
bstell%ix.netcom.com 2002-12-11 06:24:48 +00:00
parent e81697ce7c
commit 7c5097d7d8
7 changed files with 1501 additions and 0 deletions

View File

@ -36,6 +36,7 @@ REQUIRES = xpcom \
string \
widget \
pref \
caps \
uconv \
view \
necko \
@ -72,8 +73,22 @@ EXTRA_DSO_LDOPTS = \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
ifdef MOZ_ENABLE_FREETYPE2
CPPSRCS += \
nsCidMap.cpp \
nsType1.cpp \
nsType8.cpp \
$(NULL)
DEFINES += -DMOZ_ENABLE_FREETYPE2
LOCAL_INCLUDES += -I$(srcdir)/../freetype
endif
include $(topsrcdir)/config/rules.mk
ifdef MOZ_ENABLE_FREETYPE2
INCLUDES += $(FT2_CFLAGS)
endif
ifeq ($(OS_ARCH), Linux)
DEFINES += -D_BSD_SOURCE
endif

205
gfx/src/ps/nsCidMap.cpp Normal file
View File

@ -0,0 +1,205 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* ex: set tabstop=8 softtabstop=2 shiftwidth=2 expandtab:
* 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 Golden Hills Computer Services code.
*
* The Initial Developer of the Original Code is
* Brian Stell <bstell@ix.netcom.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Stell <bstell@ix.netcom.com>.
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
//
// This file has routines to build Postscript CID maps
//
// For general information on Postscript see:
// Adobe Solutions Network: Technical Notes - Fonts
// http://partners.adobe.com/asn/developer/technotes/fonts.html
//
// For information on CID maps see:
//
// CID-Keyed Font Technology Overview
// http://partners.adobe.com/asn/developer/pdfs/tn/5092.CID_Overview.pdf
//
// Adobe CMap and CID Font Files Specification
// http://partners.adobe.com/asn/developer/pdfs/tn/5014.CMap_CIDFont_Spec.pdf
//
// Building CMap Files for CID-Keyed Fonts
// http://partners.adobe.com/asn/developer/pdfs/tn/5099.CMapFiles.pdf
//
//
#include "nsCidMap.h"
CodeSpaceRangeElement UCS2_CodeSpaceRange[2] = {
{ 2, 0x0000, 0xD7FF },
{ 2, 0xE000, 0xFFFF },
};
int len_UCS2_CodeSpaceRange =
sizeof(UCS2_CodeSpaceRange)/sizeof(UCS2_CodeSpaceRange[0]);
void
WriteCidCharMap(PRUnichar *aCharIDs, PRUint32 *aCIDs,
int aLen, FILE *aFile)
{
int i, blk_len;
while (aLen) {
/* determine the # of lines in this block */
if (aLen >= 100)
blk_len = 100;
else
blk_len = aLen;
/* output the block */
fprintf(aFile, "%d begincidchar\n", blk_len);
for (i=0; i<blk_len; i++)
fprintf(aFile, "<%04X> %d\n", aCharIDs[i], aCIDs[i]);
fprintf(aFile, "endcidchar\n\n");
/* setup for next block */
aLen -= blk_len;
aCharIDs += blk_len;
aCIDs += blk_len;
}
}
void
WriteCidRangeMapUnicode(FILE *aFile)
{
int i;
fprintf(aFile, "100 begincidrange\n");
for (i=0; i<100; i++)
fprintf(aFile, "<%04X> <%04X> %d\n", i*256, ((i+1)*256)-1, i*256);
fprintf(aFile, "endcidrange\n\n");
fprintf(aFile, "100 begincidrange\n");
for (i=100; i<200; i++)
fprintf(aFile, "<%04X> <%04X> %d\n", i*256, ((i+1)*256)-1, i*256);
fprintf(aFile, "endcidrange\n\n");
fprintf(aFile, "56 begincidrange\n");
for (i=200; i<256; i++)
fprintf(aFile, "<%04X> <%04X> %d\n", i*256, ((i+1)*256)-1, i*256);
fprintf(aFile, "endcidrange\n\n");
}
void
WriteCmapHeader(const char *aName, const char *aRegistry,
const char *aEncoding, int aSupplement,
int aType, int aWmode, FILE *aFile)
{
fprintf(aFile, "%%%%DocumentNeededResources: procset CIDInit\n");
fprintf(aFile, "%%%%IncludeResource: procset CIDInit\n");
fprintf(aFile, "%%%%BeginResource: CMap %s\n", aName);
fprintf(aFile, "%%%%Title: (%s %s %s %d)\n", aName, aRegistry, aEncoding,aSupplement);
fprintf(aFile, "%%%%Version : 1\n");
fprintf(aFile, "\n");
fprintf(aFile, "/CIDInit /ProcSet findresource begin\n");
// IMPROVMENT: to add support for Postlevel 1 interpreters
// IMPROVMENT: add code to test if CIDInit is defined
// IMPROVMENT: if not defined then add code here to define it
fprintf(aFile, "\n");
fprintf(aFile, "12 dict begin\n");
fprintf(aFile, "\n");
fprintf(aFile, "begincmap\n");
fprintf(aFile, "\n");
fprintf(aFile, "/CIDSystemInfo 3 dict dup begin\n");
fprintf(aFile, " /Registry (%s) def\n", aRegistry);
fprintf(aFile, " /Ordering (%s) def\n", aEncoding);
fprintf(aFile, " /Supplement %d def\n", aSupplement);
fprintf(aFile, "end def\n");
fprintf(aFile, "\n");
fprintf(aFile, "/CMapName /%s def\n", aName);
fprintf(aFile, "\n");
fprintf(aFile, "/CMapVersion 1 def\n");
fprintf(aFile, "/CMapType %d def\n", aType);
fprintf(aFile, "\n");
fprintf(aFile, "/WMode %d def\n", aWmode);
fprintf(aFile, "\n");
}
void
WriteCmapFooter(FILE *aFile)
{
fprintf(aFile, "endcmap\n");
fprintf(aFile, "\n");
fprintf(aFile, "CMapName currentdict /CMap defineresource pop\n");
fprintf(aFile, "\n");
fprintf(aFile, "end\n");
fprintf(aFile, "end\n");
fprintf(aFile, "%%%%EndResource\n");
fprintf(aFile, "\n");
}
PRBool
WriteCodeSpaceRangeMap(CodeSpaceRangeElement *aElements, int aLen, FILE *aFile)
{
int i, blk_len;
while (aLen) {
/* determine the # of lines in this block */
if (aLen >= 100)
blk_len = 100;
else
blk_len = aLen;
/* output the block */
fprintf(aFile, "%d begincodespacerange\n", blk_len);
for (i=0; i<blk_len; i++, aElements++) {
if (aElements->num_bytes == 1)
fprintf(aFile, "<%02X> <%02X>\n", aElements->start, aElements->end);
else if (aElements->num_bytes == 2)
fprintf(aFile, "<%04X> <%04X>\n", aElements->start, aElements->end);
else {
fprintf(aFile, "codespacerange: invalid num_bytes (%d)\nexiting...\n",
aElements->num_bytes);
return PR_FALSE;
}
}
fprintf(aFile, "endcodespacerange\n\n");
/* setup for next block */
aLen -= blk_len;
}
return PR_TRUE;
}
void
WriteCodeSpaceRangeMapUCS2(FILE *aFile)
{
WriteCodeSpaceRangeMap(UCS2_CodeSpaceRange, len_UCS2_CodeSpaceRange, aFile);
}

82
gfx/src/ps/nsCidMap.h Normal file
View File

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* ex: set tabstop=8 softtabstop=2 shiftwidth=2 expandtab:
* 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 Golden Hills Computer Services code.
*
* The Initial Developer of the Original Code is
* Brian Stell <bstell@ix.netcom.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Stell <bstell@ix.netcom.com>.
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
//
// For general information on Postscript see:
// Adobe Solutions Network: Technical Notes - Fonts
// http://partners.adobe.com/asn/developer/technotes/fonts.html
//
// For information on CID maps see:
//
// CID-Keyed Font Technology Overview
// http://partners.adobe.com/asn/developer/pdfs/tn/5092.CID_Overview.pdf
//
// Adobe CMap and CID Font Files Specification
// http://partners.adobe.com/asn/developer/pdfs/tn/5014.CMap_CIDFont_Spec.pdf
//
// Building CMap Files for CID-Keyed Fonts
// http://partners.adobe.com/asn/developer/pdfs/tn/5099.CMapFiles.pdf
//
//
#ifndef CIDMAP_H
#define CIDMAP_H
#include <stdio.h>
#include "nscore.h"
typedef struct {
PRUint32 num_bytes;
PRUint32 start;
PRUint32 end;
} CodeSpaceRangeElement;
void WriteCidRangeMapUnicode(FILE *aFile);
void WriteCidCharMap(PRUnichar *aCharIDs, PRUint32 *aCIDs, int aLen,
FILE *aFile);
void WriteCmapFooter(FILE *aFile);
void WriteCmapHeader(const char *aName, const char *aRegistry,
const char *aEncoding, int aSupplement, int aType,
int aWmode, FILE *aFile);
int WriteCodeSpaceRangeMap(CodeSpaceRangeElement *aElements, int aLen,
FILE *aFile);
void WriteCodeSpaceRangeMapUCS2(FILE *aFile);
#endif /* CIDMAP_H */

432
gfx/src/ps/nsType1.cpp Normal file
View File

@ -0,0 +1,432 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* ex: set tabstop=8 softtabstop=2 shiftwidth=2 expandtab:
* 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 Golden Hills Computer Services code.
*
* The Initial Developer of the Original Code is
* Brian Stell <bstell@ix.netcom.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Stell <bstell@ix.netcom.com>.
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
//
// This file has routines to build Postscript Type 1 fonts
//
// For general information on Postscript see:
// Adobe Solutions Network: Technical Notes - Fonts
// http://partners.adobe.com/asn/developer/technotes/fonts.html
//
// For information on Postscript Type 1 fonts see:
//
// Adobe Type 1 Font Format
// http://partners.adobe.com/asn/developer/pdfs/tn/T1_SPEC.PDF
//
// This file uses the FreeType2 FT_Outline_Decompose facility to
// access the outlines which are then converted to Postscript Type 1
//
// For general information on FreeType2 see:
//
// The FreeType Project
// http://www.freetype.org/
//
//
// For information on FreeType2's outline processing see:
// FT_Outline_Decompose
// http://freetype.sourceforge.net/freetype2/docs/reference/ft2-outline_processing.html#FT_Outline_Decompose
//
//
#include "nsType1.h"
static const PRUint16 type1_encryption_c1 = TYPE1_ENCRYPTION_C1;
static const PRUint16 type1_encryption_c2 = TYPE1_ENCRYPTION_C2;
typedef struct {
nsIFreeType2 *ft2;
FT_Face face;
int elm_cnt;
int len;
double cur_x;
double cur_y;
unsigned char *buf;
int wmode;
} FT2PT1_info;
static int cubicto(FT_Vector *aControlPt1, FT_Vector *aControlPt2,
FT_Vector *aEndPt, void *aClosure);
static int Type1CharStringCommand(unsigned char **aBufPtrPtr, int aCmd);
static int Type1EncodeCharStringInt(unsigned char **aBufPtrPtr, int aValue);
/* thunk a short name for this function */
static inline int
csc(unsigned char **aBufPtrPtr, int aCmd)
{
return Type1CharStringCommand(aBufPtrPtr, aCmd);
}
/* thunk a short name for this function */
static inline int
ecsi(unsigned char **aBufPtrPtr, int aValue)
{
return Type1EncodeCharStringInt(aBufPtrPtr, aValue);
}
static int
Type1CharStringCommand(unsigned char **aBufPtrPtr, int aCmd)
{
unsigned char *p = *aBufPtrPtr;
if (p) {
*p = aCmd;
*aBufPtrPtr = p + 1;
}
return 1;
}
static int
Type1EncodeCharStringInt(unsigned char **aBufPtrPtr, int aValue)
{
unsigned char *p = *aBufPtrPtr;
if ((aValue >= -107) && (aValue <= 107)) {
if (p) {
p[0] = aValue + 139;
*aBufPtrPtr = p + 1;
}
return 1;
}
else if ((aValue >= 108) && (aValue <= 1131)) {
if (p) {
p[0] = ((aValue - 108)>>8) + 247;
p[1] = (aValue - 108) & 0xFF;
*aBufPtrPtr = p + 2;
}
return 2;
}
else if ((aValue <= -108) && (aValue >= -1131)) {
if (p) {
p[0] = ((-aValue - 108)>>8) + 251;
p[1] = (-aValue - 108) & 0xFF;
*aBufPtrPtr = p + 2;
}
return 2;
}
else {
unsigned int tmp = (unsigned int)aValue;
if (p) {
p[0] = 255;
p[1] = (tmp>>24) & 0xFF;
p[2] = (tmp>>16) & 0xFF;
p[3] = (tmp>>8) & 0xFF;
p[4] = tmp & 0xFF;
*aBufPtrPtr = p + 5;
}
return 5;
}
}
inline unsigned char
Type1Encrypt(unsigned char aPlain, PRUint16 *aKeyPtr)
{
unsigned char cipher;
cipher = (aPlain ^ (*aKeyPtr >> 8));
*aKeyPtr = (cipher + *aKeyPtr) * type1_encryption_c1 + type1_encryption_c2;
return cipher;
}
static void
Type1EncryptString(unsigned char *aInBuf, unsigned char *aOutBuf, int aLen)
{
int i;
PRUint16 key = TYPE1_ENCRYPTION_KEY;
for (i=0; i<aLen; i++)
aOutBuf[i] = Type1Encrypt(aInBuf[i], &key);
}
static PRBool
sideWidthAndBearing(FT_Vector *aEndPt, FT2PT1_info *aFti)
{
int aw = 0;
int ah = 0;
FT_UShort upm = aFti->face->units_per_EM;
FT_GlyphSlot slot;
FT_Glyph glyph;
FT_BBox bbox;
nsresult rv;
slot = aFti->face->glyph;
rv = aFti->ft2->GetGlyph(slot, &glyph);
if (NS_FAILED(rv)) {
NS_ERROR("sideWidthAndBearing failed to get glyph");
return PR_FALSE;
}
aFti->ft2->GlyphGetCBox(glyph, ft_glyph_bbox_unscaled, &bbox);
if (aFti->wmode == 0)
aw = toCS(upm, slot->metrics.horiAdvance);
else
aw = -toCS(upm, slot->metrics.vertAdvance);
if (aEndPt->y == 0) {
aFti->len += ecsi(&aFti->buf, (int)(aFti->cur_x = toCS(upm, bbox.xMin)));
aFti->cur_y = 0;
aFti->len += ecsi(&aFti->buf, aw);
aFti->len += csc(&aFti->buf, T1_HSBW);
}
else {
aFti->len += ecsi(&aFti->buf, (int)(aFti->cur_x = toCS(upm, bbox.xMin)));
aFti->len += ecsi(&aFti->buf, (int)(aFti->cur_y = toCS(upm, bbox.yMin)));
aFti->len += ecsi(&aFti->buf, aw);
aFti->len += ecsi(&aFti->buf, ah);
aFti->len += csc(&aFti->buf, T1_ESC_CMD);
aFti->len += csc(&aFti->buf, T1_ESC_SBW);
}
return PR_TRUE;
}
static int
moveto(FT_Vector *aEndPt, void *aClosure)
{
FT2PT1_info *fti = (FT2PT1_info *)aClosure;
FT_UShort upm = fti->face->units_per_EM;
PRBool rslt;
if (fti->elm_cnt == 0) {
rslt = sideWidthAndBearing(aEndPt, fti);
if (rslt != PR_TRUE) {
return 1;
}
}
else {
fti->len += csc(&fti->buf, T1_CLOSEPATH);
}
if (toCS(upm, aEndPt->x) == fti->cur_x) {
fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->y) - (int)fti->cur_y);
fti->len += csc(&fti->buf, T1_VMOVETO);
}
else if (toCS(upm, aEndPt->y) == fti->cur_y) {
fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->x) - (int)fti->cur_x);
fti->len += csc(&fti->buf, T1_HMOVETO);
}
else {
fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->x) - (int)fti->cur_x);
fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->y) - (int)fti->cur_y);
fti->len += csc(&fti->buf, T1_RMOVETO);
}
fti->cur_x = toCS(upm, aEndPt->x);
fti->cur_y = toCS(upm, aEndPt->y);
fti->elm_cnt++;
return 0;
}
static int
lineto(FT_Vector *aEndPt, void *aClosure)
{
FT2PT1_info *fti = (FT2PT1_info *)aClosure;
FT_UShort upm = fti->face->units_per_EM;
if (toCS(upm, aEndPt->x) == fti->cur_x) {
fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->y) - (int)fti->cur_y);
fti->len += csc(&fti->buf, T1_VLINETO);
}
else if (toCS(upm, aEndPt->y) == fti->cur_y) {
fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->x) - (int)fti->cur_x);
fti->len += csc(&fti->buf, T1_HLINETO);
}
else {
fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->x) - (int)fti->cur_x);
fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->y) - (int)fti->cur_y);
fti->len += csc(&fti->buf, T1_RLINETO);
}
fti->cur_x = toCS(upm, aEndPt->x);
fti->cur_y = toCS(upm, aEndPt->y);
fti->elm_cnt++;
return 0;
}
static int
conicto(FT_Vector *aControlPt, FT_Vector *aEndPt, void *aClosure)
{
FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure;
FT_UShort upm = ftinfo->face->units_per_EM;
double ctl_x, ctl_y;
double cur_x, cur_y, x3, y3;
FT_Vector aControlPt1, aControlPt2;
int rslt;
cur_x = ftinfo->cur_x;
cur_y = ftinfo->cur_y;
ctl_x = toCS(upm, aControlPt->x);
ctl_y = toCS(upm, aControlPt->y);
x3 = toCS(upm, aEndPt->x);
y3 = toCS(upm, aEndPt->y);
// So we can use the cubic curve code convert quadradic to cubic;
// the 1st control point is 2/3 the way from the start to the control point
aControlPt1.x = fromCS(upm, (cur_x + (2 * (ctl_x - cur_x) + 1)/3));
aControlPt1.y = fromCS(upm, (cur_y + (2 * (ctl_y - cur_y) + 1)/3));
// the 2nd control point is 1/3 the way from the control point to the end
aControlPt2.x = fromCS(upm, (ctl_x + (x3 - ctl_x + 1)/3));
aControlPt2.y = fromCS(upm, (ctl_y + (y3 - ctl_y + 1)/3));
// call the cubic code
rslt = cubicto(&aControlPt1, &aControlPt2, aEndPt, aClosure);
return rslt;
}
static int
cubicto(FT_Vector *aControlPt1, FT_Vector *aControlPt2, FT_Vector *aEndPt,
void *aClosure)
{
FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure;
FT_UShort upm = ftinfo->face->units_per_EM;
double cur_x, cur_y, x1, y1, x2, y2, x3, y3;
cur_x = ftinfo->cur_x;
cur_y = ftinfo->cur_y;
x1 = toCS(upm, aControlPt1->x);
y1 = toCS(upm, aControlPt1->y);
x2 = toCS(upm, aControlPt2->x);
y2 = toCS(upm, aControlPt2->y);
x3 = toCS(upm, aEndPt->x);
y3 = toCS(upm, aEndPt->y);
/* horizontal to vertical curve */
if (((int)(y1) == (int)(cur_y)) && ((int)(x3) == (int)(x2))) {
ftinfo->len += ecsi(&ftinfo->buf, (int)(x1-cur_x));
ftinfo->len += ecsi(&ftinfo->buf, (int)(x2-x1));
ftinfo->len += ecsi(&ftinfo->buf, (int)(y2-y1));
ftinfo->len += ecsi(&ftinfo->buf, (int)(y3-y2));
ftinfo->len += csc(&ftinfo->buf, T1_HVCURVETO);
}
/* vertical to horizontal curve */
else if (((int)(x1) == (int)(cur_x)) && ((int)(y3) == (int)(y2))) {
ftinfo->len += ecsi(&ftinfo->buf, (int)(y1-cur_y));
ftinfo->len += ecsi(&ftinfo->buf, (int)(x2-x1));
ftinfo->len += ecsi(&ftinfo->buf, (int)(y2-y1));
ftinfo->len += ecsi(&ftinfo->buf, (int)(x3-x2));
ftinfo->len += csc(&ftinfo->buf, T1_VHCURVETO);
}
else {
ftinfo->len += ecsi(&ftinfo->buf, (int)(x1-cur_x));
ftinfo->len += ecsi(&ftinfo->buf, (int)(y1-cur_y));
ftinfo->len += ecsi(&ftinfo->buf, (int)(x2-x1));
ftinfo->len += ecsi(&ftinfo->buf, (int)(y2-y1));
ftinfo->len += ecsi(&ftinfo->buf, (int)(x3-x2));
ftinfo->len += ecsi(&ftinfo->buf, (int)(y3-y2));
ftinfo->len += csc(&ftinfo->buf, T1_RRCURVETO);
}
ftinfo->cur_x = x3;
ftinfo->cur_y = y3;
ftinfo->elm_cnt++;
return 0;
}
static FT_Outline_Funcs ft_outline_funcs = {
moveto,
lineto,
conicto,
cubicto,
0,
0
};
FT_Error
FT2GlyphToType1CharString(nsIFreeType2 *aFt2, FT_Face aFace, PRUint32 aGlyphID,
int aWmode, int aLenIV, unsigned char *aBuf)
{
int j;
FT_Int32 flags = FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
FT_GlyphSlot slot;
unsigned char *start = aBuf;
FT2PT1_info fti;
nsresult rv;
rv = aFt2->LoadGlyph(aFace, aGlyphID, flags);
if (NS_FAILED(rv)) {
NS_ERROR("failed to load aGlyphID");
return 1;
}
slot = aFace->glyph;
if (slot->format != ft_glyph_format_outline) {
NS_ERROR("aGlyphID is not an outline glyph");
return 1;
}
fti.ft2 = aFt2;
fti.face = aFace;
fti.buf = aBuf;
fti.elm_cnt = 0;
fti.len = 0;
fti.wmode = aWmode;
/* add space for "random" bytes */
for (j=0; j< aLenIV; j++) {
fti.len += ecsi(&fti.buf, 0);
}
rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti);
if (NS_FAILED(rv)) {
NS_ERROR("error decomposing aGlyphID");
return 1;
}
if (fti.elm_cnt) {
fti.len += csc(&fti.buf, T1_CLOSEPATH);
fti.len += csc(&fti.buf, T1_ENDCHAR);
}
else {
FT_Vector end_pt;
end_pt.x = 0;
end_pt.y = 1; /* dummy value to cause sbw instead of hsbw */
PRBool rslt = sideWidthAndBearing(&end_pt, &fti);
if (rslt != PR_TRUE) {
return 1;
}
fti.len += csc(&fti.buf, T1_ENDCHAR);
}
if (fti.buf) {
Type1EncryptString(start, start, fti.len);
}
return fti.len;
}

102
gfx/src/ps/nsType1.h Normal file
View File

@ -0,0 +1,102 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* ex: set tabstop=8 softtabstop=2 shiftwidth=2 expandtab:
* 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 Golden Hills Computer Services code.
*
* The Initial Developer of the Original Code is
* Brian Stell <bstell@ix.netcom.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Stell <bstell@ix.netcom.com>.
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
//
// For genernal information on Postscript see:
// Adobe Solutions Network: Technical Notes - Fonts
// http://partners.adobe.com/asn/developer/technotes/fonts.html
//
// For information on Postscript Type 1 fonts see:
//
// Adobe Type 1 Font Format
// http://partners.adobe.com/asn/developer/pdfs/tn/T1_SPEC.PDF
//
#ifndef TYPE1_H
#define TYPE1_H
#include <stdio.h>
#include "nspr.h"
#include "nsFreeType.h"
/* to/from Character Space */
inline int
toCS(double upm, double x)
{
return (int)((x*1000.0)/upm);
}
inline int
fromCS(double upm, double x)
{
return (int) (x*upm/1000.0);
}
/* the 1 byte Postscript Type 1 commands */
#define T1_HSTEM 1 /* 0x01 */
#define T1_VSTEM 3 /* 0x03 */
#define T1_VMOVETO 4 /* 0x04 */
#define T1_RLINETO 5 /* 0x05 */
#define T1_HLINETO 6 /* 0x06 */
#define T1_VLINETO 7 /* 0x07 */
#define T1_RRCURVETO 8 /* 0x08 */
#define T1_CLOSEPATH 9 /* 0x09 */
#define T1_CALLSUBR 10 /* 0x0a */
#define T1_RETURN 11 /* 0x0b */
#define T1_ESC_CMD 12 /* 0x0c */
#define T1_HSBW 13 /* 0x0d */
#define T1_ENDCHAR 14 /* 0x0e */
#define T1_RMOVETO 21 /* 0x15 */
#define T1_HMOVETO 22 /* 0x16 */
#define T1_VHCURVETO 30 /* 0x1e */
#define T1_HVCURVETO 31 /* 0x1f */
/* the 2 byte (escaped) Postscript Type 1 commands */
#define T1_ESC_SBW 7 /* 0x07 */
#define TYPE1_ENCRYPTION_KEY 4330
#define TYPE1_ENCRYPTION_C1 52845
#define TYPE1_ENCRYPTION_C2 22719
FT_Error FT2GlyphToType1CharString(nsIFreeType2 *aFt2, FT_Face aFace,
PRUint32 aGlyphID, int aWmode, int aLenIV,
unsigned char *aBuf);
#endif /* TYPE1_H */

611
gfx/src/ps/nsType8.cpp Normal file
View File

@ -0,0 +1,611 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* ex: set tabstop=8 softtabstop=2 shiftwidth=2 expandtab:
* 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 Golden Hills Computer Services code.
*
* The Initial Developer of the Original Code is
* Brian Stell <bstell@ix.netcom.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Stell <bstell@ix.netcom.com>.
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
//
// This code converts TrueType to Postscript Type 8 fonts. (Note 1)
//
// The main entry point is FT2SubsetToType8()
//
// Note 1: actually any FreeType2 font that support FT_Outline_Decompose
// should work
//
#include <string.h>
#include <unistd.h>
#include "nsCidMap.h"
#include "nsType1.h"
#include "nsType8.h"
#include "nsFreeType.h"
#include "nsIServiceManager.h"
#include "nsISignatureVerifier.h"
#include "plbase64.h"
#include "nsCRT.h"
#define DEFAULT_CMAP_SIZE 10240
#define HEXASCII_LINE_LEN 64
static void hex_out(unsigned char *buf, PRUint32 n, FILE *f, PRUint32 *pos);
static void spaces_to_underlines(char *aToName);
static int FT2SubsetToCidKeyedType1(nsIFreeType2 *aFt2, FT_Face aFace,
PRUnichar *aCharIDs, int aLen,
const char *aFontName,
const char *aRegistry,
const char *aEncoding, int aSupplement,
int aWmode, int aLenIV, FILE *aFile);
void
AddCIDCheckCode(FILE *aFile)
{
fprintf(aFile, "%%\n");
fprintf(aFile, "%% Check if CID is supported\n");
fprintf(aFile, "%%\n");
fprintf(aFile, "/CanUseCIDFont false def\n");
fprintf(aFile, "%% If level at least level 2 check if CID is supported\n");
fprintf(aFile, "%% or it has been convert to (base) level 2\n");
fprintf(aFile, "version cvi 2000 ge {\n");
fprintf(aFile, " /CIDInit /ProcSet resourcestatus\n");
fprintf(aFile, " { pop pop /CanUseCIDFont true def }\n");
fprintf(aFile, " { /MozConvertedToLevel2 where \n");
fprintf(aFile, " { pop MozConvertedToLevel2 { /CanUseCIDFont true def"
" } if } if\n");
fprintf(aFile, " }\n");
fprintf(aFile, " ifelse\n");
fprintf(aFile, "} if\n");
fprintf(aFile, "%% If it has been converted to level 1 it is very big but\n");
fprintf(aFile, "%% guaranteed to be compatible\n");
fprintf(aFile, "/MozConvertedToLevel1 where {\n");
fprintf(aFile, " pop MozConvertedToLevel1 { /CanUseCIDFont true def } if\n");
fprintf(aFile, "} if\n");
fprintf(aFile, "CanUseCIDFont not {\n");
fprintf(aFile, " %%\n");
fprintf(aFile, " %% Cannot print this so tell the user how to convert it\n");
fprintf(aFile, " %%\n");
// IMPROVMENT: add the document title and/or user id
fprintf(aFile, " /Times-Roman findfont 12 scalefont setfont\n");
fprintf(aFile, " 50 700 moveto currentpoint\n");
fprintf(aFile, " (The Postscript interpreter in your printer is ) show\n");
fprintf(aFile, " version show\n");
fprintf(aFile, " moveto 0 -20 rmoveto currentpoint\n");
fprintf(aFile, " (This printout requires at least version 2015 or "
"greater) show\n");
fprintf(aFile, " moveto 0 -30 rmoveto currentpoint\n");
fprintf(aFile, " (To make a Unix/Linux Gecko browser (eg: Netscape or "
"Mozilla) produce ) show\n");
fprintf(aFile, " (output that will work ) show\n");
fprintf(aFile, " moveto 0 -20 rmoveto currentpoint\n");
fprintf(aFile, " (on any level 2 interpreter change the \"Print Command\" "
"to use ) show\n");
fprintf(aFile, " (Ghostscript to convert the output) show\n");
fprintf(aFile, " moveto 0 -20 rmoveto currentpoint\n");
fprintf(aFile, " (down to basic level 2; eg: change the print command "
"from) show\n");
fprintf(aFile, " moveto 0 -30 rmoveto currentpoint 20 0 rmoveto\n");
fprintf(aFile, " (lpr [OPTIONS]) show\n");
fprintf(aFile, " moveto 0 -30 rmoveto currentpoint\n");
fprintf(aFile, " (to \\(all on one line\\)) show\n");
fprintf(aFile, " moveto 0 -30 rmoveto currentpoint 20 0 rmoveto\n");
fprintf(aFile, " (gs -q -sDEVICE=pswrite -sOutputFile=- -dNOPAUSE "
"-dBATCH ) show\n");
fprintf(aFile, " moveto 0 -20 rmoveto currentpoint 60 0 rmoveto\n");
fprintf(aFile, " (-dMozConvertedToLevel2=true - | lpr [OPTIONS]) show\n");
fprintf(aFile, " /Times-Roman findfont 8 scalefont setfont\n");
fprintf(aFile, " moveto 0 -20 rmoveto currentpoint\n");
fprintf(aFile, " (for level 1 use: ) show\n");
fprintf(aFile, " moveto 0 -15 rmoveto currentpoint 20 0 rmoveto\n");
fprintf(aFile, " (gs -q -sDEVICE=pswrite -sOutputFile=- -dNOPAUSE ) show\n");
fprintf(aFile, " ( -dBATCH -dLanguageLevel=1 ) show\n");
fprintf(aFile, " (-dMozConvertedToLevel1=true - | lpr [OPTIONS]) show\n");
fprintf(aFile, " /Times-Roman findfont 12 scalefont setfont\n");
fprintf(aFile, " moveto 0 -50 rmoveto currentpoint\n");
fprintf(aFile, " (If you are printing this from a file use ) show\n");
fprintf(aFile, " (Ghostscript to convert it to basic level 2;) show\n");
fprintf(aFile, " moveto 0 -20 rmoveto currentpoint\n");
fprintf(aFile, " (eg: change the print command from) show\n");
fprintf(aFile, " moveto 0 -30 rmoveto currentpoint 20 0 rmoveto\n");
fprintf(aFile, " (lpr [OPTIONS] <FILENAME>) show\n");
fprintf(aFile, " moveto 0 -30 rmoveto currentpoint\n");
fprintf(aFile, " (to) show\n");
fprintf(aFile, " moveto 0 -30 rmoveto currentpoint 20 0 rmoveto\n");
fprintf(aFile, " (gs -q -sDEVICE=pswrite -sOutputFile=- -dNOPAUSE "
"-dBATCH ) show\n");
fprintf(aFile, " moveto 0 -30 rmoveto currentpoint 40 0 rmoveto\n");
fprintf(aFile, " (-dMozConvertedToLevel2=true <FILENAME> | lpr [OPTIONS]"
") show\n");
fprintf(aFile, " /Times-Roman findfont 8 scalefont setfont\n");
fprintf(aFile, " moveto 0 -20 rmoveto currentpoint\n");
fprintf(aFile, " (for level 1 use: ) show\n");
fprintf(aFile, " moveto 0 -15 rmoveto currentpoint 20 0 rmoveto\n");
fprintf(aFile, " (gs -q -sDEVICE=pswrite -sOutputFile=- -dNOPAUSE -dBATCH "
") show\n");
fprintf(aFile, " (-dLanguageLevel=1 -dMozConvertedToLevel1=true ) show\n");
fprintf(aFile, " (<FILENAME> | lpr [OPTIONS]) show\n");
fprintf(aFile, " /Times-Roman findfont 12 scalefont setfont\n");
fprintf(aFile, " showpage\n");
fprintf(aFile, " quit\n");
fprintf(aFile, "} if\n");
fprintf(aFile, "\n");
}
static char *
FT2ToType1FontName(FT_Face aFace, int aWmode)
{
char *fontname;
int name_len;
name_len = strlen(aFace->family_name); // family name
name_len += 1 + strlen(aFace->style_name); // '.' + style name
name_len += 11; // '.' + face_index
name_len += 2; // '.' + wmode
name_len += 1; // string terminator
fontname = (char *)PR_Malloc(name_len);
if (!fontname) {
return nsnull;
}
sprintf(fontname, "%s.%s.%ld.%d", aFace->family_name, aFace->style_name,
aFace->face_index, aWmode?1:0);
spaces_to_underlines(fontname);
return fontname;
}
static char *
FontNameToType8CmapName(char *aFontName)
{
char *cmapname;
/* get cmap name */
cmapname = (char *)PR_Malloc(strlen(aFontName)+1+5);
if (!cmapname) {
return nsnull;
}
sprintf((char*)cmapname, "%s_cmap", aFontName);
return cmapname;
}
char *
FT2ToType8CidFontName(FT_Face aFace, int aWmode)
{
int cidfontname_len;
char *cmapname = NULL;
char *fontname = NULL;
char *cidfontname = NULL;
fontname = FT2ToType1FontName(aFace, aWmode);
if (!fontname) {
goto done;
}
/* get cmap name */
cmapname = FontNameToType8CmapName(fontname);
if (!cmapname) {
goto done;
}
/* generate the font name */
cidfontname_len = strlen(fontname) + 2 + strlen(cmapname) + 1;
cidfontname = (char *)PR_Malloc(cidfontname_len);
if (!cidfontname) {
NS_ERROR("Failed to alloc space for font name");
goto done;
}
sprintf((char*)cidfontname, "%s--%s", fontname, cmapname);
done:
if (fontname)
PR_Free((void*)fontname);
if (cmapname)
PR_Free((void*)cmapname);
return (char *)cidfontname;
}
char *
FT2SubsetToEncoding(PRUnichar *aCharIDs, PRUint32 aNumChars)
{
unsigned char* rawDigest;
char *encoding = NULL;
nsresult rv;
PRUint32 len;
HASHContextStr* id;
//
// generate a cryptographic digest of the charIDs to use as the "encoding"
//
nsCOMPtr<nsISignatureVerifier> verifier =
do_GetService(SIGNATURE_VERIFIER_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = verifier->HashBegin(nsISignatureVerifier::SHA1, &id);
if (NS_SUCCEEDED(rv)) {
rv = verifier->HashUpdate(id, (const char*)aCharIDs,
aNumChars*sizeof(PRUnichar));
if (NS_SUCCEEDED(rv)) {
rawDigest = (unsigned char*)PR_Malloc(
nsISignatureVerifier::SHA1_LENGTH);
if (rawDigest) {
rv = verifier->HashEnd(id, &rawDigest, &len,
nsISignatureVerifier::SHA1_LENGTH);
if (NS_SUCCEEDED(rv)) {
encoding = PL_Base64Encode((char*)rawDigest, len, encoding);
}
PR_Free(rawDigest);
if (encoding)
return encoding;
}
}
}
}
// if psm is not available then just make a string based
// on the time and a simple hash of the chars
PRUint32 hash = nsCRT::HashCode((const PRUnichar *)aCharIDs, &aNumChars);
encoding = (char*)PR_Malloc(10+1+10+1+10+1);
if (!encoding)
return nsnull;
PRTime tmp_now, now = PR_Now();
PRTime usec_per_sec;
PRUint32 t_sec, t_usec;
LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
LL_DIV(tmp_now, now, usec_per_sec);
LL_L2I(t_sec, tmp_now);
LL_MOD(tmp_now, now, usec_per_sec);
LL_L2I(t_usec, tmp_now);
sprintf(encoding, "%u.%u.%u", hash, t_sec, t_usec);
return encoding;
}
PRBool
FT2SubsetToType8(FT_Face aFace, PRUnichar *aCharIDs, PRUint32 aNumChars,
int aWmode, FILE *aFile)
{
PRUint32 i;
char *fontname = NULL;
char *cmapname = NULL;
char *cidfontname = NULL;
char *registry;
char *encoding = NULL;
int supplement, lenIV;
PRUint32 CIDs_buf[5000];
PRUint32 *CIDs = CIDs_buf;
int cmap_type = 0;
PRBool status = PR_FALSE;
nsresult rv;
nsCOMPtr<nsIFreeType2> ft2 = do_GetService(NS_FREETYPE2_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
NS_ERROR("Failed to get nsIFreeType2 service");
goto done;
}
if ((aNumChars+1) > sizeof(CIDs_buf)/sizeof(CIDs_buf[0]))
CIDs = (PRUint32 *)PR_Malloc((aNumChars+1)*sizeof(CIDs_buf[0]));
if (!CIDs) {
NS_ERROR("Failed to alloc space for CIDs");
goto done;
}
fontname = FT2ToType1FontName(aFace, aWmode);
if (!fontname)
goto done;
cmapname = FontNameToType8CmapName(fontname);
if (!cmapname)
goto done;
cidfontname = FT2ToType8CidFontName(aFace, aWmode);
if (!cidfontname)
goto done;
registry = "mozilla_printout";
encoding = FT2SubsetToEncoding(aCharIDs, aNumChars);
if (!encoding)
goto done;
supplement = 0;
lenIV = 0;
//
// Build the Char to CID map
//
// reserve one space for the notdef glyph
// then map the the chars sequentially to glyphs
//
for (i=0; i<aNumChars; i++) {
CIDs[i] = i+1;
}
/* output the CMap */
WriteCmapHeader(cmapname, registry, encoding, supplement, cmap_type, aWmode,
aFile);
WriteCodeSpaceRangeMapUCS2(aFile);
WriteCidCharMap(aCharIDs, CIDs, aNumChars, aFile);
WriteCmapFooter(aFile);
/* output the Type 8 CID font */
FT2SubsetToCidKeyedType1(ft2, aFace, aCharIDs, aNumChars, fontname,
registry, encoding, supplement, aWmode, lenIV,
aFile);
fprintf(aFile, "\n");
/* compose the cmap and font */
fprintf(aFile, "/%s\n", cidfontname);
fprintf(aFile, " /%s /CMap findresource\n", cmapname);
fprintf(aFile, " [/%s /CIDFont findresource]\n", fontname);
fprintf(aFile, " composefont pop\n");
fprintf(aFile, "\n");
status = PR_TRUE;
done:
PR_FREEIF(fontname);
PR_FREEIF(cmapname);
PR_FREEIF(encoding);
PR_FREEIF(cidfontname);
if (CIDs != CIDs_buf)
PR_Free(CIDs);
return status;
}
static PRBool
FT2SubsetToCidKeyedType1(nsIFreeType2 *aFt2, FT_Face aFace, PRUnichar *aCharIDs,
int aLen, const char *aFontName,
const char *aRegistry, const char *aEncoding,
int aSupplement, int aWmode, int aLenIV, FILE *aFile)
{
int i, charstrings_len, data_offset;
unsigned int charstring_len;
PRUint32 glyphID, data_len, data_len2, max_charstring, line_pos;
unsigned int cmapinfo_buf[DEFAULT_CMAP_SIZE+1];
unsigned int *cmapinfo = cmapinfo_buf;
unsigned char charstring_buf[1024];
unsigned char *charstring = charstring_buf;
int fd_len, gd_len, cidmap_len, cmap_array_len, num_charstrings;
FT_UShort upm = aFace->units_per_EM;
if (aLen+2 > DEFAULT_CMAP_SIZE) {
cmapinfo = (unsigned int*)PR_Calloc(aLen+2, sizeof(unsigned int));
if (!cmapinfo)
return PR_FALSE;
}
fprintf(aFile, "%%%%DocumentNeededResources: procset CIDInit\n");
fprintf(aFile, "%%%%IncludeResource: procset CIDInit\n");
fprintf(aFile, "%%%%BeginResource: CIDFont %s\n", aFontName);
fprintf(aFile, "%%%%Title: (%s %s %s %d)\n", aFontName, aRegistry,
aEncoding, aSupplement);
fprintf(aFile, "%%%%Version: 1\n");
fprintf(aFile, "\n");
fprintf(aFile, "/CIDInit /ProcSet findresource begin\n");
fprintf(aFile, "\n");
fprintf(aFile, "20 dict begin\n");
fprintf(aFile, "\n");
fprintf(aFile, "/CIDFontName /%s def\n", aFontName);
fprintf(aFile, "/CIDFontVersion 1 def\n");
fprintf(aFile, "/CIDFontType 0 def\n");
fprintf(aFile, "\n");
fprintf(aFile, "/CIDSystemInfo 3 dict dup begin\n");
fprintf(aFile, " /Registry (%s) def \n", aRegistry);
fprintf(aFile, " /Ordering (%s) def \n", aEncoding);
fprintf(aFile, " /Supplement 0 def \n");
fprintf(aFile, "end def\n");
fprintf(aFile, "\n");
fprintf(aFile, "/FontBBox [%d %d %d %d] def\n",
toCS(upm, aFace->bbox.xMin),
toCS(upm, aFace->bbox.yMin),
toCS(upm, aFace->bbox.xMax),
toCS(upm, aFace->bbox.yMax));
fprintf(aFile, "\n");
/* measure the notdef glyph length */
cmapinfo[0] = FT2GlyphToType1CharString(aFt2, aFace, 0, aWmode, aLenIV, NULL);
num_charstrings = 1;
charstrings_len = cmapinfo[0];
/* get charstring lengths */
max_charstring = cmapinfo[0];
for (i=0; i<aLen; i++) {
aFt2->GetCharIndex(aFace, aCharIDs[i], &glyphID);
cmapinfo[i+1] = FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode,
aLenIV, NULL);
charstrings_len += cmapinfo[i+1];
if (cmapinfo[i+1])
num_charstrings++;
if (cmapinfo[i+1] > max_charstring)
max_charstring = cmapinfo[i+1];
}
cmapinfo[i+1] = 0;
if (max_charstring > sizeof(charstring_buf))
charstring = (unsigned char *)PR_Malloc(max_charstring);
if (!charstring) {
NS_ERROR("Failed to alloc bytes for charstring");
return PR_FALSE;
}
line_pos = 0;
fd_len = 0;
gd_len = 3;
cmap_array_len = 1 + aLen + 1;
cidmap_len = (fd_len+gd_len) * cmap_array_len;
fprintf(aFile, "/CIDMapOffset %d def\n", 0);
fprintf(aFile, "/FDBytes %d def\n", fd_len);
fprintf(aFile, "/GDBytes %d def\n", gd_len);
fprintf(aFile, "/CIDCount %d def\n", cmap_array_len-1);
fprintf(aFile, "\n");
fprintf(aFile, "/FDArray 1 array\n");
fprintf(aFile, "\n");
fprintf(aFile, "dup 0\n");
fprintf(aFile, " %%ADOBeginFontDict\n");
fprintf(aFile, " 14 dict begin\n");
fprintf(aFile, " \n");
fprintf(aFile, " /FontName /%s-Proportional def\n", aFontName);
fprintf(aFile, " /FontType 1 def\n");
fprintf(aFile, " /FontMatrix [ 0.001 0 0 0.001 0 0 ] def\n");
fprintf(aFile, " /PaintType 0 def\n");
fprintf(aFile, " \n");
fprintf(aFile, " %%ADOBeginPrivateDict\n");
fprintf(aFile, " /Private 25 dict dup begin\n");
fprintf(aFile, " /lenIV %d def\n", aLenIV);
fprintf(aFile, " /SubrCount 0 def\n");
fprintf(aFile, "\n");
fprintf(aFile, " end def\n");
fprintf(aFile, " %%ADOEndPrivateDict\n");
fprintf(aFile, "currentdict end\n");
fprintf(aFile, "%%ADOEndFontDict\n");
fprintf(aFile, "put\n");
fprintf(aFile, "\n");
fprintf(aFile, "def\n");
fprintf(aFile, "\n");
data_len = cidmap_len + charstrings_len;
//
// output the BeginData tag
//
// binary data is 1/2 the size of hexascii data but printers
// get confused by it so we don't use it
//
data_len2 = 27; // "(Hex) %10d StartData\n"
data_len2 += (data_len+1)*2; // the data (+pad byte) in hexascii
// new-lines at the end of the hexascii lines
data_len2 += ((data_len+1)*2)/HEXASCII_LINE_LEN;
data_len2 += 2; // EOD + new-line
fprintf(aFile, "%%%%BeginData: %d Binary Bytes\n", data_len2);
fprintf(aFile, "(Hex) %10d StartData\n", data_len);
//
// output the CIDMap
//
data_offset = cidmap_len;
for (i=0; i<cmap_array_len; i++) {
unsigned char buf[4];
int l = 0;
if (fd_len == 1)
buf[l++] = 0;
else if (fd_len != 0){
NS_ASSERTION(fd_len==0||fd_len==1, "only support fd_len == 0 or 1");
return PR_FALSE;
}
if (gd_len == 3) {
buf[l++] = (data_offset >> 16) & 0xFF;
buf[l++] = (data_offset >> 8) & 0xFF;
buf[l++] = data_offset & 0xFF;
}
else {
NS_ASSERTION(gd_len==3, "only support gd_len == 3");
return PR_FALSE;
}
hex_out(buf, fd_len + gd_len, aFile, &line_pos);
data_offset += cmapinfo[i];
}
//
// output the charStrings
//
// output the notdef glyph
charstring_len = FT2GlyphToType1CharString(aFt2, aFace, 0, aWmode, aLenIV,
charstring);
hex_out(charstring, charstring_len, aFile, &line_pos);
/* output the charstrings for the glyphs */
for (i=0; i<aLen; i++) {
aFt2->GetCharIndex(aFace, aCharIDs[i], &glyphID);
charstring_len = FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode,
aLenIV, charstring);
NS_ASSERTION(charstring_len==cmapinfo[i+1], "glyph data changed");
hex_out(charstring, charstring_len, aFile, &line_pos);
}
// add one byte padding so the interperter can always do 2 byte reads
charstring[0] = 0;
hex_out(charstring, 1, aFile, &line_pos);
// Output the EOD
fprintf(aFile, ">\n"); // EOD
/* StartData does an implicit "end end" */
fprintf(aFile, "%%%%EndData\n");
fprintf(aFile, "%%%%EndResource\n");
if (cmapinfo != cmapinfo_buf) {
PR_Free(cmapinfo);
}
if (charstring != charstring_buf) {
PR_Free(charstring);
}
return PR_TRUE;
}
static void
spaces_to_underlines(char *aString)
{
for (; *aString; aString++) {
if (*aString == ' ')
*aString = '_';
}
}
static void
hex_out(unsigned char *aBuf, PRUint32 aLen, FILE *f, PRUint32 *line_pos)
{
PRUint32 i, pos = *line_pos;
for (i=0; i<aLen; i++) {
fprintf(f, "%02X", aBuf[i]);
pos += 2;
if (pos >= HEXASCII_LINE_LEN) {
fprintf(f, "\n");
pos = 0;
}
}
*line_pos = pos;
}

54
gfx/src/ps/nsType8.h Normal file
View File

@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* ex: set tabstop=8 softtabstop=2 shiftwidth=2 expandtab:
* 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 Golden Hills Computer Services code.
*
* The Initial Developer of the Original Code is
* Brian Stell <bstell@ix.netcom.com>.
*
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Stell <bstell@ix.netcom.com>.
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 ***** */
#ifndef TYPE8_H
#define TYPE8_H
#include <stdio.h>
#include "nspr.h"
#include "nsFreeType.h"
void AddCIDCheckCode(FILE *aFile);
PRBool FT2SubsetToType8(FT_Face aFace, PRUnichar *aCharIDs, PRUint32 aNumChars,
int aWmode, FILE *aFile);
char* FT2ToType8CidFontName(FT_Face aFace, int aWmode);
#endif /* TYPE8_H */