summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdv2pdf/xdv2pdf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/xdv2pdf/xdv2pdf.cpp')
-rw-r--r--Build/source/texk/xdv2pdf/xdv2pdf.cpp2419
1 files changed, 0 insertions, 2419 deletions
diff --git a/Build/source/texk/xdv2pdf/xdv2pdf.cpp b/Build/source/texk/xdv2pdf/xdv2pdf.cpp
deleted file mode 100644
index 23b84fe8276..00000000000
--- a/Build/source/texk/xdv2pdf/xdv2pdf.cpp
+++ /dev/null
@@ -1,2419 +0,0 @@
-/****************************************************************************\
- Part of the XeTeX typesetting system
- copyright (c) 1994-2005 by SIL International
- written by Jonathan Kew
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL SIL INTERNATIONAL BE LIABLE FOR
-ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
-CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of SIL International
-shall not be used in advertising or otherwise to promote the sale,
-use or other dealings in this Software without prior written
-authorization from SIL International.
-\****************************************************************************/
-
-/*
- xdv2pdf
- Convert xdv file from XeTeX to PDF format for viewing/printing
-
- usage: xdv2pdf [-d debug] [-m mag] [-p papersize] [-v] xdvfile [-o pdffile]
-
- -m override magnification from xdv file
- -v show progress messages (page counters)
- -d set kpathsea_debug values
- -p papersize [default: from Mac OS X printing system]
-
- known papersize values:
- a0-a10
- b0-b10
- c0-c10
- jb0-jb10
- letter
- legal
- ledger
- tabloid
- can append ":landscape"
- or use "x,y" where x and y are dimensions in "big points" or with units
-
- output file defaults to <xdvfile>.pdf
-
- also permissible to omit xdvfile but specify pdffile; then input is from stdin
-*/
-
-#ifdef __POWERPC__
-#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_2
-#else
-#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_4
-#endif
-
-#include "config.h"
-
-#include <ApplicationServices/ApplicationServices.h>
-#include <QuickTime/QuickTime.h>
-
-#include <string>
-#include <vector>
-#include <list>
-#include <map>
-
-#include <sys/stat.h>
-
-#include "DVIops.h"
-
-#define XDV_ID 5 // current id_byte value for .xdv files from xetex
-
-#define XDV_FLAG_FONTTYPE_ATSUI 0x0001
-#define XDV_FLAG_FONTTYPE_ICU 0x0002
-
-#define XDV_FLAG_VERTICAL 0x0100
-#define XDV_FLAG_COLORED 0x0200
-#define XDV_FLAG_FEATURES 0x0400
-#define XDV_FLAG_VARIATIONS 0x0800
-#define XDV_FLAG_EXTEND 0x1000
-#define XDV_FLAG_SLANT 0x2000
-#define XDV_FLAG_EMBOLDEN 0x4000
-
-#define pdfbox_crop 1
-#define pdfbox_media 2
-#define pdfbox_bleed 3
-#define pdfbox_trim 4
-#define pdfbox_art 5
-
-
-#define DEFINE_GLOBALS 1
-#include "xdv2pdf_globals.h"
-
-paperSizeRec gPaperSizes[] =
-{
- { "a0", 2383.937008, 3370.393701 },
- { "a1", 1683.779528, 2383.937008 },
- { "a2", 1190.551181, 1683.779528 },
- { "a3", 841.8897638, 1190.551181 },
- { "a4", 595.2755906, 841.8897638 },
- { "a5", 419.5275591, 595.2755906 },
- { "a6", 297.6377953, 419.5275591 },
- { "a7", 209.7637795, 297.6377953 },
- { "a8", 147.4015748, 209.7637795 },
- { "a9", 104.8818898, 147.4015748 },
- { "a10", 73.7007874, 104.8818898 },
-
- { "b0", 2834.645669, 4008.188976 },
- { "b1", 2004.094488, 2834.645669 },
- { "b2", 1417.322835, 2004.094488 },
- { "b3", 1000.629921, 1417.322835 },
- { "b4", 708.6614173, 1000.629921 },
- { "b5", 498.8976378, 708.6614173 },
- { "b6", 354.3307087, 498.8976378 },
- { "b7", 249.4488189, 354.3307087 },
- { "b8", 175.7480315, 249.4488189 },
- { "b9", 124.7244094, 175.7480315 },
- { "b10", 87.87401575, 124.7244094 },
-
- { "c0", 2599.370079, 3676.535433 },
- { "c1", 1836.850394, 2599.370079 },
- { "c2", 1298.267717, 1836.850394 },
- { "c3", 918.4251969, 1298.267717 },
- { "c4", 649.1338583, 918.4251969 },
- { "c5", 459.2125984, 649.1338583 },
- { "c6", 323.1496063, 459.2125984 },
- { "c7", 229.6062992, 323.1496063 },
- { "c8", 161.5748031, 229.6062992 },
- { "c9", 113.3858268, 161.5748031 },
- { "c10", 79.37007874, 113.3858268 },
-
- { "jb0", 2919.685039, 4127.244094 },
- { "jb1", 2063.622047, 2919.685039 },
- { "jb2", 1459.84252, 2063.622047 },
- { "jb3", 1031.811024, 1459.84252 },
- { "jb4", 728.503937, 1031.811024 },
- { "jb5", 515.9055118, 728.503937 },
- { "jb6", 362.8346457, 515.9055118 },
- { "jb7", 257.9527559, 362.8346457 },
- { "jb8", 181.4173228, 257.9527559 },
- { "jb9", 127.5590551, 181.4173228 },
- { "jb10", 90.70866142, 127.5590551 },
-
- { "letter", 612.0, 792.0 },
- { "legal", 612.0, 1008.0 },
- { "tabloid", 792.0, 1224.0 },
- { "ledger", 1224.0, 792.0 },
-
- { 0, 0, 0 }
-};
-
-static const CGAffineTransform kHorizontalMatrix = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
-static const CGAffineTransform kVerticalMatrix = { 0.0, 1.0, -1.0, 0.0, 0.0, 0.0 };
-
-struct nativeFont {
- nativeFont()
- : cgFont(0)
- , atsFont(0)
- , atsuStyleH(0)
- , atsuStyleV(0)
- , size(Long2Fix(10))
- , matrix(kHorizontalMatrix)
- , isColored(false)
- , isVertical(false)
- {
- }
- CGFontRef cgFont;
- ATSFontRef atsFont;
- ATSUStyle atsuStyleH; // only present if isVertical is true
- ATSUStyle atsuStyleV;
- Fixed size;
- CGColorRef color;
- CGAffineTransform matrix;
- float embolden;
- bool isColored;
- bool isVertical;
-};
-
-static std::map<UInt32,nativeFont> sNativeFonts;
-
-static UInt32 sMag = 0;
-
-static bool sVerbose = false;
-
-static std::map<ATSFontRef,CGFontRef> sCGFonts;
-
-static CGFontRef
-getCGFontForATSFont(ATSFontRef fontRef)
-{
- std::map<ATSFontRef,CGFontRef>::const_iterator i = sCGFonts.find(fontRef);
- if (i != sCGFonts.end()) {
- return i->second;
- }
- CGFontRef newFont;
- if (fontRef == 0) {
- ATSFontRef tmpRef = ATSFontFindFromPostScriptName(CFSTR("Helvetica"), kATSOptionFlagsDefault);
- newFont = CGFontCreateWithPlatformFont(&tmpRef);
- }
- else
- newFont = CGFontCreateWithPlatformFont(&fontRef);
- sCGFonts[fontRef] = newFont;
- return newFont;
-}
-
-inline UInt32
-SWAP(UInt32 v)
-{
-#ifdef WORDS_BIGENDIAN
- return v;
-#else
- return (v << 24)
- + ((v << 8) & 0x00FF0000)
- + ((v >> 8) & 0x0000FF00)
- + (v >> 24);
-#endif
-}
-
-inline SInt32
-SWAP(SInt32 v)
-{
-#ifdef WORDS_BIGENDIAN
- return v;
-#else
- return (v << 24)
- + ((v << 8) & 0x00FF0000)
- + ((v >> 8) & 0x0000FF00)
- + ((v >> 24) & 0x000000FF);
-#endif
-}
-
-inline UInt16
-SWAP(UInt16 v)
-{
-#ifdef WORDS_BIGENDIAN
- return v;
-#else
- return (v << 8) + (v >> 8);
-#endif
-}
-
-inline SInt16
-SWAP(SInt16 v)
-{
-#ifdef WORDS_BIGENDIAN
- return v;
-#else
- return (v << 8) + ((v >> 8) & 0xFF);
-#endif
-}
-
-/* precaution, just in case we apply these to byte-sized values! */
-inline UInt8
-SWAP(UInt8 v)
-{
- return v;
-}
-
-inline SInt8
-SWAP(SInt8 v)
-{
- return v;
-}
-
-void
-initAnnotBox()
-{
- gAnnotBox.llx = gPageWd;
- gAnnotBox.lly = 0;
- gAnnotBox.urx = 0;
- gAnnotBox.ury = gPageHt;
-}
-
-void
-flushAnnotBox()
-{
- char buf[200];
- sprintf(buf, "ABOX [%f %f %f %f]",
- kDvi2Scr * gAnnotBox.llx + 72.0,
- kDvi2Scr * (gPageHt - gAnnotBox.lly) - 72.0,
- kDvi2Scr * gAnnotBox.urx + 72.0,
- kDvi2Scr * (gPageHt - gAnnotBox.ury) - 72.0);
- doPDFspecial(buf);
- initAnnotBox();
-}
-
-static void
-mergeBox(const box& b)
-{
- if (b.llx < gAnnotBox.llx)
- gAnnotBox.llx = b.llx;
- if (b.lly > gAnnotBox.lly)
- gAnnotBox.lly = b.lly; // NB positive is downwards!
- if (b.urx > gAnnotBox.urx)
- gAnnotBox.urx = b.urx;
- if (b.ury < gAnnotBox.ury)
- gAnnotBox.ury = b.ury;
-}
-
-long
-readSigned(FILE* f, int k)
-{
- long s = (long)(signed char)getc(f);
- while (--k > 0) {
- s <<= 8;
- s += (getc(f) & 0xff);
- }
- return s;
-}
-
-unsigned long
-readUnsigned(FILE* f, int k)
-{
- unsigned long u = getc(f);
- while (--k > 0) {
- u <<= 8;
- u += (getc(f) & 0xff);
- }
- return u;
-}
-
-
-void
-setColor(CGColorRef color, bool force = false)
-{
- if (force || !gCurrentColor || !CGColorEqualToColor(color, gCurrentColor)) {
- CGContextSetFillColorWithColor(gCtx, color);
- CGContextSetStrokeColorWithColor(gCtx, color);
- }
- gCurrentColor = color;
-}
-
-inline double
-radians(double degrees)
-{
- return degrees / 180.0 * M_PI;
-}
-
-void
-ensurePageStarted()
-{
- if (gPageStarted)
- return;
-
- CGContextSaveGState(gCtx);
- CGContextBeginPage(gCtx, &gMediaBox);
-
- static CGAffineTransform sInitTextMatrix;
- if (gPageIndex == 1) {
- sInitTextMatrix = CGContextGetTextMatrix(gCtx);
- }
- else
- CGContextSetTextMatrix(gCtx, sInitTextMatrix);
-
- gCurrentColor = NULL; /* ensure color will get set by first drawing op */
-
- CGContextTranslateCTM(gCtx, 72.0, -72.0);
-
- gPageWd = kScr2Dvi * gMediaBox.size.width;
- gPageHt = kScr2Dvi * gMediaBox.size.height;
-
- cur_cgFont = kUndefinedFont;
-
- gPageStarted = true;
-
- paintBackground();
-}
-
-void
-paintBackground()
-{
- if (gBackground != NULL) {
- if (!gPageStarted)
- ensurePageStarted(); /* this will call paintBackground() again */
- else {
- CGContextSaveGState(gCtx);
- CGContextSetFillColorWithColor(gCtx, gBackground);
- CGContextTranslateCTM(gCtx, -72.0, 72.0);
- CGContextFillRect(gCtx, gMediaBox);
- CGContextRestoreGState(gCtx);
- }
- }
-}
-
-#define MAX_BUFFERED_GLYPHS 1024
-int gGlyphCount = 0;
-CGGlyph gGlyphs[MAX_BUFFERED_GLYPHS];
-CGSize gAdvances[MAX_BUFFERED_GLYPHS+1];
-CGPoint gStartLoc;
-CGPoint gPrevLoc;
-
-static void
-myShowGlyphsWithAdvances(CGContextRef c, const CGGlyph* glyphs, const CGSize* advances, int count)
-{
- CGPoint loc = CGContextGetTextPosition(c);
- while (count > 0) {
- CGContextShowGlyphsAtPoint(c, loc.x, loc.y, glyphs, 1);
- loc.x += advances->width;
- loc.y += advances->height;
- ++advances;
- ++glyphs;
- --count;
- }
-}
-
-void
-flushGlyphs()
-{
- if (gGlyphCount > 0) {
- CGContextSetTextPosition(gCtx, gStartLoc.x, gStartLoc.y);
- gAdvances[gGlyphCount].width = 0;
- gAdvances[gGlyphCount].height = 0;
-
- if (sNativeFonts[cur_cgFont].isColored)
- setColor(sNativeFonts[cur_cgFont].color);
- else
- setColor(gTextColor);
- if (&CGContextShowGlyphsWithAdvances != NULL)
- CGContextShowGlyphsWithAdvances(gCtx, gGlyphs, gAdvances, gGlyphCount);
- else
- myShowGlyphsWithAdvances(gCtx, gGlyphs, gAdvances, gGlyphCount);
-
- gGlyphCount = 0;
- }
-}
-
-void
-bufferGlyph(CGGlyph g)
-{
- ensurePageStarted();
-
- CGPoint curLoc;
- curLoc.x = kDvi2Scr * dvi.h;
- curLoc.y = kDvi2Scr * (gPageHt - dvi.v);
- if (gGlyphCount == 0)
- gStartLoc = curLoc;
- else {
- gAdvances[gGlyphCount-1].width = curLoc.x - gPrevLoc.x;
- gAdvances[gGlyphCount-1].height = curLoc.y - gPrevLoc.y;
- }
- gPrevLoc = curLoc;
- gGlyphs[gGlyphCount] = g;
- if (++gGlyphCount == MAX_BUFFERED_GLYPHS)
- flushGlyphs();
-}
-
-void
-setChar(UInt32 c, bool adv)
-{
- OSStatus status;
-
- ensurePageStarted();
-
- if (f != cur_cgFont) {
- flushGlyphs();
- CGContextSetFont(gCtx, gTeXFonts[f].cgFont);
- CGContextSetFontSize(gCtx, Fix2X(gTeXFonts[f].size) * gMagScale);
- CGContextSetTextMatrix(gCtx, kHorizontalMatrix);
- CGContextSetTextDrawingMode(gCtx, kCGTextFill);
- cur_cgFont = f;
- }
-
- CGGlyph g;
- if (gTeXFonts[f].charMap != NULL) {
- if (c < gTeXFonts[f].charMap->size())
- g = (*gTeXFonts[f].charMap)[c];
- else
- g = c;
- }
- else
- // default: glyph ID = char + 1, works for the majority of the CM PS fonts
- g = c + 1;
-
- bufferGlyph(g);
-
- if (gTrackingBoxes) {
- if (gTeXFonts[f].hasMetrics) {
- box b = {
- dvi.h,
- dvi.v + gTeXFonts[f].depths[c],
- dvi.h + gTeXFonts[f].widths[c],
- dvi.v - gTeXFonts[f].heights[c] };
- mergeBox(b);
- }
- }
-
- if (adv && gTeXFonts[f].hasMetrics)
- dvi.h += gTeXFonts[f].widths[c];
-}
-
-
-static FixedPoint
-getGlyphVOrg(const nativeFont& f, UInt16 gid)
-{
- FixedPoint vorg;
- ATSGlyphIdealMetrics metrics;
- OSStatus status = ATSUGlyphGetIdealMetrics(f.atsuStyleV, 1, &gid, 0, &metrics);
-/*
- fprintf(stderr, "\nmetrics(V) for glyph %d: adv = (%.3f, %.3f) sb = (%.3f, %.3f) os = (%.3f, %.3f)\n", gid,
- metrics.advance.x, metrics.advance.y, metrics.sideBearing.x, metrics.sideBearing.y,
- metrics.otherSideBearing.x, metrics.otherSideBearing.y);
-*/
- vorg.y = X2Fix(-metrics.advance.y/* - metrics.otherSideBearing.y*/);
- status = ATSUGlyphGetIdealMetrics(f.atsuStyleH, 1, &gid, 0, &metrics);
-/*
- fprintf(stderr, "metrics(H) for glyph %d: adv = (%.3f, %.3f) sb = (%.3f, %.3f) os = (%.3f, %.3f)\n", gid,
- metrics.advance.x, metrics.advance.y, metrics.sideBearing.x, metrics.sideBearing.y,
- metrics.otherSideBearing.x, metrics.otherSideBearing.y);
-*/
- vorg.x = X2Fix(metrics.advance.x / 2);
- return vorg;
-}
-
-static void
-doGlyphArray(FILE* xdv, bool yLocs)
-{
- static int maxGlyphs = 0;
- static FixedPoint* locations = 0;
- static CGSize* advances = 0;
- static UInt16* glyphs = 0;
-
- flushGlyphs();
-
- Fixed wid = readUnsigned(xdv, 4);
- int glyphCount = readUnsigned(xdv, 2);
-
- if (glyphCount >= maxGlyphs) {
- maxGlyphs = glyphCount + 100;
- if (glyphs != 0)
- delete[] glyphs;
- glyphs = new UInt16[maxGlyphs];
- if (locations != 0)
- delete[] locations;
- locations = new FixedPoint[maxGlyphs];
- if (advances != 0)
- delete[] advances;
- advances = new CGSize[maxGlyphs];
- }
-
- for (int i = 0; i < glyphCount; ++i) {
- locations[i].x = readSigned(xdv, 4);
- locations[i].y = yLocs ? readSigned(xdv, 4) : 0;
- }
- for (int i = 0; i < glyphCount; ++i)
- glyphs[i] = readUnsigned(xdv, 2);
-
- if (f != cur_cgFont) {
- CGContextSetFont(gCtx, sNativeFonts[f].cgFont);
- CGContextSetFontSize(gCtx, Fix2X(sNativeFonts[f].size));
- CGContextSetTextMatrix(gCtx, sNativeFonts[f].matrix);
- if (sNativeFonts[f].embolden == 0.0) {
- CGContextSetTextDrawingMode(gCtx, kCGTextFill);
- }
- else {
- CGContextSetTextDrawingMode(gCtx, kCGTextFillStroke);
- CGContextSetLineWidth(gCtx, sNativeFonts[f].embolden);
- }
- cur_cgFont = f;
- }
-
- if (sNativeFonts[f].isColored)
- setColor(sNativeFonts[f].color);
- else
- setColor(gTextColor);
-
- if (sNativeFonts[f].isVertical) {
- for (int i = 0; i < glyphCount; ++i) {
- // need to adjust position to right by VOrg.y and down by VOrg.x
- FixedPoint vorg = getGlyphVOrg(sNativeFonts[f], glyphs[i]);
- locations[i].x += vorg.y;
- locations[i].y += vorg.x;
- }
- }
-
- CGContextSetTextPosition(gCtx, kDvi2Scr * dvi.h + Fix2X(locations[0].x) * 72 / 72.27,
- kDvi2Scr * (gPageHt - dvi.v) - Fix2X(locations[0].y) * 72 / 72.27);
-
- for (int i = 0; i < glyphCount - 1; ++i) {
- advances[i].width = gMagScale * Fix2X(locations[i+1].x - locations[i].x) * 72 / 72.27;
- advances[i].height = gMagScale * Fix2X(locations[i].y - locations[i+1].y) * 72 / 72.27;
- }
- advances[glyphCount-1].width = 0.0;
- advances[glyphCount-1].height = 0.0;
-
- if (&CGContextShowGlyphsWithAdvances != NULL)
- CGContextShowGlyphsWithAdvances(gCtx, glyphs, advances, glyphCount);
- else
- myShowGlyphsWithAdvances(gCtx, glyphs, advances, glyphCount);
-
- if (gTrackingBoxes) {
- box b = {
- dvi.h,
- dvi.v + (sNativeFonts[f].size / 3),
- dvi.h + wid,
- dvi.v - (2 * sNativeFonts[f].size / 3) };
- mergeBox(b);
- }
-
- dvi.h += wid;
-}
-
-/* code lifted almost verbatim from Apple sample "QTtoCG" */
-typedef struct {
- size_t width;
- size_t height;
- size_t bitsPerComponent;
- size_t bitsPerPixel;
- size_t bytesPerRow;
- size_t size;
- CGImageAlphaInfo ai;
- CGColorSpaceRef cs;
- unsigned char *data;
- CMProfileRef prof;
-} BitmapInfo;
-
-void readBitmapInfo(GraphicsImportComponent gi, BitmapInfo *bi)
-{
- ComponentResult result;
- ImageDescriptionHandle imageDescH = NULL;
- ImageDescription *desc;
- Handle profile = NULL;
-
- result = GraphicsImportGetImageDescription(gi, &imageDescH);
- if( noErr != result || imageDescH == NULL ) {
- fprintf(stderr, "Error while retrieving image description");
- exit(1);
- }
-
- desc = *imageDescH;
-
- bi->width = desc->width;
- bi->height = desc->height;
- bi->bitsPerComponent = 8;
- bi->bitsPerPixel = 32;
- bi->bytesPerRow = (bi->bitsPerPixel * bi->width + 7)/8;
- bi->ai = (desc->depth == 32) ? kCGImageAlphaFirst : kCGImageAlphaNoneSkipFirst;
- bi->size = bi->bytesPerRow * bi->height;
- bi->data = (unsigned char*)malloc(bi->size);
-
- bi->cs = NULL;
- bi->prof = NULL;
- GraphicsImportGetColorSyncProfile(gi, &profile);
- if( NULL != profile ) {
- CMError err;
- CMProfileLocation profLoc;
- Boolean bValid, bPreferredCMMNotFound;
-
- profLoc.locType = cmHandleBasedProfile;
- profLoc.u.handleLoc.h = profile;
-
- err = CMOpenProfile(&bi->prof, &profLoc);
- if( err != noErr ) {
- fprintf(stderr, "Cannot open profile");
- exit(1);
- }
-
- /* Not necessary to validate profile, but good for debugging */
- err = CMValidateProfile(bi->prof, &bValid, &bPreferredCMMNotFound);
- if( err != noErr ) {
- fprintf(stderr, "Cannot validate profile : Valid: %d, Preferred CMM not found : %d", bValid,
- bPreferredCMMNotFound);
- exit(1);
- }
-
- bi->cs = CGColorSpaceCreateWithPlatformColorSpace( bi->prof );
-
- if( bi->cs == NULL ) {
- fprintf(stderr, "Error creating cg colorspace from csync profile");
- exit(1);
- }
- DisposeHandle(profile);
- }
-
- if( imageDescH != NULL)
- DisposeHandle((Handle)imageDescH);
-}
-
-void getBitmapData(GraphicsImportComponent gi, BitmapInfo *bi)
-{
- GWorldPtr gWorld;
- QDErr err = noErr;
- Rect boundsRect = { 0, 0, bi->height, bi->width };
- ComponentResult result;
-
- if( bi->data == NULL ) {
- fprintf(stderr, "no bitmap buffer available");
- exit(1);
- }
-
- err = NewGWorldFromPtr( &gWorld, k32ARGBPixelFormat, &boundsRect, NULL, NULL, 0,
- (char*)bi->data, bi->bytesPerRow );
- if (noErr != err) {
- fprintf(stderr, "error creating new gworld - %d", err);
- exit(1);
- }
-
- if( (result = GraphicsImportSetGWorld(gi, gWorld, NULL)) != noErr ) {
- fprintf(stderr, "error while setting gworld");
- exit(1);
- }
-
- if( (result = GraphicsImportDraw(gi)) != noErr ) {
- fprintf(stderr, "error while drawing image through qt");
- exit(1);
- }
-
- DisposeGWorld(gWorld);
-}
-/* end of code from "QTtoCG" */
-
-struct imageRec {
- CGImageRef ref;
- CGRect bounds;
-};
-std::map<std::string,imageRec> sCGImages;
-std::map<std::string,CGPDFDocumentRef> sPdfDocs;
-
-static void
-doPicFile(FILE* xdv, int pdfBoxType) // t[4][6] p[2] l[2] a[l]
-{
- CGAffineTransform t;
- t.a = Fix2X(readSigned(xdv, 4));
- t.b = Fix2X(readSigned(xdv, 4));
- t.c = Fix2X(readSigned(xdv, 4));
- t.d = Fix2X(readSigned(xdv, 4));
- t.tx = Fix2X(readSigned(xdv, 4));
- t.ty = Fix2X(readSigned(xdv, 4));
- if (sMag != 1000)
- t = CGAffineTransformConcat(t, CGAffineTransformMakeScale(gMagScale, gMagScale));
-
- int p = readSigned(xdv, 2);
- int l = readUnsigned(xdv, 2);
- unsigned char* pathname = new unsigned char[l + 1];
- for (int i = 0; i < l; ++i)
- pathname[i] = readUnsigned(xdv, 1);
- pathname[l] = 0;
-
- CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, pathname, l, false);
- if (url != NULL) {
- std::string pathString((char*)pathname, l); // key for our map<>s of already-used images
-
- // is it a \pdffile instance?
- CGPDFDocumentRef document = NULL;
- CGImageRef image = NULL;
- CGRect bounds;
- CGPDFBox cgPdfBoxType;
- if (pdfBoxType > 0) {
- std::map<std::string,CGPDFDocumentRef>::const_iterator i = sPdfDocs.find(pathString);
- if (i != sPdfDocs.end())
- document = i->second;
- else {
- document = CGPDFDocumentCreateWithURL(url);
- sPdfDocs[pathString] = document;
- }
- if (document != NULL) {
- int nPages = CGPDFDocumentGetNumberOfPages(document);
- if (p < 0) p = nPages + 1 + p;
- if (p > nPages) p = nPages;
- if (p < 1) p = 1;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3
- if (&CGPDFDocumentGetPage == NULL) {
- switch (pdfBoxType) {
- case pdfbox_crop:
- default:
- bounds = CGPDFDocumentGetCropBox(document, p);
- break;
- case pdfbox_media:
- bounds = CGPDFDocumentGetMediaBox(document, p);
- break;
- case pdfbox_bleed:
- bounds = CGPDFDocumentGetBleedBox(document, p);
- break;
- case pdfbox_trim:
- bounds = CGPDFDocumentGetTrimBox(document, p);
- break;
- case pdfbox_art:
- bounds = CGPDFDocumentGetArtBox(document, p);
- break;
- }
- }
- else
-#endif
- {
- CGPDFPageRef pageRef = CGPDFDocumentGetPage(document, p);
- switch (pdfBoxType) {
- case pdfbox_crop:
- default:
- cgPdfBoxType = kCGPDFCropBox;
- break;
- case pdfbox_media:
- cgPdfBoxType = kCGPDFMediaBox;
- break;
- case pdfbox_bleed:
- cgPdfBoxType = kCGPDFBleedBox;
- break;
- case pdfbox_trim:
- cgPdfBoxType = kCGPDFTrimBox;
- break;
- case pdfbox_art:
- cgPdfBoxType = kCGPDFArtBox;
- break;
- }
- bounds = CGPDFPageGetBoxRect(pageRef, cgPdfBoxType);
- }
- }
- }
-
- // otherwise use GraphicsImport
- else {
- std::map<std::string,imageRec>::const_iterator i = sCGImages.find(pathString);
- if (i != sCGImages.end()) {
- image = i->second.ref;
- bounds = i->second.bounds;
- }
- else {
- FSRef ref;
- if (CFURLGetFSRef(url, &ref)) {
- FSSpec spec;
- if (FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, &spec, NULL) == noErr) {
- ComponentInstance gi;
- OSErr result = GetGraphicsImporterForFile(&spec, &gi);
- if (result == noErr) {
- BitmapInfo bi;
- readBitmapInfo(gi, &bi);
- getBitmapData(gi, &bi);
-
- if (bi.cs == NULL)
- bi.cs = CGColorSpaceCreateDeviceRGB();
- CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bi.data, bi.size, NULL);
- image = CGImageCreate(bi.width, bi.height, bi.bitsPerComponent, bi.bitsPerPixel,
- bi.bytesPerRow, bi.cs, bi.ai, provider, NULL, 0, kCGRenderingIntentDefault);
- CGColorSpaceRelease(bi.cs);
-
- ImageDescriptionHandle desc = NULL;
- result = GraphicsImportGetImageDescription(gi, &desc);
- bounds.origin.x = 0;
- bounds.origin.y = 0;
- bounds.size.width = (*desc)->width * 72.0 / Fix2X((*desc)->hRes);
- bounds.size.height = (*desc)->height * 72.0 / Fix2X((*desc)->vRes);
- DisposeHandle((Handle)desc);
- result = CloseComponent(gi);
- }
- imageRec ir = { image, bounds };
- sCGImages[pathString] = ir;
- }
- }
- }
- }
-
- CGContextSaveGState(gCtx);
-
- CGContextTranslateCTM(gCtx, kDvi2Scr * dvi.h, kDvi2Scr * (gPageHt - dvi.v));
- CGContextConcatCTM(gCtx, t);
-
- if (document != NULL) {
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3
- if (&CGPDFDocumentGetPage == NULL) {
- CGRect mediaBox = CGPDFDocumentGetMediaBox(document, p);
- CGRect cropBox = CGPDFDocumentGetCropBox(document, p);
- CGContextClipToRect(gCtx, cropBox);
- CGContextDrawPDFDocument(gCtx, mediaBox, document, p);
- }
- else
-#endif
- {
- CGPDFPageRef pageRef = CGPDFDocumentGetPage(document, p);
- CGAffineTransform xf = CGPDFPageGetDrawingTransform(pageRef, cgPdfBoxType, bounds, 0, true);
- CGContextConcatCTM(gCtx, xf);
- CGRect cropBox = CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox);
- CGContextClipToRect(gCtx, cropBox);
- CGContextDrawPDFPage(gCtx, pageRef);
- }
- }
- else if (image != NULL)
- CGContextDrawImage(gCtx, bounds, image);
-
- if (gTrackingBoxes) {
- // figure out the corners of the transformed and positioned image,
- // and remember the lower left and upper right of the result
- CGPoint p[4];
- p[0].x = bounds.origin.x;
- p[0].y = bounds.origin.y;
- p[1].x = bounds.origin.x;
- p[1].y = bounds.origin.y + bounds.size.height;
- p[2].x = bounds.origin.x + bounds.size.width;
- p[2].y = bounds.origin.y + bounds.size.height;
- p[3].x = bounds.origin.x + bounds.size.width;
- p[3].y = bounds.origin.y;
-
- CGPoint ll = { MAXFLOAT, MAXFLOAT };
- CGPoint ur = { -MAXFLOAT, -MAXFLOAT };
-
- t = CGContextGetCTM(gCtx);
- // now t is the CTM, including positioning as well as transformations of the image
-
- for (int i = 0; i < 4; ++i) {
- p[i] = CGPointApplyAffineTransform(p[i], t);
- if (p[i].x < ll.x)
- ll.x = p[i].x;
- if (p[i].y < ll.y)
- ll.y = p[i].y;
- if (p[i].x > ur.x)
- ur.x = p[i].x;
- if (p[i].y > ur.y)
- ur.y = p[i].y;
- }
-
- // convert back to dvi space and add to the annotation area
- box b = {
- (ll.x - 72.0) * kScr2Dvi,
- gPageHt - (ur.y + 72.0) * kScr2Dvi,
- (ur.x - 72.0) * kScr2Dvi,
- gPageHt - (ll.y + 72.0) * kScr2Dvi
- };
- mergeBox(b);
- }
-
- CGContextRestoreGState(gCtx);
-
- CFRelease(url);
- }
-
-}
-
-/* declarations of KPATHSEARCH functions we use for finding TFMs and OTFs */
-extern "C" {
-#include <kpathsea/kpathsea.h>
-#define kpse_find_file(name, type, must_exist) reinterpret_cast<UInt8*> \
- (kpse_find_file(reinterpret_cast<const_string>(name), \
- (kpse_file_format_type)type, must_exist))
-#define uppercasify(s) reinterpret_cast<UInt8*> \
- (uppercasify(reinterpret_cast<const_string>(s)))
-};
-
-#include "xdv_kpse_formats.h"
-
-static void
-loadMetrics(struct texFont& font, UInt8* name, Fixed d, Fixed s)
-{
- UInt8* pathname = kpse_find_file(name, xdv_kpse_tfm_format, true);
- if (pathname) {
- FILE* tfmFile = fopen((char*)pathname, "rb");
- if (tfmFile != 0) {
- enum { lf = 0, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np };
- SInt16 directory[12];
- for (int i = 0; i < 12; ++i)
- directory[i] = readSigned(tfmFile, 2);
- fseek(tfmFile, directory[lh] * 4, SEEK_CUR);
- int nChars = directory[ec] - directory[bc] + 1;
- double_t factor = Fix2X(d) / 16.0;
- if (s != d)
- factor = factor * Fix2X(s) / Fix2X(d);
- if (nChars > 0) {
- struct s_charinfo {
- UInt8 widthIndex;
- UInt8 heightDepth;
- UInt8 italicIndex;
- UInt8 remainder;
- };
- s_charinfo* charInfo = new s_charinfo[nChars];
- for (int i = 0; i < nChars; ++i) {
- charInfo[i].widthIndex = readUnsigned(tfmFile, 1);
- charInfo[i].heightDepth = readUnsigned(tfmFile, 1);
- charInfo[i].italicIndex = readUnsigned(tfmFile, 1);
- charInfo[i].remainder = readUnsigned(tfmFile, 1);
- }
- Fixed* widths = new Fixed[directory[nw]];
- for (int i = 0; i < directory[nw]; ++i)
- widths[i] = readSigned(tfmFile, 4);
- Fixed* heights = new Fixed[directory[nh]];
- for (int i = 0; i < directory[nh]; ++i)
- heights[i] = readSigned(tfmFile, 4);
- Fixed* depths = new Fixed[directory[nd]];
- for (int i = 0; i < directory[nd]; ++i)
- depths[i] = readSigned(tfmFile, 4);
-
- font.widths.reserve(directory[ec] + 1);
- font.heights.reserve(directory[ec] + 1);
- font.depths.reserve(directory[ec] + 1);
- font.charMap = new std::vector<UInt16>;
- font.charMap->reserve(directory[ec] + 1);
- for (int i = 0; i < directory[bc]; ++i) {
- font.widths.push_back(0);
- font.heights.push_back(0);
- font.depths.push_back(0);
- font.charMap->push_back(0);
- }
- int g = 0;
- for (int i = 0; i < nChars; ++i) {
- if (charInfo[i].widthIndex == 0) {
- font.widths.push_back(0);
- font.heights.push_back(0);
- font.depths.push_back(0);
- font.charMap->push_back(0);
- }
- else {
- double_t wid = Fix2X(widths[charInfo[i].widthIndex]) * factor;
- font.widths.push_back(X2Fix(wid));
-
- int heightIndex = (charInfo[i].heightDepth >> 4);
- double_t ht = Fix2X(heights[heightIndex]) * factor;
- font.heights.push_back(X2Fix(ht));
-
- int depthIndex = (charInfo[i].heightDepth & 0x0f);
- double_t dp = Fix2X(depths[depthIndex]) * factor;
- font.depths.push_back(X2Fix(dp));
-
- font.charMap->push_back(++g);
- }
- }
-
- delete[] widths;
- delete[] heights;
- delete[] depths;
- delete[] charInfo;
- }
-
- font.hasMetrics = true;
- fclose(tfmFile);
- }
- free(pathname);
- }
-}
-
-typedef std::vector<std::string> encoding;
-std::map<std::string,encoding> sEncodings;
-
-class fontMapRec {
-public:
- fontMapRec()
- : cgFont(0)
- , cmap(NULL)
- , loaded(false)
- { }
-
- std::string psName;
- std::string encName;
- std::string pfbName;
-
- CGFontRef cgFont;
- std::vector<UInt16>* cmap;
-
- bool loaded;
-};
-
-std::map<std::string,fontMapRec> psFontsMap;
-
-static void
-clearFontMap()
-{
- std::map<std::string,fontMapRec>::iterator i;
- for (i = psFontsMap.begin(); i != psFontsMap.end(); ++i) {
- if (i->second.cmap != NULL)
- delete i->second.cmap;
- }
- psFontsMap.clear();
-}
-
-void
-doPdfMapLine(const char* line, char mode)
-{
- if (*line == '%')
- return;
- while (*line == ' ' || *line == '\t')
- ++line;
- if (*line < ' ')
- return;
-
- if (mode == 0) {
- switch (*line) {
- case '+':
- case '-':
- case '=':
- mode = *line;
- ++line;
- while (*line == ' ' || *line == '\t')
- ++line;
- if (*line < ' ')
- return;
- break;
- default:
- clearFontMap();
- mode = '+';
- break;
- }
- }
-
- const char* b = line;
- const char* e = b;
- while (*e > ' ')
- ++e;
- std::string tfmName(b, e - b);
-
- if (mode == '-') {
- psFontsMap.erase(tfmName);
- return;
- // erase existing entry
- }
-
- if ((mode == '+') && (psFontsMap.find(tfmName) != psFontsMap.end()))
- return;
- // don't add if entry already exists
-
- while (*e && *e <= ' ')
- ++e;
- b = e;
- while (*e > ' ')
- ++e;
- if (e > b) {
- fontMapRec fr;
- fr.psName.assign(b, e - b);
- while (*e && *e <= ' ')
- ++e;
- if (*e == '"') { // skip quoted string; we don't do oblique, stretch, etc. (yet)
- ++e;
- while (*e && *e != '"')
- ++e;
- if (*e == '"')
- ++e;
- while (*e && *e <= ' ')
- ++e;
- }
- while (*e == '<') {
- ++e;
- b = e;
- while (*e > ' ')
- ++e;
- if (strncmp(e - 4, ".enc", 4) == 0) {
- fr.encName.assign(b, e - b);
- }
- else if (strncmp(e - 4, ".pfb", 4) == 0) {
- fr.pfbName.assign(b, e - b);
- }
-/*
- else if (strncmp(e - 4, ".pfa", 4) == 0) {
- fr.otfName.assign(b, e - b - 4);
- }
-*/
- while (*e && *e <= ' ')
- ++e;
- }
- psFontsMap[tfmName] = fr;
- }
-}
-
-static bool sMapFileLoaded = false;
-
-void
-doPdfMapFile(const char* fileName)
-{
- char mode = 0;
-
- while (*fileName == ' ' || *fileName == '\t')
- ++fileName;
- if (*fileName < ' ')
- return;
-
- switch (*fileName) {
- case '+':
- case '-':
- case '=':
- mode = *fileName;
- ++fileName;
- break;
- default:
- clearFontMap();
- mode = '+';
- break;
- }
- while (*fileName == ' ' || *fileName == '\t')
- ++fileName;
- if (*fileName < ' ')
- return;
-
- bool loaded = false;
- UInt8* pathname = kpse_find_file((UInt8*)fileName, xdv_kpse_font_map_format, true);
- if (pathname) {
- FILE* f = fopen((char*)pathname, "r");
- if (f != NULL) {
- char line[1000];
- while (!feof(f)) {
- if (fgets(line, 999, f) == 0)
- break;
- doPdfMapLine(line, mode);
-
- }
- loaded = true;
- fclose(f);
- if (sVerbose)
- fprintf(stderr, "\n{fontmap: %s} ", pathname);
- }
- free(pathname);
- }
- if (!loaded)
- fprintf(stderr, "\n*** fontmap %s not found; texmf.cnf may be broken\n", fileName);
- else
- sMapFileLoaded = true;
-}
-
-// return a pointer to the encoding vector with the given name, loading it if necessary
-// we don't really "parse" the .enc file
-static const encoding*
-getEncoding(const std::string& name)
-{
- std::map<std::string,encoding>::iterator i = sEncodings.find(name);
- if (i == sEncodings.end()) {
- encoding enc;
- UInt8* pathname = kpse_find_file((UInt8*)(name.c_str()), xdv_kpse_enc_format, true);
- if (pathname != NULL) {
- FILE* f = fopen((char*)pathname, "r");
- if (f != NULL) {
- int c;
- bool inVector = false;
- std::string str;
- while ((c = getc(f)) != EOF) {
- got_ch:
- if (c == '%') { // comment: skip rest of line
- while ((c = getc(f)) != EOF && c != '\r' && c != '\n')
- ;
- goto got_ch;
- }
- if (c == '[') {
- inVector = true;
- }
- else if (c == '/' || c <= ' ' || c == ']' || c == EOF) {
- if (inVector && str.length() > 0)
- enc.push_back(str);
- str.clear();
- }
- else if (inVector && c != EOF)
- str.append(1, (char)c);
- }
- if (sVerbose)
- fprintf(stderr, "\n{encoding: %s} ", pathname);
- fclose(f);
- }
- free(pathname);
- }
- sEncodings[name] = enc;
- return &(sEncodings[name]);
- }
-
- return &(i->second);
-}
-
-static ATSFontRef
-activateFromPath(const char* pathName)
-{
- if (sVerbose)
- fprintf(stderr, "\n{activate %s", pathName);
- ItemCount count = 0;
- FSRef fontFileRef;
- bzero(&fontFileRef, sizeof(fontFileRef));
- OSStatus status = FSPathMakeRef((UInt8*)pathName, &fontFileRef, 0);
- if (status == noErr) {
- ++count;
- FSSpec fontFileSpec;
- bzero(&fontFileSpec, sizeof(fontFileSpec));
- status = FSGetCatalogInfo(&fontFileRef, 0, 0, 0, &fontFileSpec, 0);
- if (status == noErr) {
- ++count;
- ATSFontContainerRef containerRef = 0;
- status = ATSFontActivateFromFileSpecification(&fontFileSpec, kATSFontContextLocal,
- kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &containerRef);
- if (status == noErr) {
- ++count;
- ATSFontRef fontRef;
- status = ATSFontFindFromContainer(containerRef, 0, 1, &fontRef, &count);
- if (status == noErr && count == 1) {
- if (sVerbose)
- fprintf(stderr, "}");
- return fontRef;
- }
- // failed, or container contained multiple fonts(!) -- confused
- ATSFontDeactivate(containerRef, 0, kATSOptionFlagsDefault);
- }
- }
- }
- if (sVerbose)
- fprintf(stderr, "... failed: status=%d, count=%d}", status, count);
- return 0;
-}
-
-struct postTable {
- Fixed format;
- Fixed italicAngle;
- SInt16 underlinePosition;
- SInt16 underlineThickness;
- UInt16 isFixedPitch;
- UInt16 reserved;
- UInt32 minMemType42;
- UInt32 maxMemType42;
- UInt32 minMemType1;
- UInt32 maxMemType1;
-};
-
-#include "appleGlyphNames.c"
-
-#define sfntCacheDir "/Library/Caches/Type1-sfnt-fonts/"
-#define sfntWrapCommand "T1Wrap"
-#define sfntWrapSuffix "-sfnt.otf"
-
-static ATSFontRef
-activatePFB(const char* pfbName)
-{
- static std::map<std::string,ATSFontRef> sActivatedFonts;
-
- std::map<std::string,ATSFontRef>::iterator i = sActivatedFonts.find(pfbName);
- if (i != sActivatedFonts.end())
- return i->second;
-
- ATSFontRef fontRef = 0;
- OSStatus status = noErr;
-
- static int firstTime = 1;
- if (firstTime) {
- firstTime = 0;
- status = mkdir(sfntCacheDir, S_IRWXU | S_IRWXG | S_IRWXO);
- if (status != 0) {
- if (errno == EEXIST) {
- // clean up possible residue from past failed conversions
- system("/usr/bin/find " sfntCacheDir " -maxdepth 1 -empty -type f -delete");
- status = 0;
- }
- else
- fprintf(stderr, "*** failed to create sfnt cache directory %s (errno = %d), cannot activate .pfb fonts\n",
- sfntCacheDir, errno);
- }
- }
-
- char* sfntName = new char[strlen(sfntCacheDir) + strlen(pfbName) + strlen(sfntWrapSuffix) + 1];
- strcpy(sfntName, sfntCacheDir);
- strcat(sfntName, pfbName);
- strcat(sfntName, sfntWrapSuffix);
-
- FSRef ref;
- status = FSPathMakeRef((const UInt8*)sfntName, &ref, NULL);
- if (status == fnfErr) {
- char* pathName = (char*)kpse_find_file((UInt8*)pfbName, xdv_kpse_pfb_format, true);
- if (pathName != NULL) {
- char* cmd = new char[strlen(sfntWrapCommand) + strlen(pathName) + strlen(sfntName) + 6];
- strcpy(cmd, sfntWrapCommand " ");
- strcat(cmd, pathName);
- strcat(cmd, " > ");
- strcat(cmd, sfntName);
- status = system(cmd);
- delete[] cmd;
- free(pathName);
- }
- }
-
- if (status == noErr)
- fontRef = activateFromPath(sfntName);
-
- delete[] sfntName;
-
- if (fontRef == 0) {
- // try removing extension (.pfb) and looking for an .otf font...
- char* baseName = new char[strlen(pfbName) + 1];
- strcpy(baseName, pfbName);
- char* dot = strrchr(baseName, '.');
- if (dot != NULL)
- *dot = 0;
- char* pathName = (char*)kpse_find_file((UInt8*)baseName, xdv_kpse_otf_format, true);
- delete[] baseName;
- if (pathName != NULL) {
- fontRef = activateFromPath(pathName);
- free(pathName);
- }
- }
-
- if (fontRef == 0)
- fprintf(stderr, "\n*** font activation failed (status=%d): %s\n", status, pfbName);
-
- sActivatedFonts[pfbName] = fontRef;
- return fontRef;
-}
-
-static std::vector<UInt16>*
-readMacRomanCmap(ATSFontRef fontRef)
-{
- std::vector<UInt16>* cmap = NULL;
- ByteCount size;
- OSStatus status = ATSFontGetTable(fontRef, 'cmap', 0, 0, 0, &size);
- if (status == noErr) {
- UInt8* buffer = new UInt8[size];
- ATSFontGetTable(fontRef, 'cmap', 0, size, buffer, &size);
-
- struct cmapHeader {
- UInt16 version;
- UInt16 numSubtables;
- };
- struct subtableHeader {
- UInt16 platform;
- UInt16 encoding;
- UInt32 offset;
- };
- struct format0 {
- UInt16 format;
- UInt16 length;
- UInt16 language;
- UInt8 glyphIndex[256];
- };
- struct format6 {
- UInt16 format;
- UInt16 length;
- UInt16 language;
- UInt16 firstCode;
- UInt16 entryCount;
- UInt16 glyphIndex[1];
- };
-
- struct cmapHeader* h = (struct cmapHeader*)buffer;
- struct subtableHeader* sh = (struct subtableHeader*)(buffer + sizeof(struct cmapHeader));
- int subtable = 0;
- cmap = new std::vector<UInt16>;
- cmap->reserve(256);
- while (subtable < SWAP(h->numSubtables)) {
- if ((SWAP(sh->platform) == 1) && (SWAP(sh->encoding) == 0)) {
- struct format0* f0 = (struct format0*)(buffer + SWAP(sh->offset));
- if (SWAP(f0->format) == 0) {
- for (int ch = 0; ch < 256; ++ch) {
- cmap->push_back(SWAP(f0->glyphIndex[ch]));
- }
- }
- else if (SWAP(f0->format) == 6) {
- struct format6* f6 = (struct format6*)f0;
- for (int ch = 0; ch < 256; ++ch) {
- if ((ch < SWAP(f6->firstCode)) || (ch >= SWAP(f6->firstCode) + SWAP(f6->entryCount)))
- cmap->push_back(0);
- else
- cmap->push_back(SWAP(f6->glyphIndex[ch - SWAP(f6->firstCode)]));
- }
- }
- else {
- // unsupported cmap subtable format
- fprintf(stderr, "\n*** unsupported 'cmap' subtable format (%d)\n", SWAP(f0->format));
- }
- break;
- }
- ++subtable;
- ++sh;
- }
-
- delete[] buffer;
- }
-
- return cmap;
-}
-
-static const fontMapRec*
-getFontRec(const std::string& name)
-{
- if (!sMapFileLoaded)
- doPdfMapFile("psfonts.map");
-
- std::map<std::string,fontMapRec>::iterator i = psFontsMap.find(name);
- if (i == psFontsMap.end())
- return NULL;
-
- fontMapRec& fr = i->second;
- if (fr.loaded)
- return &fr;
-
- ATSFontRef fontRef = 0;
- // if a filename is known, try to find and activate it
-
- if (fr.pfbName.length() > 0)
- fontRef = activatePFB(fr.pfbName.c_str());
-
- // if no downloadable file, see if it's installed in the OS
- if (fontRef == 0)
- fontRef = ATSFontFindFromPostScriptName(CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, fr.psName.c_str(),
- CFStringGetSystemEncoding(), kCFAllocatorNull), kATSOptionFlagsDefault);
-
- if (fontRef == 0)
- fprintf(stderr, "\n*** font %s (%s: file '%s') not found\n", name.c_str(), fr.psName.c_str(), fr.pfbName.c_str());
-
- if (fontRef != 0) {
- // if re-encoding was called for, load the encoding vector and build a new cmap
- if (fr.encName.length() > 0) {
- const encoding* enc = getEncoding(fr.encName);
- if (enc != 0) {
- ByteCount size;
- OSStatus status = ATSFontGetTable(fontRef, 'post', 0, 0, 0, &size);
- if (status == noErr) {
- UInt8* buffer = new UInt8[size];
- ATSFontGetTable(fontRef, 'post', 0, size, buffer, &size);
- postTable* p = (postTable*)&buffer[0];
- std::map<std::string,UInt16> name2gid;
- UInt16 g = 0;
- switch (SWAP(p->format)) {
- case 0x00010000:
- {
- char* cp;
- while ((cp = appleGlyphNames[g]) != 0) {
- name2gid[cp] = g;
- ++g;
- }
- }
- break;
-
- case 0x00020000:
- {
- UInt16* n = (UInt16*)(p + 1);
- UInt16 numGlyphs = SWAP(*n++);
- UInt8* ps = (UInt8*)(n + numGlyphs);
- std::vector<std::string> newNames;
- while (ps < buffer + size) {
- newNames.push_back(std::string((char*)ps + 1, *ps));
- ps += *ps + 1;
- }
- for (g = 0; g < numGlyphs; ++g) {
- if (SWAP(*n) < 258)
- name2gid[appleGlyphNames[SWAP(*n)]] = g;
- else
- name2gid[newNames[SWAP(*n) - 258]] = g;
- ++n;
- }
- }
- break;
-
- case 0x00028000:
- fprintf(stderr, "\n*** format 2.5 'post' table not supported\n");
- break;
-
- case 0x00030000:
- // TODO: see if it's a CFF OpenType font, and if so, get the glyph names from the CFF data
- fprintf(stderr, "\n*** format 3 'post' table; cannot reencode font %s\n", name.c_str());
- break;
-
- case 0x00040000:
- fprintf(stderr, "\n*** format 4 'post' table not supported\n");
- break;
-
- default:
- fprintf(stderr, "\n*** unknown 'post' table format %08x\n");
- break;
- }
- if (fr.cmap != NULL)
- delete fr.cmap;
- fr.cmap = new std::vector<UInt16>;
- for (encoding::const_iterator i = enc->begin(); i != enc->end(); ++i) {
- std::map<std::string,UInt16>::const_iterator g = name2gid.find(*i);
- if (g == name2gid.end())
- fr.cmap->push_back(0);
- else
- fr.cmap->push_back(g->second);
- }
- }
- else {
- fprintf(stderr, "\n*** no 'post' table found, unable to re-encode font %s\n", name.c_str());
- }
- }
- }
- else {
- // read the MacOS/Roman cmap, if available
- std::vector<UInt16>* cmap = readMacRomanCmap(fontRef);
- if (fr.cmap != NULL)
- delete fr.cmap;
- fr.cmap = cmap;
- }
- }
-
- if (fontRef == 0) {
- fprintf(stderr, "\n*** font %s (%s) not found, will substitute Helvetica glyphs\n", name.c_str(), fr.pfbName.c_str());
- fontRef = ATSFontFindFromPostScriptName(CFSTR("Helvetica"), kATSOptionFlagsDefault);
- if (fr.cmap != NULL)
- delete fr.cmap;
- fr.cmap = readMacRomanCmap(fontRef);
- }
-
- fr.cgFont = getCGFontForATSFont(fontRef);
- fr.loaded = true;
-
- return &fr;
-}
-
-static void
-doFontDef(FILE* xdv, int k)
-{
- OSStatus status;
-
- UInt32 f = readUnsigned(xdv, k); // font number we're defining
- UInt32 c = readUnsigned(xdv, 4); // TFM checksum
- Fixed s = readUnsigned(xdv, 4); // at size
- Fixed d = readUnsigned(xdv, 4); // design size
-
- UInt16 alen = readUnsigned(xdv, 1); // area length
- UInt16 nlen = readUnsigned(xdv, 1); // name length
-
- UInt8* name = new UInt8[alen + nlen + 2];
- if (alen > 0) {
- fread(name, 1, alen, xdv);
- name[alen] = '/';
- fread(name + alen + 1, 1, nlen, xdv);
- nlen += alen + 1;
- }
- else
- fread(name, 1, nlen, xdv);
- name[nlen] = 0;
-
- texFont font;
- loadMetrics(font, name, d, s);
-
- if (alen > 0)
- name = name + alen + 1; // point past the area to get the name by itself for the remaining operations
-
- ATSFontRef fontRef;
-
- // look for a map entry for this font name
- std::string nameStr((char*)name);
- const fontMapRec* fr = getFontRec(nameStr);
- if (fr != NULL) {
- font.cgFont = fr->cgFont;
- if (fr->cmap != NULL && fr->cmap->size() > 0) {
- if (font.charMap != NULL)
- delete font.charMap;
- font.charMap = fr->cmap; // replacing map that was synthesized from the tfm coverage
- }
- }
- else {
- /* try to find the font without the benefit of psfonts.map...
- first try the name as a pfb or otf filename
- and then as the PS name of an installed font
- */
-
- // ****** FIXME ****** this needs re-working to read the 'cmap' properly
-
- fontRef = ATSFontFindFromPostScriptName(CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, (char*)name,
- CFStringGetSystemEncoding(), kCFAllocatorNull), kATSOptionFlagsDefault);
- UInt8* ucname = 0;
- if (fontRef == 0) {
- ucname = uppercasify(name);
- fontRef = ATSFontFindFromPostScriptName(CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, (char*)ucname,
- CFStringGetSystemEncoding(), kCFAllocatorNull), kATSOptionFlagsDefault);
- }
-
- if (ucname != 0)
- free(ucname);
-
- if (fontRef == 0) {
- fprintf(stderr, "\n*** font %s not found in psfonts.map or host system; will substitute Helvetica glyphs\n", (char*)name);
- fontRef = ATSFontFindFromPostScriptName(CFSTR("Helvetica"), kATSOptionFlagsDefault);
- if (font.charMap != NULL)
- delete font.charMap;
- font.charMap = readMacRomanCmap(fontRef);
- }
-
- font.cgFont = getCGFontForATSFont(fontRef);
-
- delete[] name;
- }
-
- font.size = s;
- gTeXFonts.insert(std::pair<const UInt32,texFont>(f, font));
-}
-
-static void
-variationWarning()
-{
- static bool alreadyWarned = false;
- if (alreadyWarned)
- return;
- fprintf(stderr, "\n"
- "## xdv2pdf: AAT variation axes/multiple master fonts not supported on this system\n"
- "## (at least Mac OS X 10.4 is required)\n");
- alreadyWarned = true;
-}
-
-static void
-doNativeFontDef(FILE* xdv)
-{
- UInt32 f = readUnsigned(xdv, 4); // font ID
- Fixed s = X2Fix(Fix2X(readUnsigned(xdv, 4)) * 72 / 72.27); // size, converted to "big" points
- if (sMag != 1000)
- s = X2Fix(gMagScale * Fix2X(s));
- UInt16 flags = readUnsigned(xdv, 2);
-
- int psLen = readUnsigned(xdv, 1); // PSName length
- int skipLen = readUnsigned(xdv, 1); // family name length
- skipLen += readUnsigned(xdv, 1); // style name length
-
- char* name = new char[psLen+1];
- fread(name, 1, psLen, xdv);
- name[psLen] = 0;
-
- // don't use fseek, doesn't work when reading from a pipe!
- while (skipLen-- > 0)
- (void)readUnsigned(xdv, 1);
-
- UInt32 rgba = 0x000000FF;
- if (flags & XDV_FLAG_COLORED)
- rgba = readUnsigned(xdv, 4);
-
- ATSFontRef fontRef = 0;
- ATSUFontID fontID = kATSUInvalidFontID;
-
- if (name[0] == '[') { // uninstalled font specified by filename: not supported
- fprintf(stderr, "\n"
- "## xdv2pdf: use of uninstalled fonts (specified by filename) such as\n"
- "## %s\n"
- "## is not supported; try using the xdvipdfmx driver instead.\n", name);
- }
- else {
- CFStringRef psNameStr = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman);
- fontRef = ATSFontFindFromPostScriptName(psNameStr, kATSOptionFlagsDefault);
- CFRelease(psNameStr);
-
- fontID = FMGetFontFromATSFontRef(fontRef);
- }
-
- if (fontID == kATSUInvalidFontID)
- rgba = 0xFF0000FF;
-
- CGFontRef cgFont = getCGFontForATSFont(fontRef);
-
- OSStatus status = noErr;
-
- if (flags & XDV_FLAG_VARIATIONS) {
- int n = readUnsigned(xdv, 2); // number of variations
- if (n > 0) {
- bool applyVars = true;
- CFStringRef* axes = new CFStringRef[n];
- for (int i = 0; i < n; ++i) {
- UInt32 axis = readUnsigned(xdv, 4);
- FontNameCode nameCode;
- status = ATSUGetFontVariationNameCode(fontID, axis, &nameCode);
- ByteCount len;
- status = ATSUFindFontName(fontID, nameCode, kFontMacintoshPlatform, kFontRomanScript,
- (FontLanguageCode)kFontNoLanguage, 0, NULL, &len, NULL);
- if (status == noErr) {
- char* buf = new char[len + 1];
- status = ATSUFindFontName(fontID, nameCode, kFontMacintoshPlatform, kFontRomanScript,
- (FontLanguageCode)kFontNoLanguage, len, buf, &len, NULL);
- buf[len] = 0;
- axes[i] = CFStringCreateWithCString(kCFAllocatorDefault, buf, kCFStringEncodingMacRoman);
- delete[] buf;
- }
- else
- applyVars = false;
- }
-
- CFNumberRef* values = new CFNumberRef[n];
- for (int i = 0; i < n; ++i) {
- SInt32 v = readSigned(xdv, 4);
- Float32 f = Fix2X(v);
- values[i] = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat32Type, &f);
- }
-
- if (&CGFontCreateCopyWithVariations != NULL) {
- CFDictionaryRef variations = CFDictionaryCreate(kCFAllocatorDefault,
- (const void**)axes, (const void**)values, n,
- &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
- cgFont = CGFontCreateCopyWithVariations(cgFont, variations);
- CFRelease(variations);
- }
- else
- variationWarning();
-
- for (int i = 0; i < n; ++i) {
- CFRelease(axes[i]);
- CFRelease(values[i]);
- }
- delete[] values;
- delete[] axes;
- }
- }
-
- nativeFont fontRec;
- fontRec.cgFont = cgFont;
- fontRec.atsFont = fontRef;
- fontRec.size = s;
- fontRec.isColored = (flags & XDV_FLAG_COLORED) != 0 || fontID == kATSUInvalidFontID;
- fontRec.isVertical = (flags & XDV_FLAG_VERTICAL) != 0;
- if (fontRec.isColored) {
- float values[4];
- values[0] = (rgba >> 24) / 255.0;
- values[1] = ((rgba >> 16) & 0xFF) / 255.0;
- values[2] = ((rgba >> 8) & 0xFF) / 255.0;
- values[3] = ( rgba & 0xFF) / 255.0;
- fontRec.color = CGColorCreate(gRGBColorSpace, values);
- }
- else
- fontRec.color = NULL;
-
- if (fontRec.isVertical) {
- ATSUStyle style;
- status = ATSUCreateStyle(&style);
- ATSUVerticalCharacterType vert = kATSUStronglyHorizontal;
- ATSUAttributeTag tags[] = { kATSUFontTag, kATSUSizeTag, kATSUVerticalCharacterTag };
- ByteCount sizes[] = { sizeof(fontID), sizeof(s), sizeof(vert) };
- ATSUAttributeValuePtr values[] = { &fontID, &s, &vert };
- ItemCount numTags = sizeof(tags) / sizeof(ATSUAttributeTag);
- status = ATSUSetAttributes(style, numTags, tags, sizes, values);
- fontRec.atsuStyleH = style;
-
- status = ATSUCreateStyle(&style);
- vert = kATSUStronglyVertical;
- status = ATSUSetAttributes(style, numTags, tags, sizes, values);
- fontRec.atsuStyleV = style;
-
- fontRec.matrix = kVerticalMatrix;
- }
-
- if (flags & XDV_FLAG_EXTEND) {
- Fixed x = readUnsigned(xdv, 4);
- if (fontRec.isVertical)
- fontRec.matrix.c *= Fix2X(x);
- else
- fontRec.matrix.a *= Fix2X(x);
- }
- if (flags & XDV_FLAG_SLANT) {
- Fixed s = readSigned(xdv, 4);
- if (fontRec.isVertical)
- fontRec.matrix.d = Fix2X(s);
- else
- fontRec.matrix.c = Fix2X(s);
- }
- if (flags & XDV_FLAG_EMBOLDEN) {
- Fixed s = readSigned(xdv, 4);
- fontRec.embolden = Fix2X(s);
- }
- else
- fontRec.embolden = 0;
-
- sNativeFonts.insert(std::pair<const UInt32,nativeFont>(f, fontRec));
-}
-
-static void
-processPage(FILE* xdv)
-{
- /* enter here having just read BOP from xdv file */
- ++gPageIndex;
-
- OSStatus status;
- int i;
-
- std::list<dviVars> stack;
- gDviLevel = 0;
-
- int j = 0;
- for (i = 0; i < 10; ++i) { // read counts
- gCounts[i] = readSigned(xdv, 4);
- if (gCounts[i] != 0)
- j = i;
- }
- if (sVerbose) {
- fprintf(stderr, "[");
- for (i = 0; i < j; ++i)
- fprintf(stderr, "%d.", gCounts[i]);
- fprintf(stderr, "%d", gCounts[j]);
- }
-
- (void)readUnsigned(xdv, 4); // skip prev-BOP pointer
-
- cur_cgFont = kUndefinedFont;
- dvi.h = dvi.v = 0;
- dvi.w = dvi.x = dvi.y = dvi.z = 0;
- f = 0;
-
- unsigned int cmd = DVI_BOP;
- while (cmd != DVI_EOP) {
- UInt32 u;
- SInt32 s;
- SInt32 ht, wd;
- int k = 1;
-
- cmd = readUnsigned(xdv, 1);
- switch (cmd) {
- default:
- if (cmd < DVI_SET1)
- setChar(cmd, true);
- else if (cmd >= DVI_FNTNUM0 && cmd <= DVI_FNTNUM0 + 63)
- f = cmd - DVI_FNTNUM0;
- else
- goto ABORT_PAGE;
- break;
-
- case DVI_EOP:
- flushGlyphs();
- break;
-
- case DVI_NOP:
- break;
-
- case DVI_FNT4:
- ++k;
- case DVI_FNT3:
- ++k;
- case DVI_FNT2:
- ++k;
- case DVI_FNT1:
- f = readUnsigned(xdv, k); // that's it: just set |f|
- break;
-
- case DVI_XXX4:
- ++k;
- case DVI_XXX3:
- ++k;
- case DVI_XXX2:
- ++k;
- case DVI_XXX1:
- flushGlyphs();
- u = readUnsigned(xdv, k);
- if (u > 0) {
- char* special = new char[u+1];
- fread(special, 1, u, xdv);
- special[u] = '\0';
-
- doSpecial(special);
-
- delete[] special;
- }
- break;
-
- case DVI_SETRULE:
- case DVI_PUTRULE:
- ensurePageStarted();
- ht = readSigned(xdv, 4);
- wd = readSigned(xdv, 4);
- if (ht > 0 && wd > 0) {
- CGRect r = CGRectMake(kDvi2Scr * dvi.h, kDvi2Scr * (gPageHt - dvi.v), kDvi2Scr * wd, kDvi2Scr * ht);
- setColor(gRuleColor);
- CGContextFillRect(gCtx, r);
- if (gTrackingBoxes) {
- box b = {
- dvi.h,
- dvi.v,
- dvi.h + wd,
- dvi.v - ht };
- mergeBox(b);
- }
- }
- if (cmd == DVI_SETRULE)
- dvi.h += wd;
- break;
-
- case DVI_SET4:
- ++k;
- case DVI_SET3:
- ++k;
- case DVI_SET2:
- ++k;
- case DVI_SET1:
- u = readUnsigned(xdv, k);
- setChar(u, true);
- break;
-
- case DVI_PUT4:
- ++k;
- case DVI_PUT3:
- ++k;
- case DVI_PUT2:
- ++k;
- case DVI_PUT1:
- u = readUnsigned(xdv, k);
- setChar(u, false);
- break;
-
- case DVI_PUSH:
- stack.push_back(dvi);
- ++gDviLevel;
- break;
-
- case DVI_POP:
- if (gDviLevel == gTagLevel)
- flushAnnotBox();
- --gDviLevel;
- dvi = stack.back();
- stack.pop_back();
- break;
-
- case DVI_RIGHT4:
- ++k;
- case DVI_RIGHT3:
- ++k;
- case DVI_RIGHT2:
- ++k;
- case DVI_RIGHT1:
- s = readSigned(xdv, k);
- dvi.h += s;
- break;
-
- case DVI_DOWN4:
- ++k;
- case DVI_DOWN3:
- ++k;
- case DVI_DOWN2:
- ++k;
- case DVI_DOWN1:
- s = readSigned(xdv, k);
- dvi.v += s;
- break;
-
- case DVI_W4:
- ++k;
- case DVI_W3:
- ++k;
- case DVI_W2:
- ++k;
- case DVI_W1:
- s = readSigned(xdv, k);
- dvi.w = s;
- case DVI_W0:
- dvi.h += dvi.w;
- break;
-
- case DVI_X4:
- ++k;
- case DVI_X3:
- ++k;
- case DVI_X2:
- ++k;
- case DVI_X1:
- s = readSigned(xdv, k);
- dvi.x = s;
- case DVI_X0:
- dvi.h += dvi.x;
- break;
-
- case DVI_Y4:
- ++k;
- case DVI_Y3:
- ++k;
- case DVI_Y2:
- ++k;
- case DVI_Y1:
- s = readSigned(xdv, k);
- dvi.y = s;
- case DVI_Y0:
- dvi.v += dvi.y;
- break;
-
- case DVI_Z4:
- ++k;
- case DVI_Z3:
- ++k;
- case DVI_Z2:
- ++k;
- case DVI_Z1:
- s = readSigned(xdv, k);
- dvi.z = s;
- case DVI_Z0:
- dvi.v += dvi.z;
- break;
-
- case XDV_GLYPH_ARRAY:
- ensurePageStarted();
- doGlyphArray(xdv, true);
- break;
-
- case XDV_GLYPH_STRING:
- ensurePageStarted();
- doGlyphArray(xdv, false);
- break;
-
- case XDV_PIC_FILE:
- ensurePageStarted();
- k = readUnsigned(xdv, 1); /* 0 for QT picfile, or PDF box code (1..5) */
- doPicFile(xdv, k);
- break;
-
- case DVI_FNTDEF4:
- ++k;
- case DVI_FNTDEF3:
- ++k;
- case DVI_FNTDEF2:
- ++k;
- case DVI_FNTDEF1:
- doFontDef(xdv, k);
- break;
-
- case XDV_NATIVE_FONT_DEF:
- doNativeFontDef(xdv);
- break;
- }
- }
-
- ensurePageStarted(); // needed for completely blank pages!
-
- if (sVerbose) {
- fprintf(stderr, "]%s", (gPageIndex % 10) == 0 ? "\n" : "");
- }
-
-ABORT_PAGE:
-
- if (gPageStarted) {
- CGContextEndPage(gCtx);
- CGContextRestoreGState(gCtx);
- }
-
- gPageStarted = false;
-}
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
-/* From Apple Technical Q&A 1396, Listing 2 */
-static CGColorSpaceRef
-CreateICCColorSpaceFromPathToProfile(const char* iccProfilePath)
-{
- CMProfileRef iccProfile = (CMProfileRef)0;
- CGColorSpaceRef iccColorSpace = NULL;
- CMProfileLocation loc;
-
- // Specify that the location of the profile will be a POSIX path to the profile.
- loc.locType = cmPathBasedProfile;
-
- // Make sure the path is not larger then the buffer
- if (strlen(iccProfilePath) > sizeof(loc.u.pathLoc.path))
- return NULL;
-
- // Copy the path the profile into the CMProfileLocation structure
- strcpy(loc.u.pathLoc.path, iccProfilePath);
-
- // Open the profile
- if (CMOpenProfile(&iccProfile, &loc) != noErr) {
- iccProfile = (CMProfileRef)0;
- return NULL;
- }
-
- // Create the ColorSpace with the open profile.
- iccColorSpace = CGColorSpaceCreateWithPlatformColorSpace(iccProfile);
-
- // Close the profile now that we have what we need from it.
- CMCloseProfile(iccProfile);
-
- return iccColorSpace;
-}
-
-static CGColorSpaceRef
-CreateColorSpaceFromSystemICCProfileName(CFStringRef profileName)
-{
- FSRef pathToProfilesFolder;
- FSRef pathToProfile;
-
- // Find the Systems Color Sync Profiles folder
- if (FSFindFolder(kOnSystemDisk, kColorSyncProfilesFolderType,
- kDontCreateFolder, &pathToProfilesFolder) == noErr) {
-
- // Make a UniChar string of the profile name
- UniChar uniBuffer[sizeof(CMPathLocation)];
- CFStringGetCharacters(profileName, CFRangeMake(0, CFStringGetLength(profileName)), uniBuffer);
-
- // Create a FSRef to the profile in the Systems Color Sync Profile folder
- if (FSMakeFSRefUnicode(&pathToProfilesFolder, CFStringGetLength(profileName), uniBuffer,
- kUnicodeUTF8Format, &pathToProfile) == noErr) {
- char path[sizeof(CMPathLocation)];
-
- // Write the posix path to the profile into our path buffer from the FSRef
- if (FSRefMakePath(&pathToProfile, (UInt8*)path, sizeof(CMPathLocation)) == noErr)
- return CreateICCColorSpaceFromPathToProfile(path);
- }
- }
-
- return NULL;
-}
-/* end of Apple Q&A code */
-#endif
-
-static void
-processAllPages(FILE* xdv)
-{
- // initialize some global variables that we use as CG "constants"
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
- if (&kCGColorSpaceGenericRGB == NULL) {
- gRGBColorSpace = CreateColorSpaceFromSystemICCProfileName(CFSTR("Generic RGB Profile.icc"));
- gCMYKColorSpace = CreateColorSpaceFromSystemICCProfileName(CFSTR("Generic CMYK Profile.icc"));
- gGrayColorSpace = CreateColorSpaceFromSystemICCProfileName(CFSTR("Generic Gray Profile.icc"));
- }
- else
-#endif
- {
- gRGBColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
- gCMYKColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericCMYK);
- gGrayColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
- }
-
- if (gRGBColorSpace == NULL || gCMYKColorSpace == NULL || gGrayColorSpace == NULL) {
- fprintf(stderr, "\n*** unable to initialize color spaces.... something's badly broken\n");
- exit(1);
- }
-
- const float black[2] = { 0.0, 1.0 };
- kBlackColor = CGColorCreate(gGrayColorSpace, black);
-
- gPageIndex = 0;
- unsigned int cmd;
- while ((cmd = readUnsigned(xdv, 1)) != DVI_POST) {
- switch (cmd) {
- case DVI_BOP:
- processPage(xdv);
- break;
-
- case DVI_NOP:
- break;
-
- default:
- fprintf(stderr, "\n*** unexpected DVI command: %d\n", cmd);
- exit(1);
- }
- }
- if (sVerbose && (gPageIndex % 10) != 0)
- fprintf(stderr, "\n");
-}
-
-const char* progName;
-static void
-usage()
-{
- fprintf(stderr, "usage: %s [-m mag] [-p papersize[:landscape]] [-v] [-o pdfFile] xdvFile\n", progName);
- fprintf(stderr, " papersize values: ");
- paperSizeRec* ps = &gPaperSizes[0];
- while (ps->name != 0) {
- fprintf(stderr, "%s/", ps->name);
- ++ps;
- }
- fprintf(stderr, "wd,ht [in 'big' points or with explicit units]\n");
-}
-
-static void
-version()
-{
- fprintf(stderr, "%s version %s\n", PACKAGE, VERSION);
- fprintf(stderr, "Written by Jonathan Kew\n"
- "Copyright (c) 2008 SIL International\n"
- "This program is part of the XeTeX typesetting system;\n"
- "see the XeTeX license for details.\n\n");
-}
-
-int
-xdv2pdf(int argc, char** argv)
-{
- OSStatus status;
-
- progName = argv[0];
-
- gMagScale = 1.0;
- gRuleColor = kBlackColor;
- gTextColor = gRuleColor;
-
- gTagLevel = -1;
-
- gPaperWd = gPaperHt = 0.0;
-
- int ch;
- while ((ch = getopt(argc, argv, "o:p:m:d:hv" /*r:*/)) != -1) {
- switch (ch) {
- case 'o':
- {
- CFStringRef outFileName = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8);
- gSaveURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, outFileName, kCFURLPOSIXPathStyle, false);
- CFRelease(outFileName);
- }
- break;
-
- case 'p':
- if (!getPaperSize(optarg, gPaperWd, gPaperHt)) {
- fprintf(stderr, "*** unknown paper name: %s\n", optarg);
- exit(1);
- }
- break;
-
- case 'm':
- sMag = atoi(optarg);
- break;
-
- case 'd':
- kpathsea_debug |= atoi(optarg);
- break;
-
- case 'v':
- version();
- sVerbose = true;
- break;
-
- case 'h':
- usage();
- exit(0);
- }
- }
-
- if ((gPaperWd == 0.0) || (gPaperHt == 0.0)) {
- // get default paper size from printing system
- PMRect paperRect = { 0, 0, 792, 612 };
- PMPrintSession printSession;
- PMPrintSettings printSettings;
- PMPageFormat pageFormat;
- status = PMCreateSession(&printSession);
- if (status == noErr) {
- status = PMCreatePrintSettings(&printSettings);
- if (status == noErr) {
- status = PMSessionDefaultPrintSettings(printSession, printSettings);
- status = PMCreatePageFormat(&pageFormat);
- if (status == noErr) {
- status = PMSessionDefaultPageFormat(printSession, pageFormat);
- PMGetUnadjustedPaperRect(pageFormat, &paperRect);
- status = PMRelease(pageFormat);
- }
- status = PMRelease(printSettings);
- }
- status = PMRelease(printSession);
- }
- gPaperWd = paperRect.right - paperRect.left;
- gPaperHt = paperRect.bottom - paperRect.top;
- }
-
- // set the media box for PDF generation
- gMediaBox = CGRectMake(0, 0, gPaperWd, gPaperHt);
-
- argc -= optind;
- argv += optind;
- if (argc == 1 && gSaveURL == 0) {
- CFStringRef inFileName = CFStringCreateWithCString(kCFAllocatorDefault, argv[0], CFStringGetSystemEncoding());
- CFURLRef inURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, inFileName, kCFURLPOSIXPathStyle, false);
- CFRelease(inFileName);
- CFURLRef tmpURL = CFURLCreateCopyDeletingPathExtension(kCFAllocatorDefault, inURL);
- CFRelease(inURL);
- gSaveURL = CFURLCreateCopyAppendingPathExtension(kCFAllocatorDefault, tmpURL, CFSTR("pdf"));
- CFRelease(tmpURL);
- }
-
- if (argc > 1 || gSaveURL == 0) {
- usage();
- exit(1);
- }
-
- FILE* xdv;
- if (argc == 1)
- xdv = fopen(argv[0], "r");
- else
- xdv = stdin;
-
- if (xdv != NULL) {
- // read the preamble
- unsigned b = readUnsigned(xdv, 1);
- if (b != DVI_PRE) { fprintf(stderr, "*** bad XDV file: DVI_PRE not found, b=%d\n", b); exit(1); }
- b = readUnsigned(xdv, 1);
- if (b != XDV_ID) { fprintf(stderr, "*** bad XDV file: version=%d, expected %d\n", b, XDV_ID); exit(1); }
- (void)readUnsigned(xdv, 4); // num
- (void)readUnsigned(xdv, 4); // den
- if (sMag == 0)
- sMag = readUnsigned(xdv, 4); // sMag
- else
- (void)readUnsigned(xdv, 4);
-
- unsigned numBytes = readUnsigned(xdv, 1); // length of output comment
- UInt8* bytes = new UInt8[numBytes];
- fread(bytes, 1, numBytes, xdv);
-
- CFStringRef keys[2] = { CFSTR("Creator") , CFSTR("Title") /*, CFSTR("Author")*/ };
- CFStringRef values[2] = { CFSTR("xdv2pdf") , 0 /*, 0*/ };
- values[1] = CFStringCreateWithBytes(kCFAllocatorDefault, bytes, numBytes, CFStringGetSystemEncoding(), false);
- delete[] bytes;
-// values[2] = CFStringCreateWithCString(kCFAllocatorDefault, getlogin(), CFStringGetSystemEncoding());
- CFDictionaryRef auxInfo = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, sizeof(keys) / sizeof(keys[0]),
- &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFRelease(values[1]);
-// CFRelease(values[2]);
-
- // create PDF graphics context
- gCtx = CGPDFContextCreateWithURL(gSaveURL, &gMediaBox, auxInfo);
-
- // handle magnification
- if (sMag != 1000) {
- gMagScale = sMag / 1000.0;
- kScr2Dvi /= gMagScale;
- kDvi2Scr *= gMagScale;
- CGContextScaleCTM(gCtx, gMagScale, gMagScale);
- }
-
- // draw all the pages
- processAllPages(xdv);
-
- CGContextRelease(gCtx);
-
- while (getc(xdv) != EOF)
- ;
- fclose(xdv);
- }
-
- if (gPdfMarkFile != NULL) {
- fclose(gPdfMarkFile);
- char pdfPath[_POSIX_PATH_MAX+1];
- Boolean gotPath = CFURLGetFileSystemRepresentation(gSaveURL, true, (UInt8*)pdfPath, _POSIX_PATH_MAX);
- CFRelease(gSaveURL);
-#if 0
- if (gotPath) {
- char* mergeMarks = "xdv2pdf_mergemarks";
- execlp(mergeMarks, mergeMarks, pdfPath, gPdfMarkPath, 0); // should not return!
- status = errno;
- }
- fprintf(stderr, "*** failed to run xdv2pdf_mergemarks: status = %d\n", status);
-#else
- if (gotPath) {
- char* mergeMarks = "`kpsewhich -progname=xetex -format=texmfscripts xdv2pdf_mergemarks"
- " || echo echo '# ERROR: need xdv2pdf_mergemarks script to process:'`";
- char cmd[_POSIX_PATH_MAX*2 + 150]; // enough for the mergeMarks command above, plus some
- sprintf(cmd, "%s \"%s\" \"%s\"", mergeMarks, pdfPath, gPdfMarkPath);
- status = system(cmd);
- }
- else
- status = fnfErr;
- if (status != 0)
- fprintf(stderr, "*** failed to run xdv2pdf_mergemarks: status = %d\n", status);
-#endif
- }
- else
- CFRelease(gSaveURL);
-
- return status;
-}