[poppler] poppler/splash: Splash.cc, 1.10, 1.11 Splash.h, 1.3, 1.4 SplashBitmap.cc, 1.4, 1.5 SplashBitmap.h, 1.2, 1.3 SplashClip.cc, 1.2, 1.3 SplashClip.h, 1.2, 1.3 SplashFTFont.cc, 1.7, 1.8 SplashFTFont.h, 1.1.1.1, 1.2 SplashFTFontEngine.cc, 1.4, 1.5 SplashFTFontEngine.h, 1.3, 1.4 SplashFTFontFile.cc, 1.3, 1.4 SplashFTFontFile.h, 1.2, 1.3 SplashFont.cc, 1.3, 1.4 SplashFont.h, 1.2, 1.3 SplashFontEngine.cc, 1.4, 1.5 SplashFontEngine.h, 1.2, 1.3 SplashFontFile.cc, 1.3, 1.4 SplashFontFile.h, 1.2, 1.3 SplashMath.h, 1.2, 1.3 SplashPath.cc, 1.3, 1.4 SplashPath.h, 1.3, 1.4 SplashPattern.cc, 1.2, 1.3 SplashPattern.h, 1.2, 1.3 SplashScreen.cc, 1.3, 1.4 SplashScreen.h, 1.2, 1.3 SplashState.cc, 1.3, 1.4 SplashState.h, 1.2, 1.3 SplashT1Font.cc, 1.2, 1.3 SplashT1Font.h, 1.2, 1.3 SplashT1FontEngine.cc, 1.2, 1.3 SplashT1FontFile.cc, 1.3, 1.4 SplashT1FontFile.h, 1.2, 1.3 SplashTypes.h, 1.5, 1.6 SplashXPath.cc, 1.3, 1.4 SplashXPath.h, 1.1.1.1, 1.2 SplashXPathScanner.cc, 1.4, 1.5 SplashXPathScanner.h, 1.1.1.1, 1.2

Albert Astals Cid aacid at kemper.freedesktop.org
Wed Apr 25 12:59:13 PDT 2007


Update of /cvs/poppler/poppler/splash
In directory kemper:/tmp/cvs-serv1447/splash

Modified Files:
	Splash.cc Splash.h SplashBitmap.cc SplashBitmap.h 
	SplashClip.cc SplashClip.h SplashFTFont.cc SplashFTFont.h 
	SplashFTFontEngine.cc SplashFTFontEngine.h SplashFTFontFile.cc 
	SplashFTFontFile.h SplashFont.cc SplashFont.h 
	SplashFontEngine.cc SplashFontEngine.h SplashFontFile.cc 
	SplashFontFile.h SplashMath.h SplashPath.cc SplashPath.h 
	SplashPattern.cc SplashPattern.h SplashScreen.cc 
	SplashScreen.h SplashState.cc SplashState.h SplashT1Font.cc 
	SplashT1Font.h SplashT1FontEngine.cc SplashT1FontFile.cc 
	SplashT1FontFile.h SplashTypes.h SplashXPath.cc SplashXPath.h 
	SplashXPathScanner.cc SplashXPathScanner.h 
Log Message:
Merge xpdf302branch in HEAD as noone vetoed it.
Testing more than welcome


Index: Splash.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/Splash.cc,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- Splash.cc	19 Nov 2006 12:59:48 -0000	1.10
+++ Splash.cc	25 Apr 2007 19:59:10 -0000	1.11
@@ -28,23 +28,812 @@
 
 //------------------------------------------------------------------------
 
-static void blendNormal(SplashColorPtr src, SplashColorPtr dest,
-			SplashColorPtr blend, SplashColorMode cm) {
+// distance of Bezier control point from center for circle approximation
+// = (4 * (sqrt(2) - 1) / 3) * r
+#define bezierCircle ((SplashCoord)0.55228475)
+#define bezierCircle2 ((SplashCoord)(0.5 * 0.55228475))
+
+// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result.
[...4967 lines suppressed...]
-  return splashOk;
+  return pathOut;
 }
 
 void Splash::dumpPath(SplashPath *path) {
   int i;
 
   for (i = 0; i < path->length; ++i) {
-    printf("  %3d: x=%8.2f y=%8.2f%s%s%s%s%s\n",
+    printf("  %3d: x=%8.2f y=%8.2f%s%s%s%s\n",
 	   i, (double)path->pts[i].x, (double)path->pts[i].y,
 	   (path->flags[i] & splashPathFirst) ? " first" : "",
 	   (path->flags[i] & splashPathLast) ? " last" : "",
 	   (path->flags[i] & splashPathClosed) ? " closed" : "",
-	   (path->flags[i] & splashPathCurve) ? " curve" : "",
-	   (path->flags[i] & splashPathArcCW) ? " arcCW" : "");
+	   (path->flags[i] & splashPathCurve) ? " curve" : "");
   }
 }
 

Index: Splash.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/Splash.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Splash.h	30 Oct 2005 20:29:05 -0000	1.3
+++ Splash.h	25 Apr 2007 19:59:10 -0000	1.4
@@ -14,6 +14,7 @@
 #include "SplashTypes.h"
 #include "SplashClip.h"
 
+class Splash;
 class SplashBitmap;
 struct SplashGlyphBitmap;
 class SplashState;
@@ -22,6 +23,7 @@
 class SplashPath;
 class SplashXPath;
 class SplashFont;
+struct SplashPipe;
 
 //------------------------------------------------------------------------
 
@@ -33,7 +35,29 @@
 // Retrieves the next line of pixels in an image.  Normally, fills in
 // *<line> and returns true.  If the image stream is exhausted,
 // returns false.
-typedef GBool (*SplashImageSource)(void *data, SplashColorPtr line);
+typedef GBool (*SplashImageSource)(void *data, SplashColorPtr colorLine,
+				   Guchar *alphaLine);
+
+//------------------------------------------------------------------------
+
+enum SplashPipeResultColorCtrl {
+#if SPLASH_CMYK
+  splashPipeResultColorNoAlphaBlendCMYK,
+#endif
+  splashPipeResultColorNoAlphaBlendRGB,
+  splashPipeResultColorNoAlphaBlendMono,
+  splashPipeResultColorAlphaNoBlendMono,
+  splashPipeResultColorAlphaNoBlendRGB,
+#if SPLASH_CMYK
+  splashPipeResultColorAlphaNoBlendCMYK,
+#endif
+  splashPipeResultColorAlphaBlendMono,
+  splashPipeResultColorAlphaBlendRGB
+#if SPLASH_CMYK
+  ,
+  splashPipeResultColorAlphaBlendCMYK
+#endif
+};
 
 //------------------------------------------------------------------------
 // Splash
@@ -43,12 +67,16 @@
 public:
 
   // Create a new rasterizer object.
-  Splash(SplashBitmap *bitmapA);
+  Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
+	 SplashScreenParams *screenParams = NULL);
+  Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
+	 SplashScreen *screenA);
 
   ~Splash();
 
   //----- state read
 
+  SplashCoord *getMatrix();
   SplashPattern *getStrokePattern();
   SplashPattern *getFillPattern();
   SplashScreen *getScreen();
@@ -64,9 +92,12 @@
   int getLineDashLength();
   SplashCoord getLineDashPhase();
   SplashClip *getClip();
+  SplashBitmap *getSoftMask();
+  GBool getInNonIsolatedGroup();
 
   //----- state write
 
+  void setMatrix(SplashCoord *matrix);
   void setStrokePattern(SplashPattern *strokeColor);
   void setFillPattern(SplashPattern *fillColor);
   void setScreen(SplashScreen *screen);
@@ -81,25 +112,28 @@
   // the <lineDash> array will be copied
   void setLineDash(SplashCoord *lineDash, int lineDashLength,
 		   SplashCoord lineDashPhase);
+  void setStrokeAdjust(GBool strokeAdjust);
+  // NB: uses transformed coordinates.
   void clipResetToRect(SplashCoord x0, SplashCoord y0,
 		       SplashCoord x1, SplashCoord y1);
+  // NB: uses transformed coordinates.
   SplashError clipToRect(SplashCoord x0, SplashCoord y0,
 			 SplashCoord x1, SplashCoord y1);
+  // NB: uses untransformed coordinates.
   SplashError clipToPath(SplashPath *path, GBool eo);
+  void setSoftMask(SplashBitmap *softMask);
+  void setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA,
+			     int alpha0XA, int alpha0YA);
 
   //----- state save/restore
 
   void saveState();
   SplashError restoreState();
 
-  //----- soft mask
-
-  void setSoftMask(SplashBitmap *softMaskA);
-
   //----- drawing operations
 
   // Fill the bitmap with <color>.  This is not subject to clipping.
-  void clear(SplashColorPtr color);
+  void clear(SplashColorPtr color, Guchar alpha = 0x00);
 
   // Stroke a path using the current stroke pattern.
   SplashError stroke(SplashPath *path);
@@ -132,12 +166,15 @@
   // is assumed to produce pixels in raster order, starting from the
   // top line.
   SplashError fillImageMask(SplashImageMaskSource src, void *srcData,
-			    int w, int h, SplashCoord *mat);
+			    int w, int h, SplashCoord *mat,
+			    GBool glyphMode);
 
   // Draw an image.  This will read <h> lines of <w> pixels from
   // <src>, starting with the top line.  These pixels are assumed to
-  // be in the source mode, <srcMode>.  The following combinations of
-  // source and target modes are supported:
+  // be in the source mode, <srcMode>.  If <srcAlpha> is true, the
+  // alpha values returned by <src> are used; otherwise they are
+  // ignored.  The following combinations of source and target modes
+  // are supported:
   //    source       target
   //    ------       ------
   //    Mono1        Mono1
@@ -145,15 +182,35 @@
   //    Mono8        Mono8
   //    RGB8         RGB8
   //    BGR8         BGR8
-  //    ARGB8        RGB8    -- with source alpha (masking)
-  //    BGRA8        BGR8    -- with source alpha (masking)
+  //    CMYK8        CMYK8
   // The matrix behaves as for fillImageMask.
   SplashError drawImage(SplashImageSource src, void *srcData,
-			SplashColorMode srcMode,
+			SplashColorMode srcMode, GBool srcAlpha,
 			int w, int h, SplashCoord *mat);
 
+  // Composite a rectangular region from <src> onto this Splash
+  // object.
+  SplashError composite(SplashBitmap *src, int xSrc, int ySrc,
+			int xDest, int yDest, int w, int h,
+			GBool noClip, GBool nonIsolated);
+
+  // Composite this Splash object onto a background color.  The
+  // background alpha is assumed to be 1.
+  void compositeBackground(SplashColorPtr color);
+
+  // Copy a rectangular region from <src> onto the bitmap belonging to
+  // this Splash object.  The destination alpha values are all set to
+  // zero.
+  SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
+			      int xDest, int yDest, int w, int h);
+
   //----- misc
 
+  // Construct a path for a stroke, given the path to be stroked, and
+  // using the current line parameters.  If <flatten> is true, this
+  // function will first flatten the path and handle the linedash.
+  SplashPath *makeStrokePath(SplashPath *path, GBool flatten = gTrue);
+
   // Return the associated bitmap.
   SplashBitmap *getBitmap() { return bitmap; }
 
@@ -172,30 +229,62 @@
   // Toggle debug mode on or off.
   void setDebugMode(GBool debugModeA) { debugMode = debugModeA; }
 
+#if 1 //~tmp: turn off anti-aliasing temporarily
+  GBool getVectorAntialias() { return vectorAntialias; }
+  void setVectorAntialias(GBool vaa) { vectorAntialias = vaa; }
+#endif
+
 private:
 
+  void pipeInit(SplashPipe *pipe, int x, int y,
+		SplashPattern *pattern, SplashColorPtr cSrc,
+		SplashCoord aInput, GBool usesShape,
+		GBool nonIsolatedGroup);
+  void pipeRun(SplashPipe *pipe);
+  void pipeSetXY(SplashPipe *pipe, int x, int y);
+  void pipeIncX(SplashPipe *pipe);
+  void drawPixel(SplashPipe *pipe, int x, int y, GBool noClip);
+  void drawAAPixelInit();
+  void drawAAPixel(SplashPipe *pipe, int x, int y);
+  void drawSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip);
+  void drawAALine(SplashPipe *pipe, int x0, int x1, int y);
+  void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi,
+		 SplashCoord *xo, SplashCoord *yo);
   void updateModX(int x);
   void updateModY(int y);
-  void strokeNarrow(SplashXPath *xPath);
-  void strokeWide(SplashXPath *xPath);
-  SplashXPath *makeDashedPath(SplashXPath *xPath);
+  void strokeNarrow(SplashPath *path);
+  void strokeWide(SplashPath *path);
+  SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix,
+			  SplashCoord flatness);
+  void flattenCurve(SplashCoord x0, SplashCoord y0,
+		    SplashCoord x1, SplashCoord y1,
+		    SplashCoord x2, SplashCoord y2,
+		    SplashCoord x3, SplashCoord y3,
+		    SplashCoord *matrix, SplashCoord flatness2,
+		    SplashPath *fPath);
+  SplashPath *makeDashedPath(SplashPath *xPath);
   SplashError fillWithPattern(SplashPath *path, GBool eo,
 			      SplashPattern *pattern, SplashCoord alpha);
-  void drawPixel(int x, int y, SplashColorPtr color,
-		 SplashCoord alpha, GBool noClip);
-  void drawPixel(int x, int y, SplashPattern *pattern,
-		 SplashCoord alpha, GBool noClip);
-  void drawSpan(int x0, int x1, int y, SplashPattern *pattern,
-		SplashCoord alpha, GBool noClip);
-  void xorSpan(int x0, int x1, int y, SplashPattern *pattern, GBool noClip);
+  SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph);
   void dumpPath(SplashPath *path);
   void dumpXPath(SplashXPath *path);
 
+  static SplashPipeResultColorCtrl pipeResultColorNoAlphaBlend[];
+  static SplashPipeResultColorCtrl pipeResultColorAlphaNoBlend[];
+  static SplashPipeResultColorCtrl pipeResultColorAlphaBlend[];
+  static int pipeNonIsoGroupCorrection[];
+
   SplashBitmap *bitmap;
   SplashState *state;
-  SplashBitmap *softMask;
+  SplashBitmap *aaBuf;
+  int aaBufY;
+  SplashBitmap *alpha0Bitmap;	// for non-isolated groups, this is the
+				//   bitmap containing the alpha0 values
+  int alpha0X, alpha0Y;		// offset within alpha0Bitmap
+  SplashCoord aaGamma[splashAASize * splashAASize + 1];
   int modXMin, modYMin, modXMax, modYMax;
   SplashClipResult opClipRes;
+  GBool vectorAntialias;
   GBool debugMode;
 };
 

Index: SplashBitmap.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashBitmap.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- SplashBitmap.cc	23 May 2006 20:49:16 -0000	1.4
+++ SplashBitmap.cc	25 Apr 2007 19:59:10 -0000	1.5
@@ -20,7 +20,8 @@
 //------------------------------------------------------------------------
 
 SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad,
-			   SplashColorMode modeA, GBool topDown) {
+			   SplashColorMode modeA, GBool alphaA,
+			   GBool topDown) {
   width = widthA;
   height = heightA;
   mode = modeA;
@@ -31,24 +32,16 @@
   case splashModeMono8:
     rowSize = width;
     break;
-  case splashModeAMono8:
-    rowSize = width * 2;
-    break;
   case splashModeRGB8:
   case splashModeBGR8:
     rowSize = width * 3;
     break;
-  case splashModeRGB8Qt:
-  case splashModeARGB8:
-  case splashModeBGRA8:
-#if SPLASH_CMYK
-  case splashModeCMYK8:
-#endif
+  case splashModeRGBX8:
     rowSize = width * 4;
     break;
 #if SPLASH_CMYK
-  case splashModeACMYK8:
-    rowSize = width * 5;
+  case splashModeCMYK8:
+    rowSize = width * 4;
     break;
 #endif
   }
@@ -59,6 +52,11 @@
     data += (height - 1) * rowSize;
     rowSize = -rowSize;
   }
+  if (alphaA) {
+    alpha = (Guchar *)gmalloc(width * height);
+  } else {
+    alpha = NULL;
+  }
 }
 
 
@@ -68,6 +66,7 @@
   } else {
     gfree(data);
   }
+  gfree(alpha);
 }
 
 SplashError SplashBitmap::writePNMFile(char *fileName) {
@@ -107,19 +106,6 @@
     }
     break;
 
-  case splashModeAMono8:
-    fprintf(f, "P5\n%d %d\n255\n", width, height);
-    row = data;
-    for (y = 0; y < height; ++y) {
-      p = row;
-      for (x = 0; x < width; ++x) {
-	fputc(splashAMono8M(p), f);
-	p += 2;
-      }
-      row += rowSize;
-    }
-    break;
-
   case splashModeRGB8:
     fprintf(f, "P6\n%d %d\n255\n", width, height);
     row = data;
@@ -135,22 +121,7 @@
     }
     break;
 
-  case splashModeBGR8:
-    fprintf(f, "P6\n%d %d\n255\n", width, height);
-    row = data;
-    for (y = 0; y < height; ++y) {
-      p = row;
-      for (x = 0; x < width; ++x) {
-	fputc(splashBGR8R(p), f);
-	fputc(splashBGR8G(p), f);
-	fputc(splashBGR8B(p), f);
-	p += 3;
-      }
-      row += rowSize;
-    }
-    break;
-
- case splashModeRGB8Qt:
+  case splashModeRGBX8:
     fprintf(f, "P6\n%d %d\n255\n", width, height);
     row = data;
     for (y = 0; y < height; ++y) {
@@ -165,31 +136,17 @@
     }
     break;
 
-  case splashModeARGB8:
-    fprintf(f, "P6\n%d %d\n255\n", width, height);
-    row = data;
-    for (y = 0; y < height; ++y) {
-      p = row;
-      for (x = 0; x < width; ++x) {
-	fputc(splashARGB8R(p), f);
-	fputc(splashARGB8G(p), f);
-	fputc(splashARGB8B(p), f);
-	p += 4;
-      }
-      row += rowSize;
-    }
-    break;
 
-  case splashModeBGRA8:
+  case splashModeBGR8:
     fprintf(f, "P6\n%d %d\n255\n", width, height);
     row = data;
     for (y = 0; y < height; ++y) {
       p = row;
       for (x = 0; x < width; ++x) {
-	fputc(splashBGRA8R(p), f);
-	fputc(splashBGRA8G(p), f);
-	fputc(splashBGRA8B(p), f);
-	p += 4;
+	fputc(splashBGR8R(p), f);
+	fputc(splashBGR8G(p), f);
+	fputc(splashBGR8B(p), f);
+	p += 3;
       }
       row += rowSize;
     }
@@ -197,7 +154,6 @@
 
 #if SPLASH_CMYK
   case splashModeCMYK8:
-  case splashModeACMYK8:
     // PNM doesn't support CMYK
     break;
 #endif
@@ -217,49 +173,43 @@
   case splashModeMono1:
     p = &data[y * rowSize + (x >> 3)];
     pixel[0] = (p[0] >> (7 - (x & 7))) & 1;
+    pixel[0] = (p[0] & (0x80 >> (x & 7))) ? 0xff : 0x00;
     break;
   case splashModeMono8:
     p = &data[y * rowSize + x];
     pixel[0] = p[0];
     break;
-  case splashModeAMono8:
-    p = &data[y * rowSize + 2 * x];
-    pixel[0] = p[0];
-    pixel[1] = p[1];
-    break;
   case splashModeRGB8:
-  case splashModeBGR8:
     p = &data[y * rowSize + 3 * x];
     pixel[0] = p[0];
     pixel[1] = p[1];
     pixel[2] = p[2];
     break;
-  case splashModeRGB8Qt:
+  case splashModeRGBX8:
     p = &data[y * rowSize + 4 * x];
+    pixel[0] = p[0];
+    pixel[1] = p[1];
+    pixel[2] = p[2];
+    pixel[3] = p[3];
+    break;
+  case splashModeBGR8:
+    p = &data[y * rowSize + 3 * x];
     pixel[0] = p[2];
     pixel[1] = p[1];
     pixel[2] = p[0];
     break;
-  case splashModeARGB8:
-  case splashModeBGRA8:
 #if SPLASH_CMYK
   case splashModeCMYK8:
-#endif
     p = &data[y * rowSize + 4 * x];
     pixel[0] = p[0];
     pixel[1] = p[1];
     pixel[2] = p[2];
     pixel[3] = p[3];
     break;
-#if SPLASH_CMYK
-  case splashModeACMYK8:
-    p = &data[y * rowSize + 5 * x];
-    pixel[0] = p[0];
-    pixel[1] = p[1];
-    pixel[2] = p[2];
-    pixel[3] = p[3];
-    pixel[4] = p[4];
-    break;
 #endif
   }
 }
+
+Guchar SplashBitmap::getAlpha(int x, int y) {
+  return alpha[y * width + x];
+}

Index: SplashBitmap.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashBitmap.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashBitmap.h	30 Oct 2005 20:29:05 -0000	1.2
+++ SplashBitmap.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -25,19 +25,23 @@
   // <rowPad> bytes.  If <topDown> is false, the bitmap will be stored
   // upside-down, i.e., with the last row first in memory.
   SplashBitmap(int widthA, int heightA, int rowPad,
-	       SplashColorMode modeA, GBool topDown = gTrue);
+	       SplashColorMode modeA, GBool alphaA,
+	       GBool topDown = gTrue);
 
   ~SplashBitmap();
 
   int getWidth() { return width; }
   int getHeight() { return height; }
   int getRowSize() { return rowSize; }
+  int getAlphaRowSize() { return width; }
   SplashColorMode getMode() { return mode; }
   SplashColorPtr getDataPtr() { return data; }
+  Guchar *getAlphaPtr() { return alpha; }
 
   SplashError writePNMFile(char *fileName);
 
   void getPixel(int x, int y, SplashColorPtr pixel);
+  Guchar getAlpha(int x, int y);
 
 private:
 
@@ -45,7 +49,9 @@
   int rowSize;			// size of one row of data, in bytes
 				//   - negative for bottom-up bitmaps
   SplashColorMode mode;		// color mode
-  SplashColorPtr data;		// pointer to row zero of the bitmap data
+  SplashColorPtr data;		// pointer to row zero of the color data
+  Guchar *alpha;		// pointer to row zero of the alpha data
+				//   (always top-down)
 
   friend class Splash;
 };

Index: SplashClip.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashClip.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashClip.cc	27 Aug 2005 08:43:43 -0000	1.2
+++ SplashClip.cc	25 Apr 2007 19:59:10 -0000	1.3
@@ -14,10 +14,10 @@
 #include <string.h>
 #include "goo/gmem.h"
 #include "SplashErrorCodes.h"
-#include "SplashMath.h"
 #include "SplashPath.h"
 #include "SplashXPath.h"
 #include "SplashXPathScanner.h"
+#include "SplashBitmap.h"
 #include "SplashClip.h"
 
 //------------------------------------------------------------------------
@@ -31,21 +31,27 @@
 //------------------------------------------------------------------------
 
 SplashClip::SplashClip(SplashCoord x0, SplashCoord y0,
-		       SplashCoord x1, SplashCoord y1) {
+		       SplashCoord x1, SplashCoord y1,
+		       GBool antialiasA) {
+  antialias = antialiasA;
   if (x0 < x1) {
-    xMin = splashFloor(x0);
-    xMax = splashFloor(x1);
+    xMin = x0;
+    xMax = x1;
   } else {
-    xMin = splashFloor(x1);
-    xMax = splashFloor(x0);
+    xMin = x1;
+    xMax = x0;
   }
   if (y0 < y1) {
-    yMin = splashFloor(y0);
-    yMax = splashFloor(y1);
+    yMin = y0;
+    yMax = y1;
   } else {
-    yMin = splashFloor(y1);
-    yMax = splashFloor(y0);
+    yMin = y1;
+    yMax = y0;
   }
+  xMinI = splashFloor(xMin);
+  yMinI = splashFloor(yMin);
+  xMaxI = splashFloor(xMax);
+  yMaxI = splashFloor(yMax);
   paths = NULL;
   flags = NULL;
   scanners = NULL;
@@ -55,10 +61,15 @@
 SplashClip::SplashClip(SplashClip *clip) {
   int i;
 
+  antialias = clip->antialias;
   xMin = clip->xMin;
   yMin = clip->yMin;
   xMax = clip->xMax;
   yMax = clip->yMax;
+  xMinI = clip->xMinI;
+  yMinI = clip->yMinI;
+  xMaxI = clip->xMaxI;
+  yMaxI = clip->yMaxI;
   length = clip->length;
   size = clip->size;
   paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *));
@@ -116,98 +127,117 @@
   length = size = 0;
 
   if (x0 < x1) {
-    xMin = splashFloor(x0);
-    xMax = splashFloor(x1);
+    xMin = x0;
+    xMax = x1;
   } else {
-    xMin = splashFloor(x1);
-    xMax = splashFloor(x0);
+    xMin = x1;
+    xMax = x0;
   }
   if (y0 < y1) {
-    yMin = splashFloor(y0);
-    yMax = splashFloor(y1);
+    yMin = y0;
+    yMax = y1;
   } else {
-    yMin = splashFloor(y1);
-    yMax = splashFloor(y0);
+    yMin = y1;
+    yMax = y0;
   }
+  xMinI = splashFloor(xMin);
+  yMinI = splashFloor(yMin);
+  xMaxI = splashFloor(xMax);
+  yMaxI = splashFloor(yMax);
 }
 
 SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
 				   SplashCoord x1, SplashCoord y1) {
-  int x0I, y0I, x1I, y1I;
-
   if (x0 < x1) {
-    x0I = splashFloor(x0);
-    x1I = splashFloor(x1);
+    if (x0 > xMin) {
+      xMin = x0;
+      xMinI = splashFloor(xMin);
+    }
+    if (x1 < xMax) {
+      xMax = x1;
+      xMaxI = splashFloor(xMax);
+    }
   } else {
-    x0I = splashFloor(x1);
-    x1I = splashFloor(x0);
-  }
-  if (x0I > xMin) {
-    xMin = x0I;
-  }
-  if (x1I < xMax) {
-    xMax = x1I;
+    if (x1 > xMin) {
+      xMin = x1;
+      xMinI = splashFloor(xMin);
+    }
+    if (x0 < xMax) {
+      xMax = x0;
+      xMaxI = splashFloor(xMax);
+    }
   }
   if (y0 < y1) {
-    y0I = splashFloor(y0);
-    y1I = splashFloor(y1);
+    if (y0 > yMin) {
+      yMin = y0;
+      yMinI = splashFloor(yMin);
+    }
+    if (y1 < yMax) {
+      yMax = y1;
+      yMaxI = splashFloor(yMax);
+    }
   } else {
-    y0I = splashFloor(y1);
-    y1I = splashFloor(y0);
-  }
-  if (y0I > yMin) {
-    yMin = y0I;
-  }
-  if (y1I < yMax) {
-    yMax = y1I;
+    if (y1 > yMin) {
+      yMin = y1;
+      yMinI = splashFloor(yMin);
+    }
+    if (y0 < yMax) {
+      yMax = y0;
+      yMaxI = splashFloor(yMax);
+    }
   }
   return splashOk;
 }
 
-SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord flatness,
-				   GBool eo) {
+SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
+				   SplashCoord flatness, GBool eo) {
   SplashXPath *xPath;
 
-  xPath = new SplashXPath(path, flatness, gTrue);
+  xPath = new SplashXPath(path, matrix, flatness, gTrue);
 
   // check for an empty path
   if (xPath->length == 0) {
     xMax = xMin - 1;
     yMax = yMin - 1;
+    xMaxI = splashFloor(xMax);
+    yMaxI = splashFloor(yMax);
     delete xPath;
 
   // check for a rectangle
   } else if (xPath->length == 4 &&
-      ((xPath->segs[0].x0 == xPath->segs[0].x1 &&
-	xPath->segs[0].x0 == xPath->segs[1].x0 &&
-	xPath->segs[0].x0 == xPath->segs[3].x1 &&
-	xPath->segs[2].x0 == xPath->segs[2].x1 &&
-	xPath->segs[2].x0 == xPath->segs[1].x1 &&
-	xPath->segs[2].x0 == xPath->segs[3].x0 &&
-	xPath->segs[1].y0 == xPath->segs[1].y1 &&
-	xPath->segs[1].y0 == xPath->segs[0].y1 &&
-	xPath->segs[1].y0 == xPath->segs[2].y0 &&
-	xPath->segs[3].y0 == xPath->segs[3].y1 &&
-	xPath->segs[3].y0 == xPath->segs[0].y0 &&
-	xPath->segs[3].y0 == xPath->segs[2].y1) ||
-       (xPath->segs[0].y0 == xPath->segs[0].y1 &&
-	xPath->segs[0].y0 == xPath->segs[1].y0 &&
-	xPath->segs[0].y0 == xPath->segs[3].y1 &&
-	xPath->segs[2].y0 == xPath->segs[2].y1 &&
-	xPath->segs[2].y0 == xPath->segs[1].y1 &&
-	xPath->segs[2].y0 == xPath->segs[3].y0 &&
-	xPath->segs[1].x0 == xPath->segs[1].x1 &&
-	xPath->segs[1].x0 == xPath->segs[0].x1 &&
-	xPath->segs[1].x0 == xPath->segs[2].x0 &&
-	xPath->segs[3].x0 == xPath->segs[3].x1 &&
-	xPath->segs[3].x0 == xPath->segs[0].x0 &&
-	xPath->segs[3].x0 == xPath->segs[2].x1))) {
+	     ((xPath->segs[0].x0 == xPath->segs[0].x1 &&
+	       xPath->segs[0].x0 == xPath->segs[1].x0 &&
+	       xPath->segs[0].x0 == xPath->segs[3].x1 &&
+	       xPath->segs[2].x0 == xPath->segs[2].x1 &&
+	       xPath->segs[2].x0 == xPath->segs[1].x1 &&
+	       xPath->segs[2].x0 == xPath->segs[3].x0 &&
+	       xPath->segs[1].y0 == xPath->segs[1].y1 &&
+	       xPath->segs[1].y0 == xPath->segs[0].y1 &&
+	       xPath->segs[1].y0 == xPath->segs[2].y0 &&
+	       xPath->segs[3].y0 == xPath->segs[3].y1 &&
+	       xPath->segs[3].y0 == xPath->segs[0].y0 &&
+	       xPath->segs[3].y0 == xPath->segs[2].y1) ||
+	      (xPath->segs[0].y0 == xPath->segs[0].y1 &&
+	       xPath->segs[0].y0 == xPath->segs[1].y0 &&
+	       xPath->segs[0].y0 == xPath->segs[3].y1 &&
+	       xPath->segs[2].y0 == xPath->segs[2].y1 &&
+	       xPath->segs[2].y0 == xPath->segs[1].y1 &&
+	       xPath->segs[2].y0 == xPath->segs[3].y0 &&
+	       xPath->segs[1].x0 == xPath->segs[1].x1 &&
+	       xPath->segs[1].x0 == xPath->segs[0].x1 &&
+	       xPath->segs[1].x0 == xPath->segs[2].x0 &&
+	       xPath->segs[3].x0 == xPath->segs[3].x1 &&
+	       xPath->segs[3].x0 == xPath->segs[0].x0 &&
+	       xPath->segs[3].x0 == xPath->segs[2].x1))) {
     clipToRect(xPath->segs[0].x0, xPath->segs[0].y0,
 	       xPath->segs[2].x0, xPath->segs[2].y0);
     delete xPath;
 
   } else {
     grow(1);
+    if (antialias) {
+      xPath->aaScale();
+    }
     xPath->sort();
     paths[length] = xPath;
     flags[length] = eo ? splashClipEO : 0;
@@ -222,14 +252,22 @@
   int i;
 
   // check the rectangle
-  if (x < xMin || x > xMax || y < yMin || y > yMax) {
+  if (x < xMinI || x > xMaxI || y < yMinI || y > yMaxI) {
     return gFalse;
   }
 
   // check the paths
-  for (i = 0; i < length; ++i) {
-    if (!scanners[i]->test(x, y)) {
-      return gFalse;
+  if (antialias) {
+    for (i = 0; i < length; ++i) {
+      if (!scanners[i]->test(x * splashAASize, y * splashAASize)) {
+	return gFalse;
+      }
+    }
+  } else {
+    for (i = 0; i < length; ++i) {
+      if (!scanners[i]->test(x, y)) {
+	return gFalse;
+      }
     }
   }
 
@@ -238,12 +276,18 @@
 
 SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
 				      int rectXMax, int rectYMax) {
-  if (rectXMax < xMin || rectXMin > xMax ||
-      rectYMax < yMin || rectYMin > yMax) {
+  // This tests the rectangle:
+  //     x = [rectXMin, rectXMax + 1)    (note: rect coords are ints)
+  //     y = [rectYMin, rectYMax + 1)
+  // against the clipping region:
+  //     x = [xMin, xMax]                (note: clipping coords are fp)
+  //     y = [yMin, yMax]
+  if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin > xMax ||
+      (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin > yMax) {
     return splashClipAllOutside;
   }
-  if (rectXMin >= xMin && rectXMax <= xMax &&
-      rectYMin >= yMin && rectYMax <= yMax &&
+  if ((SplashCoord)rectXMin >= xMin && (SplashCoord)(rectXMax + 1) <= xMax &&
+      (SplashCoord)rectYMin >= yMin && (SplashCoord)(rectYMax + 1) <= yMax &&
       length == 0) {
     return splashClipAllInside;
   }
@@ -253,18 +297,86 @@
 SplashClipResult SplashClip::testSpan(int spanXMin, int spanXMax, int spanY) {
   int i;
 
-  if (spanXMax < xMin || spanXMin > xMax ||
-      spanY < yMin || spanY > yMax) {
+  // This tests the rectangle:
+  //     x = [spanXMin, spanXMax + 1)    (note: span coords are ints)
+  //     y = [spanY, spanY + 1)
+  // against the clipping region:
+  //     x = [xMin, xMax]                (note: clipping coords are fp)
+  //     y = [yMin, yMax]
+  if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin > xMax ||
+      (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY > yMax) {
     return splashClipAllOutside;
   }
-  if (!(spanXMin >= xMin && spanXMax <= xMax &&
-	spanY >= yMin && spanY <= yMax)) {
+  if (!((SplashCoord)spanXMin >= xMin && (SplashCoord)(spanXMax + 1) <= xMax &&
+	(SplashCoord)spanY >= yMin && (SplashCoord)(spanY + 1) <= yMax)) {
     return splashClipPartial;
   }
-  for (i = 0; i < length; ++i) {
-    if (!scanners[i]->testSpan(xMin, xMax, spanY)) {
-      return splashClipPartial;
+  if (antialias) {
+    for (i = 0; i < length; ++i) {
+      if (!scanners[i]->testSpan(spanXMin * splashAASize,
+				 spanXMax * splashAASize + (splashAASize - 1),
+				 spanY * splashAASize)) {
+	return splashClipPartial;
+      }
+    }
+  } else {
+    for (i = 0; i < length; ++i) {
+      if (!scanners[i]->testSpan(spanXMin, spanXMax, spanY)) {
+	return splashClipPartial;
+      }
     }
   }
   return splashClipAllInside;
 }
+
+void SplashClip::clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y) {
+  int xx0, xx1, xx, yy, i;
+  SplashColorPtr p;
+
+  // zero out pixels with x < xMin
+  xx0 = *x0 * splashAASize;
+  xx1 = splashFloor(xMin * splashAASize);
+  if (xx1 > aaBuf->getWidth()) {
+    xx1 = aaBuf->getWidth();
+  }
+  if (xx0 < xx1) {
+    xx0 &= ~7;
+    for (yy = 0; yy < splashAASize; ++yy) {
+      p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3);
+      for (xx = xx0; xx + 7 < xx1; xx += 8) {
+	*p++ = 0;
+      }
+      if (xx < xx1) {
+	*p &= 0xff >> (xx1 & 7);
+      }
+    }
+    *x0 = splashFloor(xMin);
+  }
+
+  // zero out pixels with x > xMax
+  xx0 = splashFloor(xMax * splashAASize) + 1;
+  if (xx0 < 0) {
+    xx0 = 0;
+  }
+  xx1 = (*x1 + 1) * splashAASize;
+  if (xx0 < xx1) {
+    for (yy = 0; yy < splashAASize; ++yy) {
+      p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx0 >> 3);
+      xx = xx0;
+      if (xx & 7) {
+	*p &= 0xff00 >> (xx & 7);
+	xx = (xx & ~7) + 8;
+	++p;
+      }
+      for (; xx < xx1; xx += 8) {
+	*p++ = 0;
+      }
+    }
+    *x1 = splashFloor(xMax);
+  }
+
+  // check the paths
+  for (i = 0; i < length; ++i) {
+    scanners[i]->clipAALine(aaBuf, x0, x1, y);
+  }
+}

Index: SplashClip.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashClip.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashClip.h	15 Sep 2005 21:51:16 -0000	1.2
+++ SplashClip.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -12,10 +12,12 @@
 #endif
 
 #include "SplashTypes.h"
+#include "SplashMath.h"
 
 class SplashPath;
 class SplashXPath;
 class SplashXPathScanner;
+class SplashBitmap;
 
 //------------------------------------------------------------------------
 
@@ -34,7 +36,8 @@
 
   // Create a clip, for the given rectangle.
   SplashClip(SplashCoord x0, SplashCoord y0,
-	     SplashCoord x1, SplashCoord y1);
+	     SplashCoord x1, SplashCoord y1,
+	     GBool antialiasA);
 
   // Copy a clip.
   SplashClip *copy() { return new SplashClip(this); }
@@ -50,8 +53,8 @@
 			 SplashCoord x1, SplashCoord y1);
 
   // Interesect the clip with <path>.
-  SplashError clipToPath(SplashPath *path, SplashCoord flatness,
-			 GBool eo);
+  SplashError clipToPath(SplashPath *path, SplashCoord *matrix,
+			 SplashCoord flatness, GBool eo);
 
   // Returns true if (<x>,<y>) is inside the clip.
   GBool test(int x, int y);
@@ -71,11 +74,16 @@
   // Similar to testRect, but tests a horizontal span.
   SplashClipResult testSpan(int spanXMin, int spanXMax, int spanY);
 
-  // Get the rectangle part of the clip region.
-  int getXMin() { return xMin; }
-  int getXMax() { return xMax; }
-  int getYMin() { return yMin; }
-  int getYMax() { return yMax; }
+  // Clips an anti-aliased line by setting pixels to zero.  On entry,
+  // all non-zero pixels are between <x0> and <x1>.  This function
+  // will update <x0> and <x1>.
+  void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y);
+
+  // Get the rectangle part of the clip region, in integer coordinates.
+  int getXMinI() { return xMinI; }
+  int getXMaxI() { return xMaxI; }
+  int getYMinI() { return yMinI; }
+  int getYMaxI() { return yMaxI; }
 
   // Get the number of arbitrary paths used by the clip region.
   int getNumPaths() { return length; }
@@ -85,7 +93,9 @@
   SplashClip(SplashClip *clip);
   void grow(int nPaths);
 
-  int xMin, yMin, xMax, yMax;
+  GBool antialias;
+  SplashCoord xMin, yMin, xMax, yMax;
+  int xMinI, yMinI, xMaxI, yMaxI;
   SplashXPath **paths;
   Guchar *flags;
   SplashXPathScanner **scanners;

Index: SplashFTFont.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFTFont.cc,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- SplashFTFont.cc	4 Apr 2006 20:42:08 -0000	1.7
+++ SplashFTFont.cc	25 Apr 2007 19:59:10 -0000	1.8
@@ -12,11 +12,6 @@
 #pragma implementation
 #endif
 
-#define MAKE_VERSION( a,b,c ) (((a) << 16) | ((b) << 8) | (c))
-
-#define FREETYPE_VERSION \
-	MAKE_VERSION(FREETYPE_MAJOR,FREETYPE_MINOR,FREETYPE_PATCH)
-
 #include <ft2build.h>
 #include FT_OUTLINE_H
 #include FT_SIZES_H
@@ -31,26 +26,20 @@
 
 //------------------------------------------------------------------------
 
-#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
 static int glyphPathMoveTo(const FT_Vector *pt, void *path);
 static int glyphPathLineTo(const FT_Vector *pt, void *path);
-static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt, void *path);
+static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt,
+			    void *path);
 static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2,
 			    const FT_Vector *pt, void *path);
-#else
-static int glyphPathMoveTo(FT_Vector *pt, void *path);
-static int glyphPathLineTo(FT_Vector *pt, void *path);
-static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path);
-static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2,
-			    FT_Vector *pt, void *path);
-#endif
 
 //------------------------------------------------------------------------
 // SplashFTFont
 //------------------------------------------------------------------------
 
-SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA):
-  SplashFont(fontFileA, matA, fontFileA->engine->aa)
+SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
+			   SplashCoord *textMatA):
+  SplashFont(fontFileA, matA, textMatA, fontFileA->engine->aa)
 {
   FT_Face face;
   double size, div;
@@ -65,6 +54,9 @@
   if (FT_Set_Pixel_Sizes(face, 0, (int)size)) {
     return;
   }
+  // if the textMat values are too small, FreeType's fixed point
+  // arithmetic doesn't work so well
+  textScale = splashSqrt(textMat[2]*textMat[2] + textMat[3]*textMat[3]) / size;
 
   div = face->bbox.xMax > 20000 ? 65536 : 1;
 
@@ -135,11 +127,19 @@
   matrix.yx = (FT_Fixed)((mat[1] / size).getRaw());
   matrix.xy = (FT_Fixed)((mat[2] / size).getRaw());
   matrix.yy = (FT_Fixed)((mat[3] / size).getRaw());
+  textMatrix.xx = (FT_Fixed)((textMat[0] / (size * textScale)).getRaw());
+  textMatrix.yx = (FT_Fixed)((textMat[1] / (size * textScale)).getRaw());
+  textMatrix.xy = (FT_Fixed)((textMat[2] / (size * textScale)).getRaw());
+  textMatrix.yy = (FT_Fixed)((textMat[3] / (size * textScale)).getRaw());
 #else
   matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
   matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
   matrix.xy = (FT_Fixed)((mat[2] / size) * 65536);
   matrix.yy = (FT_Fixed)((mat[3] / size) * 65536);
+  textMatrix.xx = (FT_Fixed)((textMat[0] / (size * textScale)) * 65536);
+  textMatrix.yx = (FT_Fixed)((textMat[1] / (size * textScale)) * 65536);
+  textMatrix.xy = (FT_Fixed)((textMat[2] / (size * textScale)) * 65536);
+  textMatrix.yy = (FT_Fixed)((textMat[3] / (size * textScale)) * 65536);
 #endif
 }
 
@@ -174,6 +174,10 @@
   } else {
     gid = (FT_UInt)c;
   }
+  if (ff->trueType && gid == 0) {
+    // skip the TrueType notdef glyph
+    return gFalse;
+  }
 
   // if we have the FT2 bytecode interpreter, autohinting won't be used
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@@ -220,15 +224,23 @@
 
 struct SplashFTFontPath {
   SplashPath *path;
+  SplashCoord textScale;
   GBool needClose;
 };
 
 SplashPath *SplashFTFont::getGlyphPath(int c) {
   static FT_Outline_Funcs outlineFuncs = {
+#if FREETYPE_MINOR <= 1
+    (int (*)(FT_Vector *, void *))&glyphPathMoveTo,
+    (int (*)(FT_Vector *, void *))&glyphPathLineTo,
+    (int (*)(FT_Vector *, FT_Vector *, void *))&glyphPathConicTo,
+    (int (*)(FT_Vector *, FT_Vector *, FT_Vector *, void *))&glyphPathCubicTo,
+#else
     &glyphPathMoveTo,
     &glyphPathLineTo,
     &glyphPathConicTo,
     &glyphPathCubicTo,
+#endif
     0, 0
   };
   SplashFTFontFile *ff;
@@ -239,13 +251,17 @@
 
   ff = (SplashFTFontFile *)fontFile;
   ff->face->size = sizeObj;
-  FT_Set_Transform(ff->face, &matrix, NULL);
+  FT_Set_Transform(ff->face, &textMatrix, NULL);
   slot = ff->face->glyph;
   if (ff->codeToGID && c < ff->codeToGIDLen) {
     gid = ff->codeToGID[c];
   } else {
     gid = (FT_UInt)c;
   }
+  if (ff->trueType && gid == 0) {
+    // skip the TrueType notdef glyph
+    return NULL;
+  }
   if (FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP)) {
     return NULL;
   }
@@ -253,6 +269,7 @@
     return NULL;
   }
   path.path = new SplashPath();
+  path.textScale = textScale;
   path.needClose = gFalse;
   FT_Outline_Decompose(&((FT_OutlineGlyph)glyph)->outline,
 		       &outlineFuncs, &path);
@@ -263,51 +280,39 @@
   return path.path;
 }
 
-#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
-static int glyphPathMoveTo(const FT_Vector *pt, void *path)
-#else
-static int glyphPathMoveTo(FT_Vector *pt, void *path)
-#endif
-{
+static int glyphPathMoveTo(const FT_Vector *pt, void *path) {
   SplashFTFontPath *p = (SplashFTFontPath *)path;
 
   if (p->needClose) {
     p->path->close();
     p->needClose = gFalse;
   }
-  p->path->moveTo(pt->x / 64.0, -pt->y / 64.0);
+  p->path->moveTo((SplashCoord)pt->x * p->textScale / 64.0,
+		  (SplashCoord)pt->y * p->textScale / 64.0);
   return 0;
 }
 
-#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
-static int glyphPathLineTo(const FT_Vector *pt, void *path)
-#else
-static int glyphPathLineTo(FT_Vector *pt, void *path)
-#endif
-{
+static int glyphPathLineTo(const FT_Vector *pt, void *path) {
   SplashFTFontPath *p = (SplashFTFontPath *)path;
 
-  p->path->lineTo(pt->x / 64.0, -pt->y / 64.0);
+  p->path->lineTo((SplashCoord)pt->x * p->textScale / 64.0,
+		  (SplashCoord)pt->y * p->textScale / 64.0);
   p->needClose = gTrue;
   return 0;
 }
 
-#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
-static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt, void *path)
-#else
-static int glyphPathConicTo(FT_Vector *ctrl, FT_Vector *pt, void *path)
-#endif
-{
+static int glyphPathConicTo(const FT_Vector *ctrl, const FT_Vector *pt,
+			    void *path) {
   SplashFTFontPath *p = (SplashFTFontPath *)path;
   SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xc, yc;
 
   if (!p->path->getCurPt(&x0, &y0)) {
     return 0;
   }
-  xc = ctrl->x / 64.0;
-  yc = -ctrl->y / 64.0;
-  x3 = pt->x / 64.0;
-  y3 = -pt->y / 64.0;
+  xc = (SplashCoord)ctrl->x * p->textScale / 64.0;
+  yc = (SplashCoord)ctrl->y * p->textScale / 64.0;
+  x3 = (SplashCoord)pt->x * p->textScale / 64.0;
+  y3 = (SplashCoord)pt->y * p->textScale / 64.0;
 
   // A second-order Bezier curve is defined by two endpoints, p0 and
   // p3, and one control point, pc:
@@ -335,17 +340,16 @@
   return 0;
 }
 
-#if ( FREETYPE_VERSION >= MAKE_VERSION(2,2,0) )
-static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2, const FT_Vector *pt, void *path)
-#else
-static int glyphPathCubicTo(FT_Vector *ctrl1, FT_Vector *ctrl2, FT_Vector *pt, void *path)
-#endif
-{
+static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2,
+			    const FT_Vector *pt, void *path) {
   SplashFTFontPath *p = (SplashFTFontPath *)path;
 
-  p->path->curveTo(ctrl1->x / 64.0, -ctrl1->y / 64.0,
-		   ctrl2->x / 64.0, -ctrl2->y / 64.0,
-		   pt->x / 64.0, -pt->y / 64.0);
+  p->path->curveTo((SplashCoord)ctrl1->x * p->textScale / 64.0,
+		   (SplashCoord)ctrl1->y * p->textScale / 64.0,
+		   (SplashCoord)ctrl2->x * p->textScale / 64.0,
+		   (SplashCoord)ctrl2->y * p->textScale / 64.0,
+		   (SplashCoord)pt->x * p->textScale / 64.0,
+		   (SplashCoord)pt->y * p->textScale / 64.0);
   p->needClose = gTrue;
   return 0;
 }

Index: SplashFTFont.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFTFont.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- SplashFTFont.h	3 Mar 2005 19:45:59 -0000	1.1.1.1
+++ SplashFTFont.h	25 Apr 2007 19:59:10 -0000	1.2
@@ -26,7 +26,8 @@
 class SplashFTFont: public SplashFont {
 public:
 
-  SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA);
+  SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
+	       SplashCoord *textMatA);
 
   virtual ~SplashFTFont();
 
@@ -46,6 +47,8 @@
 
   FT_Size sizeObj;
   FT_Matrix matrix;
+  FT_Matrix textMatrix;
+  SplashCoord textScale;
 };
 
 #endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H

Index: SplashFTFontEngine.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFTFontEngine.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- SplashFTFontEngine.cc	2 Feb 2006 22:50:01 -0000	1.4
+++ SplashFTFontEngine.cc	25 Apr 2007 19:59:10 -0000	1.5
@@ -75,6 +75,12 @@
   return SplashFTFontFile::loadType1Font(this, idA, src, enc);
 }
 
+SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
+							SplashFontSrc *src,
+							char **enc) {
+  return SplashFTFontFile::loadType1Font(this, idA, src, enc);
+}
+
 SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA,
 						SplashFontSrc *src) {
   FoFiType1C *ff;
@@ -90,15 +96,15 @@
     if (src->isFile) {
       ff = FoFiType1C::load(src->fileName->getCString());
     } else {
-      ff = new FoFiType1C(src->buf, src->bufLen, gFalse);
+      ff = FoFiType1C::make(src->buf, src->bufLen);
     }
     if (ff) {
-    cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
-    delete ff;
-  } else {
-    cidToGIDMap = NULL;
-    nCIDs = 0;
-  }
+      cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
+      delete ff;
+    } else {
+      cidToGIDMap = NULL;
+      nCIDs = 0;
+    }
   }
   ret = SplashFTFontFile::loadCIDFont(this, idA, src, cidToGIDMap, nCIDs);
   if (!ret) {
@@ -107,6 +113,38 @@
   return ret;
 }
 
+SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
+							SplashFontSrc *src) {
+  FoFiTrueType *ff;
+  GBool isCID;
+  Gushort *cidToGIDMap;
+  int nCIDs;
+  SplashFontFile *ret;
+
+  cidToGIDMap = NULL;
+  nCIDs = 0;
+  isCID = gFalse;
+  if (!useCIDs) {
+    if (src->isFile) {
+      ff = FoFiTrueType::load(src->fileName->getCString());
+    } else {
+      ff = FoFiTrueType::make(src->buf, src->bufLen);
+    }
+    if (ff) {
+      if (ff->isOpenTypeCFF()) {
+	cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
+      }
+      delete ff;
+    }
+  }
+  ret = SplashFTFontFile::loadCIDFont(this, idA, src,
+				      cidToGIDMap, nCIDs);
+  if (!ret) {
+    gfree(cidToGIDMap);
+  }
+  return ret;
+}
+
 SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
 						     SplashFontSrc *src,
 						     Gushort *codeToGID,
@@ -118,7 +156,7 @@
   FILE *tmpFile;
   SplashFontFile *ret;
 
-  if (!(ff = FoFiTrueType::load(fileName, faceIndex))) {
+  if (!(ff = FoFiTrueType::load(fileName))) {
     return NULL;
   }
   tmpFileName = NULL;

Index: SplashFTFontEngine.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFTFontEngine.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashFTFontEngine.h	2 Feb 2006 22:50:01 -0000	1.3
+++ SplashFTFontEngine.h	25 Apr 2007 19:59:10 -0000	1.4
@@ -33,12 +33,13 @@
   ~SplashFTFontEngine();
 
   // Load fonts.
-  SplashFontFile *loadType1Font(SplashFontFileID *idA, SplashFontSrc *src, char **enc);
-  SplashFontFile *loadType1CFont(SplashFontFileID *idA, SplashFontSrc *src, char **enc);
+  SplashFontFile *loadType1Font(SplashFontFileID *idA, SplashFontSrc *src,  char **enc);
+  SplashFontFile *loadType1CFont(SplashFontFileID *idA, SplashFontSrc *src,  char **enc);
+  SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, SplashFontSrc *src,  char **enc);
   SplashFontFile *loadCIDFont(SplashFontFileID *idA, SplashFontSrc *src);
+  SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, SplashFontSrc *src);
   SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, SplashFontSrc *src,
-				   Gushort *codeToGID, int codeToGIDLen,
-				   int faceIndex=0);
+				   Gushort *codeToGID, int codeToGIDLen, int faceIndex = 0);
 
 private:
 

Index: SplashFTFontFile.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFTFontFile.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashFTFontFile.cc	2 Feb 2006 22:50:01 -0000	1.3
+++ SplashFTFontFile.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -47,7 +47,7 @@
   }
 
   return new SplashFTFontFile(engineA, idA, src,
-			      faceA, codeToGIDA, 256);
+			      faceA, codeToGIDA, 256, gFalse);
 }
 
 SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA,
@@ -66,7 +66,7 @@
   }
 
   return new SplashFTFontFile(engineA, idA, src,
-			      faceA, codeToGIDA, codeToGIDLenA);
+			      faceA, codeToGIDA, codeToGIDLenA, gFalse);
 }
 
 SplashFontFile *SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA,
@@ -86,20 +86,22 @@
   }
 
   return new SplashFTFontFile(engineA, idA, src,
-			      faceA, codeToGIDA, codeToGIDLenA);
+			      faceA, codeToGIDA, codeToGIDLenA, gTrue);
 }
 
 SplashFTFontFile::SplashFTFontFile(SplashFTFontEngine *engineA,
 				   SplashFontFileID *idA,
-				   SplashFontSrc *srcA,
+				   SplashFontSrc *src,
 				   FT_Face faceA,
-				   Gushort *codeToGIDA, int codeToGIDLenA):
-  SplashFontFile(idA, srcA)
+				   Gushort *codeToGIDA, int codeToGIDLenA,
+				   GBool trueTypeA):
+  SplashFontFile(idA, src)
 {
   engine = engineA;
   face = faceA;
   codeToGID = codeToGIDA;
   codeToGIDLen = codeToGIDLenA;
+  trueType = trueTypeA;
 }
 
 SplashFTFontFile::~SplashFTFontFile() {
@@ -111,10 +113,11 @@
   }
 }
 
-SplashFont *SplashFTFontFile::makeFont(SplashCoord *mat) {
+SplashFont *SplashFTFontFile::makeFont(SplashCoord *mat,
+				       SplashCoord *textMat) {
   SplashFont *font;
 
-  font = new SplashFTFont(this, mat);
+  font = new SplashFTFont(this, mat, textMat);
   font->initCache();
   return font;
 }

Index: SplashFTFontFile.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFTFontFile.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashFTFontFile.h	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashFTFontFile.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -45,20 +45,23 @@
 
   // Create a new SplashFTFont, i.e., a scaled instance of this font
   // file.
-  virtual SplashFont *makeFont(SplashCoord *mat);
+  virtual SplashFont *makeFont(SplashCoord *mat,
+			       SplashCoord *textMat);
 
 private:
 
   SplashFTFontFile(SplashFTFontEngine *engineA,
 		   SplashFontFileID *idA,
-		   SplashFontSrc *srcA,
+		   SplashFontSrc *src,
 		   FT_Face faceA,
-		   Gushort *codeToGIDA, int codeToGIDLenA);
+		   Gushort *codeToGIDA, int codeToGIDLenA,
+		   GBool trueTypeA);
 
   SplashFTFontEngine *engine;
   FT_Face face;
   Gushort *codeToGID;
   int codeToGIDLen;
+  GBool trueType;
 
   friend class SplashFTFont;
 };

Index: SplashFont.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFont.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashFont.cc	15 Sep 2005 22:15:47 -0000	1.3
+++ SplashFont.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -31,13 +31,17 @@
 //------------------------------------------------------------------------
 
 SplashFont::SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
-		       GBool aaA) {
+		       SplashCoord *textMatA, GBool aaA) {
   fontFile = fontFileA;
   fontFile->incRefCnt();
   mat[0] = matA[0];
   mat[1] = matA[1];
   mat[2] = matA[2];
   mat[3] = matA[3];
+  textMat[0] = textMatA[0];
+  textMat[1] = textMatA[1];
+  textMat[2] = textMatA[2];
+  textMat[3] = textMatA[3];
   aa = aaA;
 
   cache = NULL;

Index: SplashFont.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFont.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashFont.h	15 Sep 2005 22:15:47 -0000	1.2
+++ SplashFont.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -35,7 +35,8 @@
 class SplashFont {
 public:
 
-  SplashFont(SplashFontFile *fontFileA, SplashCoord *matA, GBool aaA);
+  SplashFont(SplashFontFile *fontFileA, SplashCoord *matA,
+	     SplashCoord *textMatA, GBool aaA);
 
   // This must be called after the constructor, so that the subclass
   // constructor has a chance to compute the bbox.
@@ -46,10 +47,13 @@
   SplashFontFile *getFontFile() { return fontFile; }
 
   // Return true if <this> matches the specified font file and matrix.
-  GBool matches(SplashFontFile *fontFileA, SplashCoord *matA) {
+  GBool matches(SplashFontFile *fontFileA, SplashCoord *matA,
+		SplashCoord *textMatA) {
     return fontFileA == fontFile &&
            matA[0] == mat[0] && matA[1] == mat[1] &&
-           matA[2] == mat[2] && matA[3] == mat[3];
+           matA[2] == mat[2] && matA[3] == mat[3] &&
+           textMatA[0] == textMat[0] && textMatA[1] == textMat[1] &&
+           textMatA[2] == textMat[2] && textMatA[3] == textMat[3];
   }
 
   // Get a glyph - this does a cache lookup first, and if not found,
@@ -81,6 +85,9 @@
 
   SplashFontFile *fontFile;
   SplashCoord mat[4];		// font transform matrix
+				//   (text space -> device space)
+  SplashCoord textMat[4];	// text transform matrix
+				//   (text space -> user space)
   GBool aa;			// anti-aliasing
   int xMin, yMin, xMax, yMax;	// glyph bounding box
   Guchar *cache;		// glyph bitmap cache

Index: SplashFontEngine.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFontEngine.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- SplashFontEngine.cc	30 Jul 2006 09:38:28 -0000	1.4
+++ SplashFontEngine.cc	25 Apr 2007 19:59:10 -0000	1.5
@@ -21,6 +21,7 @@
 #endif
 #include "goo/gmem.h"
 #include "goo/GooString.h"
+#include "SplashMath.h"
 #include "SplashT1FontEngine.h"
 #include "SplashFTFontEngine.h"
 #include "SplashFontFile.h"
@@ -34,6 +35,12 @@
 #endif
 #endif
 
+#ifdef VMS
+#if (__VMS_VER < 70000000)
+extern "C" int unlink(char *filename);
+#endif
+#endif
+
 //------------------------------------------------------------------------
 // SplashFontEngine
 //------------------------------------------------------------------------
@@ -141,7 +148,7 @@
   fontFile = NULL;
 #if HAVE_T1LIB_H
   if (!fontFile && t1Engine) {
-    fontFile = t1Engine->loadType1CFont(idA, src, enc);
+    fontFile = t1Engine->loadType1CFont(idA, sec, enc);
   }
 #endif
 #if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
@@ -162,6 +169,28 @@
   return fontFile;
 }
 
+SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
+						      SplashFontSrc *src,
+						      char **enc) {
+  SplashFontFile *fontFile;
+
+  fontFile = NULL;
+#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+  if (!fontFile && ftEngine) {
+    fontFile = ftEngine->loadOpenTypeT1CFont(idA, src, enc);
+  }
+#endif
+
+  // delete the (temporary) font file -- with Unix hard link
+  // semantics, this will remove the last link; otherwise it will
+  // return an error, leaving the file to be deleted later (if
+  // loadXYZFont failed, the file will always be deleted)
+  if (src->isFile)
+    src->unref();
+
+  return fontFile;
+}
+
 SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA,
 					      SplashFontSrc *src) {
   SplashFontFile *fontFile;
@@ -185,6 +214,27 @@
   return fontFile;
 }
 
+SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
+						      SplashFontSrc *src) {
+  SplashFontFile *fontFile;
+
+  fontFile = NULL;
+#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+  if (!fontFile && ftEngine) {
+    fontFile = ftEngine->loadOpenTypeCFFFont(idA, src);
+  }
+#endif
+
+  // delete the (temporary) font file -- with Unix hard link
+  // semantics, this will remove the last link; otherwise it will
+  // return an error, leaving the file to be deleted later (if
+  // loadXYZFont failed, the file will always be deleted)
+  if (src->isFile)
+    src->unref();
+
+  return fontFile;
+}
+
 SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
 						   SplashFontSrc *src,
 						   Gushort *codeToGID,
@@ -217,17 +267,29 @@
 }
 
 SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile,
-				      SplashCoord *mat) {
+				      SplashCoord *textMat,
+				      SplashCoord *ctm) {
+  SplashCoord mat[4];
   SplashFont *font;
   int i, j;
 
+  mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2];
+  mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]);
+  mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2];
+  mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]);
+  if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.01) {
+    // avoid a singular (or close-to-singular) matrix
+    mat[0] = 0.01;  mat[1] = 0;
+    mat[2] = 0;     mat[3] = 0.01;
+  }
+
   font = fontCache[0];
-  if (font && font->matches(fontFile, mat)) {
+  if (font && font->matches(fontFile, mat, textMat)) {
     return font;
   }
   for (i = 1; i < splashFontCacheSize; ++i) {
     font = fontCache[i];
-    if (font && font->matches(fontFile, mat)) {
+    if (font && font->matches(fontFile, mat, textMat)) {
       for (j = i; j > 0; --j) {
 	fontCache[j] = fontCache[j-1];
       }
@@ -235,7 +297,7 @@
       return font;
     }
   }
-  font = fontFile->makeFont(mat);
+  font = fontFile->makeFont(mat, textMat);
   if (fontCache[splashFontCacheSize - 1]) {
     delete fontCache[splashFontCacheSize - 1];
   }

Index: SplashFontEngine.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFontEngine.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashFontEngine.h	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashFontEngine.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -16,6 +16,7 @@
 class SplashT1FontEngine;
 class SplashFTFontEngine;
 class SplashDTFontEngine;
+class SplashDT4FontEngine;
 class SplashFontFile;
 class SplashFontFileID;
 class SplashFont;
@@ -51,20 +52,22 @@
   // Load fonts - these create new SplashFontFile objects.
   SplashFontFile *loadType1Font(SplashFontFileID *idA, SplashFontSrc *src, char **enc);
   SplashFontFile *loadType1CFont(SplashFontFileID *idA, SplashFontSrc *src, char **enc);
+  SplashFontFile *loadOpenTypeT1CFont(SplashFontFileID *idA, SplashFontSrc *src, char **enc);
   SplashFontFile *loadCIDFont(SplashFontFileID *idA, SplashFontSrc *src);
+  SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA, SplashFontSrc *src);
   SplashFontFile *loadTrueTypeFont(SplashFontFileID *idA, SplashFontSrc *src,
-				   Gushort *codeToGID, int codeToGIDLen,
-				   int faceIndex=0);
+				   Gushort *codeToGID, int codeToGIDLen, int faceIndex = 0);
 
   // Get a font - this does a cache lookup first, and if not found,
   // creates a new SplashFont object and adds it to the cache.  The
-  // matrix:
+  // matrix, mat = textMat * ctm:
   //    [ mat[0] mat[1] ]
   //    [ mat[2] mat[3] ]
   // specifies the font transform in PostScript style:
   //    [x' y'] = [x y] * mat
   // Note that the Splash y axis points downward.
-  SplashFont *getFont(SplashFontFile *fontFile, SplashCoord *mat);
+  SplashFont *getFont(SplashFontFile *fontFile,
+		      SplashCoord *textMat, SplashCoord *ctm);
 
 private:
 

Index: SplashFontFile.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFontFile.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashFontFile.cc	2 Feb 2006 22:50:01 -0000	1.3
+++ SplashFontFile.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -104,4 +104,3 @@
   bufLen = bufLenA;
   deleteSrc = del;
 }
-

Index: SplashFontFile.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashFontFile.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashFontFile.h	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashFontFile.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -49,7 +49,7 @@
 
   // Create a new SplashFont, i.e., a scaled instance of this font
   // file.
-  virtual SplashFont *makeFont(SplashCoord *mat) = 0;
+  virtual SplashFont *makeFont(SplashCoord *mat, SplashCoord *textMat) = 0;
 
   // Get the font file ID.
   SplashFontFileID *getID() { return id; }

Index: SplashMath.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashMath.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashMath.h	16 Sep 2005 18:21:38 -0000	1.2
+++ SplashMath.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -7,7 +7,7 @@
 #ifndef SPLASHMATH_H
 #define SPLASHMATH_H
 
-#if USE_FIXEDPONT
+#if USE_FIXEDPOINT
 #include "FixedPoint.h"
 #else
 #include <math.h>
@@ -68,7 +68,18 @@
   dx = x1 - x0;
   dy = y1 - y0;
 #if USE_FIXEDPOINT
-  return FixedPoint::sqrt(dx * dx + dy * dy);
+  // this handles the situation where dx*dx or dy*dy is too large to
+  // fit in the 16.16 fixed point format
+  SplashCoord dxa, dya;
+  dxa = splashAbs(dx);
+  dya = splashAbs(dy);
+  if (dxa == 0 && dya == 0) {
+    return 0;
+  } else if (dxa > dya) {
+    return dxa * FixedPoint::sqrt(dya / dxa + 1);
+  } else {
+    return dya * FixedPoint::sqrt(dxa / dya + 1);
+  }
 #else
   return sqrt(dx * dx + dy * dy);
 #endif

Index: SplashPath.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashPath.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashPath.cc	15 Sep 2005 22:20:37 -0000	1.3
+++ SplashPath.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -35,6 +35,8 @@
   flags = NULL;
   length = size = 0;
   curSubpath = 0;
+  hints = NULL;
+  hintsLength = hintsSize = 0;
 }
 
 SplashPath::SplashPath(SplashPath *path) {
@@ -45,11 +47,19 @@
   memcpy(pts, path->pts, length * sizeof(SplashPathPoint));
   memcpy(flags, path->flags, length * sizeof(Guchar));
   curSubpath = path->curSubpath;
+  if (path->hints) {
+    hintsLength = hintsSize = path->hintsLength;
+    hints = (SplashPathHint *)gmallocn(hintsSize, sizeof(SplashPathHint));
+    memcpy(hints, path->hints, hintsLength * sizeof(SplashPathHint));
+  } else {
+    hints = NULL;
+  }
 }
 
 SplashPath::~SplashPath() {
   gfree(pts);
   gfree(flags);
+  gfree(hints);
 }
 
 // Add space for <nPts> more points.
@@ -126,24 +136,6 @@
   return splashOk;
 }
 
-SplashError SplashPath::arcCWTo(SplashCoord x1, SplashCoord y1,
-				SplashCoord xc, SplashCoord yc) {
-  if (noCurrentPoint()) {
-    return splashErrNoCurPt;
-  }
-  flags[length-1] &= ~splashPathLast;
-  grow(2);
-  pts[length].x = xc;
-  pts[length].y = yc;
-  flags[length] = splashPathArcCW;
-  ++length;
-  pts[length].x = x1;
-  pts[length].y = y1;
-  flags[length] = splashPathLast;
-  ++length;
-  return splashOk;
-}
-
 SplashError SplashPath::close() {
   if (noCurrentPoint()) {
     return splashErrNoCurPt;
@@ -159,6 +151,20 @@
   return splashOk;
 }
 
+void SplashPath::addStrokeAdjustHint(int ctrl0, int ctrl1,
+				     int firstPt, int lastPt) {
+  if (hintsLength == hintsSize) {
+    hintsSize = hintsLength ? 2 * hintsLength : 8;
+    hints = (SplashPathHint *)greallocn(hints, hintsSize,
+					sizeof(SplashPathHint));
+  }
+  hints[hintsLength].ctrl0 = ctrl0;
+  hints[hintsLength].ctrl1 = ctrl1;
+  hints[hintsLength].firstPt = firstPt;
+  hints[hintsLength].lastPt = lastPt;
+  ++hintsLength;
+}
+
 void SplashPath::offset(SplashCoord dx, SplashCoord dy) {
   int i;
 

Index: SplashPath.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashPath.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashPath.h	15 Sep 2005 22:20:37 -0000	1.3
+++ SplashPath.h	25 Apr 2007 19:59:10 -0000	1.4
@@ -26,20 +26,26 @@
 //------------------------------------------------------------------------
 
 // first point on each subpath sets this flag
-#define splashPathFirst  0x01
+#define splashPathFirst         0x01
 
 // last point on each subpath sets this flag
-#define splashPathLast   0x02
+#define splashPathLast          0x02
 
 // if the subpath is closed, its first and last points must be
 // identical, and must set this flag
-#define splashPathClosed 0x04
+#define splashPathClosed        0x04
 
 // curve control points set this flag
-#define splashPathCurve  0x08
+#define splashPathCurve         0x08
 
-// clockwise arc center points set this flag
-#define splashPathArcCW  0x10
+//------------------------------------------------------------------------
+// SplashPathHint
+//------------------------------------------------------------------------
+
+struct SplashPathHint {
+  int ctrl0, ctrl1;
+  int firstPt, lastPt;
+};
 
 //------------------------------------------------------------------------
 // SplashPath
@@ -71,14 +77,14 @@
 		      SplashCoord x2, SplashCoord y2,
 		      SplashCoord x3, SplashCoord y3);
 
-  // Add a clockwise circular arc with center (xc, yc) and endpoint
-  // (x1, y1).
-  SplashError arcCWTo(SplashCoord x1, SplashCoord y1,
-		      SplashCoord xc, SplashCoord yc);
-
   // Close the last subpath, adding a line segment if necessary.
   SplashError close();
 
+  // Add a stroke adjustment hint.  The controlling segments are
+  // <ctrl0> and <ctrl1> (where segments are identified by their first
+  // point), and the points to be adjusted are <firstPt> .. <lastPt>.
+  void addStrokeAdjustHint(int ctrl0, int ctrl1, int firstPt, int lastPt);
+
   // Add (<dx>, <dy>) to every point on this path.
   void offset(SplashCoord dx, SplashCoord dy);
 
@@ -103,6 +109,9 @@
   int length, size;		// length/size of the pts and flags arrays
   int curSubpath;		// index of first point in last subpath
 
+  SplashPathHint *hints;	// list of hints
+  int hintsLength, hintsSize;
+
   friend class SplashXPath;
   friend class Splash;
   // this is a temporary hack, until we read FreeType paths directly

Index: SplashPattern.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashPattern.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashPattern.cc	30 Oct 2005 20:29:05 -0000	1.2
+++ SplashPattern.cc	25 Apr 2007 19:59:10 -0000	1.3
@@ -38,31 +38,3 @@
 void SplashSolidColor::getColor(int x, int y, SplashColorPtr c) {
   splashColorCopy(c, color);
 }
-
-//------------------------------------------------------------------------
-// SplashHalftone
-//------------------------------------------------------------------------
-
-SplashHalftone::SplashHalftone(SplashColorPtr color0A, SplashColorPtr color1A,
-			       SplashScreen *screenA, SplashCoord valueA) {
-  splashColorCopy(color0, color0A);
-  splashColorCopy(color1, color1A);
-  screen = screenA;
-  value = valueA;
-}
-
-SplashPattern *SplashHalftone::copy() {
-  return new SplashHalftone(color0, color1, screen->copy(), value);
-}
-
-SplashHalftone::~SplashHalftone() {
-  delete screen;
-}
-
-void SplashHalftone::getColor(int x, int y, SplashColorPtr c) {
-  splashColorCopy(c, screen->test(x, y, value) ? color1 : color0);
-}
-
-GBool SplashHalftone::isStatic() {
-  return screen->isStatic(value);
-}

Index: SplashPattern.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashPattern.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashPattern.h	30 Oct 2005 20:29:05 -0000	1.2
+++ SplashPattern.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -60,29 +60,4 @@
   SplashColor color;
 };
 
-//------------------------------------------------------------------------
-// SplashHalftone
-//------------------------------------------------------------------------
-
-class SplashHalftone: public SplashPattern {
-public:
-
-  SplashHalftone(SplashColorPtr color0A, SplashColorPtr color1A,
-		 SplashScreen *screenA, SplashCoord valueA);
-
-  virtual SplashPattern *copy();
-
-  virtual ~SplashHalftone();
-
-  virtual void getColor(int x, int y, SplashColorPtr c);
-
-  virtual GBool isStatic();
-
-private:
-
-  SplashColor color0, color1;
-  SplashScreen *screen;
-  SplashCoord value;
-};
-
 #endif

Index: SplashScreen.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashScreen.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashScreen.cc	16 Oct 2005 14:25:32 -0000	1.3
+++ SplashScreen.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -10,34 +10,139 @@
 #pragma implementation
 #endif
 
+#include <stdlib.h>
 #include <string.h>
 #include "goo/gmem.h"
 #include "SplashMath.h"
 #include "SplashScreen.h"
 
+static SplashScreenParams defaultParams = {
+  splashScreenDispersed,	// type
+  2,				// size
+  2,				// dotRadius
+  1.0,				// gamma
+  0.0,				// blackThreshold
+  1.0				// whiteThreshold
+};
+
+//------------------------------------------------------------------------
+
+struct SplashScreenPoint {
+  int x, y;
+  int dist;
+};
+
+static int cmpDistances(const void *p0, const void *p1) {
+  return ((SplashScreenPoint *)p0)->dist - ((SplashScreenPoint *)p1)->dist;
+}
+
 //------------------------------------------------------------------------
 // SplashScreen
 //------------------------------------------------------------------------
 
-// This generates a 45 degree screen using a circular dot spot
-// function.  DPI = resolution / ((size / 2) * sqrt(2)).
-// Gamma correction (gamma = 1 / 1.33) is also computed here.
-SplashScreen::SplashScreen(int sizeA) {
+// If <clustered> is true, this generates a 45 degree screen using a
+// circular dot spot function.  DPI = resolution / ((size / 2) *
+// sqrt(2)).  If <clustered> is false, this generates an optimal
+// threshold matrix using recursive tesselation.  Gamma correction
+// (gamma = 1 / 1.33) is also computed here.
+SplashScreen::SplashScreen(SplashScreenParams *params) {
+  Guchar u, black, white;
+  int i;
+
+  if (!params) {
+    params = &defaultParams;
+  }
+
+  switch (params->type) {
+
+  case splashScreenDispersed:
+    // size must be a power of 2
+    for (size = 1; size < params->size; size <<= 1) ;
+    mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
+    buildDispersedMatrix(size/2, size/2, 1, size/2, 1);
+    break;
+
+  case splashScreenClustered:
+    // size must be even
+    size = (params->size >> 1) << 1;
+    if (size < 2) {
+      size = 2;
+    }
+    mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
+    buildClusteredMatrix();
+    break;
+
+  case splashScreenStochasticClustered:
+    // size must be at least 2*r
+    if (params->size < 2 * params->dotRadius) {
+      size = 2 * params->dotRadius;
+    } else {
+      size = params->size;
+    }
+    mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
+    buildSCDMatrix(params->dotRadius);
+    break;
+  }
+
+  // do gamma correction and compute minVal/maxVal
+  minVal = 255;
+  maxVal = 0;
+  black = splashRound((SplashCoord)255.0 * params->blackThreshold);
+  if (black < 1) {
+    black = 1;
+  }
+  int whiteAux = splashRound((SplashCoord)255.0 * params->whiteThreshold);
+  if (whiteAux > 255) {
+    white = 255;
+  } else {
+    white = whiteAux;
+  }
+   for (i = 0; i < size * size; ++i) {
+    u = splashRound((SplashCoord)255.0 *
+		    splashPow((SplashCoord)mat[i] / 255.0, params->gamma));
+    if (u < black) {
+      u = black;
+    } else if (u >= white) {
+      u = white;
+    }
+    mat[i] = u;
+    if (u < minVal) {
+      minVal = u;
+    } else if (u > maxVal) {
+      maxVal = u;
+    }
+  }
+}
+
+void SplashScreen::buildDispersedMatrix(int i, int j, int val,
+					int delta, int offset) {
+  if (delta == 0) {
+    // map values in [1, size^2] --> [1, 255]
+    mat[i * size + j] = 1 + (254 * (val - 1)) / (size * size - 1);
+  } else {
+    buildDispersedMatrix(i, j,
+			 val, delta / 2, 4*offset);
+    buildDispersedMatrix((i + delta) % size, (j + delta) % size,
+			 val + offset, delta / 2, 4*offset);
+    buildDispersedMatrix((i + delta) % size, j,
+			 val + 2*offset, delta / 2, 4*offset);
+    buildDispersedMatrix((i + 2*delta) % size, (j + delta) % size,
+			 val + 3*offset, delta / 2, 4*offset);
+  }
+}
+
+void SplashScreen::buildClusteredMatrix() {
   SplashCoord *dist;
-  SplashCoord u, v, d, val;
+  SplashCoord u, v, d;
+  Guchar val;
   int size2, x, y, x1, y1, i;
 
-  size2 = sizeA >> 1;
-  if (size2 < 1) {
-    size2 = 1;
-  }
-  size = size2 << 1;
+  size2 = size >> 1;
 
   // initialize the threshold matrix
-  mat = (SplashCoord *)gmallocn(size * size, sizeof(SplashCoord));
   for (y = 0; y < size; ++y) {
     for (x = 0; x < size; ++x) {
-      mat[y * size + x] = -1;
+      mat[y * size + x] = 0;
     }
   }
 
@@ -72,27 +177,22 @@
   minVal = 1;
   maxVal = 0;
   x1 = y1 = 0; // make gcc happy
-  for (i = 1; i <= size * size2; ++i) {
-    d = size * size2;
+  for (i = 0; i < size * size2; ++i) {
+    d = -1;
     for (y = 0; y < size; ++y) {
       for (x = 0; x < size2; ++x) {
-	if (mat[y * size + x] < 0 &&
-	    dist[y * size2 + x] < d) {
+	if (mat[y * size + x] == 0 &&
+	    dist[y * size2 + x] > d) {
 	  x1 = x;
 	  y1 = y;
 	  d = dist[y1 * size2 + x1];
 	}
       }
     }
-    u = (SplashCoord)1 - (SplashCoord)i / (SplashCoord)(size * size2 + 1);
-    val = splashPow(u, 1.33);
-    if (val < minVal) {
-      minVal = val;
-    }
-    if (val > maxVal) {
-      maxVal = val;
-    }
+    // map values in [0, 2*size*size2-1] --> [1, 255]
+    val = 1 + (254 * (2*i)) / (2*size*size2 - 1);
     mat[y1 * size + x1] = val;
+    val = 1 + (254 * (2*i+1)) / (2*size*size2 - 1);
     if (y1 < size2) {
       mat[(y1 + size2) * size + x1 + size2] = val;
     } else {
@@ -103,13 +203,155 @@
   gfree(dist);
 }
 
-SplashScreen::SplashScreen(SplashScreen *screen) {
-  int n;
+// Compute the distance between two points on a toroid.
+int SplashScreen::distance(int x0, int y0, int x1, int y1) {
+  int dx0, dx1, dx, dy0, dy1, dy;
+
+  dx0 = abs(x0 - x1);
+  dx1 = size - dx0;
+  dx = dx0 < dx1 ? dx0 : dx1;
+  dy0 = abs(y0 - y1);
+  dy1 = size - dy0;
+  dy = dy0 < dy1 ? dy0 : dy1;
+  return dx * dx + dy * dy;
+}
+
+// Algorithm taken from:
+// Victor Ostromoukhov and Roger D. Hersch, "Stochastic Clustered-Dot
+// Dithering" in Color Imaging: Device-Independent Color, Color
+// Hardcopy, and Graphic Arts IV, SPIE Vol. 3648, pp. 496-505, 1999.
+void SplashScreen::buildSCDMatrix(int r) {
+  SplashScreenPoint *dots, *pts;
+  int dotsLen, dotsSize;
+  char *tmpl;
+  char *grid;
+  int *region, *dist;
+  int x, y, xx, yy, x0, x1, y0, y1, i, j, d, iMin, dMin, n;
+
+  //~ this should probably happen somewhere else
+  srand(123);
+
+  // generate the random space-filling curve
+  pts = (SplashScreenPoint *)gmallocn(size * size, sizeof(SplashScreenPoint));
+  i = 0;
+  for (y = 0; y < size; ++y) {
+    for (x = 0; x < size; ++x) {
+      pts[i].x = x;
+      pts[i].y = y;
+      ++i;
+    }
+  }
+  for (i = 0; i < size * size; ++i) {
+    j = i + (int)((double)(size * size - i) *
+		  (double)rand() / ((double)RAND_MAX + 1.0));
+    x = pts[i].x;
+    y = pts[i].y;
+    pts[i].x = pts[j].x;
+    pts[i].y = pts[j].y;
+    pts[j].x = x;
+    pts[j].y = y;
+  }
+
+  // construct the circle template
+  tmpl = (char *)gmallocn((r+1)*(r+1), sizeof(char));
+  for (y = 0; y <= r; ++y) {
+    for (x = 0; x <= r; ++x) {
+      tmpl[y*(r+1) + x] = (x * y <= r * r) ? 1 : 0;
+    }
+  }
+
+  // mark all grid cells as free
+  grid = (char *)gmallocn(size * size, sizeof(char));
+  for (y = 0; y < size; ++y) {
+    for (x = 0; x < size; ++x) {
+      grid[y*size + x] = 0;
+    }
+  }
+
+  // walk the space-filling curve, adding dots
+  dotsLen = 0;
+  dotsSize = 32;
+  dots = (SplashScreenPoint *)gmallocn(dotsSize, sizeof(SplashScreenPoint));
+  for (i = 0; i < size * size; ++i) {
+    x = pts[i].x;
+    y = pts[i].y;
+    if (!grid[y*size + x]) {
+      if (dotsLen == dotsSize) {
+	dotsSize *= 2;
+	dots = (SplashScreenPoint *)greallocn(dots, dotsSize,
+					      sizeof(SplashScreenPoint));
+      }
+      dots[dotsLen++] = pts[i];
+      for (yy = 0; yy <= r; ++yy) {
+	y0 = (y + yy) % size;
+	y1 = (y - yy + size) % size;
+	for (xx = 0; xx <= r; ++xx) {
+	  if (tmpl[yy*(r+1) + xx]) {
+	    x0 = (x + xx) % size;
+	    x1 = (x - xx + size) % size;
+	    grid[y0*size + x0] = 1;
+	    grid[y0*size + x1] = 1;
+	    grid[y1*size + x0] = 1;
+	    grid[y1*size + x1] = 1;
+	  }
+	}
+      }
+    }
+  }
+
+  gfree(tmpl);
+  gfree(grid);
+
+  // assign each cell to a dot, compute distance to center of dot
+  region = (int *)gmallocn(size * size, sizeof(int));
+  dist = (int *)gmallocn(size * size, sizeof(int));
+  for (y = 0; y < size; ++y) {
+    for (x = 0; x < size; ++x) {
+      iMin = 0;
+      dMin = distance(dots[0].x, dots[0].y, x, y);
+      for (i = 1; i < dotsLen; ++i) {
+	d = distance(dots[i].x, dots[i].y, x, y);
+	if (d < dMin) {
+	  iMin = i;
+	  dMin = d;
+	}
+      }
+      region[y*size + x] = iMin;
+      dist[y*size + x] = dMin;
+    }
+  }
+
+  // compute threshold values
+  for (i = 0; i < dotsLen; ++i) {
+    n = 0;
+    for (y = 0; y < size; ++y) {
+      for (x = 0; x < size; ++x) {
+	if (region[y*size + x] == i) {
+	  pts[n].x = x;
+	  pts[n].y = y;
+	  pts[n].dist = distance(dots[i].x, dots[i].y, x, y);
+	  ++n;
+	}
+      }
+    }
+    qsort(pts, n, sizeof(SplashScreenPoint), &cmpDistances);
+    for (j = 0; j < n; ++j) {
+      // map values in [0 .. n-1] --> [255 .. 1]
+      mat[pts[j].y * size + pts[j].x] = 255 - (254 * j) / (n - 1);
+    }
+  }
+
+  gfree(pts);
+  gfree(region);
+  gfree(dist);
 
+  gfree(dots);
+}
+
+SplashScreen::SplashScreen(SplashScreen *screen) {
   size = screen->size;
-  n = size * size * sizeof(SplashCoord);
-  mat = (SplashCoord *)gmalloc(n);
-  memcpy(mat, screen->mat, n);
+  mat = (Guchar *)gmallocn(size * size, sizeof(Guchar));
+  memcpy(mat, screen->mat, size * size * sizeof(Guchar));
   minVal = screen->minVal;
   maxVal = screen->maxVal;
 }
@@ -118,7 +360,7 @@
   gfree(mat);
 }
 
-int SplashScreen::test(int x, int y, SplashCoord value) {
+int SplashScreen::test(int x, int y, Guchar value) {
   int xx, yy;
 
   if (value < minVal) {
@@ -136,6 +378,6 @@
   return value < mat[yy * size + xx] ? 0 : 1;
 }
 
-GBool SplashScreen::isStatic(SplashCoord value) {
+GBool SplashScreen::isStatic(Guchar value) {
   return value < minVal || value >= maxVal;
 }

Index: SplashScreen.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashScreen.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashScreen.h	16 Oct 2005 14:25:32 -0000	1.2
+++ SplashScreen.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -20,7 +20,7 @@
 class SplashScreen {
 public:
 
-  SplashScreen(int sizeA);
+  SplashScreen(SplashScreenParams *params);
   SplashScreen(SplashScreen *screen);
   ~SplashScreen();
 
@@ -28,20 +28,26 @@
 
   // Return the computed pixel value (0=black, 1=white) for the gray
   // level <value> at (<x>, <y>).
-  int test(int x, int y, SplashCoord value);
+  int test(int x, int y, Guchar value);
 
   // Returns true if value is above the white threshold or below the
   // black threshold, i.e., if the corresponding halftone will be
   // solid white or black.
-  GBool isStatic(SplashCoord value);
+  GBool isStatic(Guchar value);
 
 private:
 
-  SplashCoord *mat;		// threshold matrix
+  void buildDispersedMatrix(int i, int j, int val,
+			    int delta, int offset);
+  void buildClusteredMatrix();
+  int distance(int x0, int y0, int x1, int y1);
+  void buildSCDMatrix(int r);
+
+  Guchar *mat;			// threshold matrix
   int size;			// size of the threshold matrix
-  SplashCoord minVal;		// any pixel value below minVal generates
+  Guchar minVal;		// any pixel value below minVal generates
 				//   solid black
-  SplashCoord maxVal;		// any pixel value above maxVal generates
+  Guchar maxVal;		// any pixel value above maxVal generates
 				//   solid white
 };
 

Index: SplashState.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashState.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashState.cc	30 Oct 2005 20:29:05 -0000	1.3
+++ SplashState.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -15,6 +15,7 @@
 #include "SplashPattern.h"
 #include "SplashScreen.h"
 #include "SplashClip.h"
+#include "SplashBitmap.h"
 #include "SplashState.h"
 
 //------------------------------------------------------------------------
@@ -23,16 +24,20 @@
 
 // number of components in each color mode
 int splashColorModeNComps[] = {
-  1, 1, 2, 3, 3, 4, 4
+  1, 1, 3, 3, 4
 };
 
-SplashState::SplashState(int width, int height) {
+SplashState::SplashState(int width, int height, GBool vectorAntialias,
+			 SplashScreenParams *screenParams) {
   SplashColor color;
 
+  matrix[0] = 1;  matrix[1] = 0;
+  matrix[2] = 0;  matrix[3] = 1;
+  matrix[4] = 0;  matrix[5] = 0;
   memset(&color, 0, sizeof(SplashColor));
   strokePattern = new SplashSolidColor(color);
   fillPattern = new SplashSolidColor(color);
-  screen = new SplashScreen(10);
+  screen = new SplashScreen(screenParams);
   blendFunc = NULL;
   strokeAlpha = 1;
   fillAlpha = 1;
@@ -44,11 +49,46 @@
   lineDash = NULL;
   lineDashLength = 0;
   lineDashPhase = 0;
-  clip = new SplashClip(0, 0, width - 1, height - 1);
+  strokeAdjust = gFalse;
+  clip = new SplashClip(0, 0, width - 0.001, height - 0.001, vectorAntialias);
+  softMask = NULL;
+  deleteSoftMask = gFalse;
+  inNonIsolatedGroup = gFalse;
+  next = NULL;
+}
+
+SplashState::SplashState(int width, int height, GBool vectorAntialias,
+			 SplashScreen *screenA) {
+  SplashColor color;
+
+  matrix[0] = 1;  matrix[1] = 0;
+  matrix[2] = 0;  matrix[3] = 1;
+  matrix[4] = 0;  matrix[5] = 0;
+  memset(&color, 0, sizeof(SplashColor));
+  strokePattern = new SplashSolidColor(color);
+  fillPattern = new SplashSolidColor(color);
+  screen = screenA->copy();
+  blendFunc = NULL;
+  strokeAlpha = 1;
+  fillAlpha = 1;
+  lineWidth = 0;
+  lineCap = splashLineCapButt;
+  lineJoin = splashLineJoinMiter;
+  miterLimit = 10;
+  flatness = 1;
+  lineDash = NULL;
+  lineDashLength = 0;
+  lineDashPhase = 0;
+  strokeAdjust = gFalse;
+  clip = new SplashClip(0, 0, width - 0.001, height - 0.001, vectorAntialias);
+  softMask = NULL;
+  deleteSoftMask = gFalse;
+  inNonIsolatedGroup = gFalse;
   next = NULL;
 }
 
 SplashState::SplashState(SplashState *state) {
+  memcpy(matrix, state->matrix, 6 * sizeof(SplashCoord));
   strokePattern = state->strokePattern->copy();
   fillPattern = state->fillPattern->copy();
   screen = state->screen->copy();
@@ -69,7 +109,11 @@
     lineDashLength = 0;
   }
   lineDashPhase = state->lineDashPhase;
+  strokeAdjust = state->strokeAdjust;
   clip = state->clip->copy();
+  softMask = state->softMask;
+  deleteSoftMask = gFalse;
+  inNonIsolatedGroup = state->inNonIsolatedGroup;
   next = NULL;
 }
 
@@ -79,6 +123,9 @@
   delete screen;
   gfree(lineDash);
   delete clip;
+  if (deleteSoftMask && softMask) {
+    delete softMask;
+  }
 }
 
 void SplashState::setStrokePattern(SplashPattern *strokePatternA) {
@@ -108,3 +155,11 @@
   }
   lineDashPhase = lineDashPhaseA;
 }
+
+void SplashState::setSoftMask(SplashBitmap *softMaskA) {
+  if (deleteSoftMask) {
+    delete softMask;
+  }
+  softMask = softMaskA;
+  deleteSoftMask = gTrue;
+}

Index: SplashState.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashState.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashState.h	30 Oct 2005 20:29:05 -0000	1.2
+++ SplashState.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -16,6 +16,7 @@
 class SplashPattern;
 class SplashScreen;
 class SplashClip;
+class SplashBitmap;
 
 //------------------------------------------------------------------------
 // line cap values
@@ -41,7 +42,10 @@
 public:
 
   // Create a new state object, initialized with default settings.
-  SplashState(int width, int height);
+  SplashState(int width, int height, GBool vectorAntialias,
+	      SplashScreenParams *screenParams);
+  SplashState(int width, int height, GBool vectorAntialias,
+	      SplashScreen *screenA);
 
   // Copy a state object.
   SplashState *copy() { return new SplashState(this); }
@@ -61,10 +65,14 @@
   void setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
 		   SplashCoord lineDashPhaseA);
 
+  // Set the soft mask bitmap.
+  void setSoftMask(SplashBitmap *softMaskA);
+
 private:
 
   SplashState(SplashState *state);
 
+  SplashCoord matrix[6];
   SplashPattern *strokePattern;
   SplashPattern *fillPattern;
   SplashScreen *screen;
@@ -79,7 +87,11 @@
   SplashCoord *lineDash;
   int lineDashLength;
   SplashCoord lineDashPhase;
+  GBool strokeAdjust;
   SplashClip *clip;
+  SplashBitmap *softMask;
+  GBool deleteSoftMask;
+  GBool inNonIsolatedGroup;
 
   SplashState *next;		// used by Splash class
 

Index: SplashT1Font.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashT1Font.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashT1Font.cc	15 Sep 2005 22:24:55 -0000	1.2
+++ SplashT1Font.cc	25 Apr 2007 19:59:10 -0000	1.3
@@ -63,8 +63,9 @@
 // SplashT1Font
 //------------------------------------------------------------------------
 
-SplashT1Font::SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA):
-  SplashFont(fontFileA, matA, ((SplashT1FontFile *)fontFileA)->engine->aa)
+SplashT1Font::SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA,
+			   SplashCoord *textMatA):
+  SplashFont(fontFileA, matA, textMatA, fontFileA->engine->aa)
 {
   T1_TMATRIX matrix;
   BBox bbox;
@@ -72,6 +73,7 @@
   int x, y;
 
   t1libID = T1_CopyFont(fontFileA->t1libID);
+  outlineID = -1;
 
   // compute font size
   size = (float)splashSqrt(mat[2]*mat[2] + mat[3]*mat[3]);
@@ -168,6 +170,9 @@
 
 SplashT1Font::~SplashT1Font() {
   T1_DeleteFont(t1libID);
+  if (outlineID >= 0) {
+    T1_DeleteFont(outlineID);
+  }
 }
 
 GBool SplashT1Font::getGlyph(int c, int xFrac, int yFrac,
@@ -210,6 +215,7 @@
 }
 
 SplashPath *SplashT1Font::getGlyphPath(int c) {
+  T1_TMATRIX matrix;
   SplashPath *path;
   T1_OUTLINE *outline;
   T1_PATHSEGMENT *seg;
@@ -217,47 +223,64 @@
   SplashCoord x, y, x1, y1;
   GBool needClose;
 
-  path = new SplashPath();
-  if (!(outline = T1_GetCharOutline(t1libID, c, size, NULL))) {
-    return path;
+  if (outlineID < 0) {
+    outlineID = T1_CopyFont(((SplashT1FontFile *)fontFile)->t1libID);
+    outlineSize = (float)splashSqrt(textMat[2]*textMat[2] +
+				    textMat[3]*textMat[3]);
+    matrix.cxx = (double)textMat[0] / outlineSize;
+    matrix.cxy = (double)textMat[1] / outlineSize;
+    matrix.cyx = (double)textMat[2] / outlineSize;
+    matrix.cyy = (double)textMat[3] / outlineSize;
+    // t1lib doesn't seem to handle small sizes correctly here, so set
+    // the size to 1000, and scale the resulting coordinates later
+    outlineMul = (float)(outlineSize / 65536000.0);
+    outlineSize = 1000;
+    T1_TransformFont(outlineID, &matrix);
   }
-  x = 0;
-  y = 0;
-  needClose = gFalse;
-  for (seg = outline; seg; seg = seg->link) {
-    switch (seg->type) {
-    case T1_PATHTYPE_MOVE:
-      if (needClose) {
-	path->close();
-	needClose = gFalse;
+
+  path = new SplashPath();
+  if ((outline = T1_GetCharOutline(outlineID, c, outlineSize, NULL))) {
+    x = 0;
+    y = 0;
+    needClose = gFalse;
+    for (seg = outline; seg; seg = seg->link) {
+      switch (seg->type) {
+      case T1_PATHTYPE_MOVE:
+	if (needClose) {
+	  path->close();
+	  needClose = gFalse;
+	}
+	x += seg->dest.x * outlineMul;
+	y += seg->dest.y * outlineMul;
+	path->moveTo(x, -y);
+	break;
+      case T1_PATHTYPE_LINE:
+	x += seg->dest.x * outlineMul;
+	y += seg->dest.y * outlineMul;
+	path->lineTo(x, -y);
+	needClose = gTrue;
+	break;
+      case T1_PATHTYPE_BEZIER:
+	bez = (T1_BEZIERSEGMENT *)seg;
+	x1 = x + (SplashCoord)(bez->dest.x * outlineMul);
+	y1 = y + (SplashCoord)(bez->dest.y * outlineMul);
+	path->curveTo(x + (SplashCoord)(bez->B.x * outlineMul),
+		      -(y + (SplashCoord)(bez->B.y * outlineMul)),
+		      x + (SplashCoord)(bez->C.x * outlineMul),
+		      -(y + (SplashCoord)(bez->C.y * outlineMul)),
+		      x1, -y1);
+	x = x1;
+	y = y1;
+	needClose = gTrue;
+	break;
       }
-      x += seg->dest.x / 65536.0;
-      y += seg->dest.y / 65536.0;
-      path->moveTo(x, y);
-      break;
-    case T1_PATHTYPE_LINE:
-      x += seg->dest.x / 65536.0;
-      y += seg->dest.y / 65536.0;
-      path->lineTo(x, y);
-      needClose = gTrue;
-      break;
-    case T1_PATHTYPE_BEZIER:
-      bez = (T1_BEZIERSEGMENT *)seg;
-      x1 = x + bez->dest.x / 65536.0;
-      y1 = y + bez->dest.y / 65536.0;
-      path->curveTo(x + bez->B.x / 65536.0, y + bez->B.y / 65536.0,
-		    x + bez->C.x / 65536.0, y + bez->C.y / 65536.0,
-		    x1, y1);
-      x = x1;
-      y = y1;
-      needClose = gTrue;
-      break;
     }
+    if (needClose) {
+      path->close();
+    }
+    T1_FreeOutline(outline);
   }
-  if (needClose) {
-    path->close();
-  }
-  T1_FreeOutline(outline);
+
   return path;
 }
 

Index: SplashT1Font.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashT1Font.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashT1Font.h	15 Sep 2005 22:24:57 -0000	1.2
+++ SplashT1Font.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -24,7 +24,8 @@
 class SplashT1Font: public SplashFont {
 public:
 
-  SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA);
+  SplashT1Font(SplashT1FontFile *fontFileA, SplashCoord *matA,
+	       SplashCoord *textMatA);
 
   virtual ~SplashT1Font();
 
@@ -43,7 +44,10 @@
 private:
 
   int t1libID;			// t1lib font ID
+  int outlineID;		// t1lib font ID for glyph outlines
   float size;
+  float outlineSize;		// size for glyph outlines
+  float outlineMul;
 };
 
 #endif // HAVE_T1LIB_H

Index: SplashT1FontEngine.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashT1FontEngine.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashT1FontEngine.cc	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashT1FontEngine.cc	25 Apr 2007 19:59:10 -0000	1.3
@@ -84,7 +84,7 @@
 SplashFontFile *SplashT1FontEngine::loadType1Font(SplashFontFileID *idA,
 						  SplashFontSrc *src,
 						  char **enc) {
-  return SplashT1FontFile::loadType1Font(this, idA, src, enc);
+  return SplashT1FontFile::loadType1Font(this, idA, fileName, deleteFile, enc);
 }
 
 SplashFontFile *SplashT1FontEngine::loadType1CFont(SplashFontFileID *idA,
@@ -109,7 +109,7 @@
     delete ff;
     return NULL;
   }
-  ff->convertToType1(NULL, gTrue, &fileWrite, tmpFile);
+  ff->convertToType1(NULL, NULL, gTrue, &fileWrite, tmpFile);
   delete ff;
   fclose(tmpFile);
   newsrc = new SplashFontSrc;

Index: SplashT1FontFile.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashT1FontFile.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashT1FontFile.cc	2 Feb 2006 22:50:01 -0000	1.3
+++ SplashT1FontFile.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -33,6 +33,7 @@
   int encStrSize;
   char *encPtr;
   int i;
+
   GString *fileNameA;
   SplashFontSrc *newsrc = NULL;
   SplashFontFile *ff;
@@ -52,8 +53,7 @@
   fileNameA = src->fileName;
   // load the font file
   if ((t1libIDA = T1_AddFont(fileNameA)) < 0) {
-    if (newsrc)
-      delete newsrc;
+    delete newsrc;
     return NULL;
   }
   T1_LoadFont(t1libIDA);
@@ -105,10 +105,11 @@
   T1_DeleteFont(t1libID);
 }
 
-SplashFont *SplashT1FontFile::makeFont(SplashCoord *mat) {
+SplashFont *SplashT1FontFile::makeFont(SplashCoord *mat,
+				       SplashCoord *textMat) {
   SplashFont *font;
 
-  font = new SplashT1Font(this, mat);
+  font = new SplashT1Font(this, mat, textMat);
   font->initCache();
   return font;
 }

Index: SplashT1FontFile.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashT1FontFile.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- SplashT1FontFile.h	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashT1FontFile.h	25 Apr 2007 19:59:10 -0000	1.3
@@ -26,20 +26,21 @@
 
   static SplashFontFile *loadType1Font(SplashT1FontEngine *engineA,
 				       SplashFontFileID *idA,
-				       SplashFontSrc *src,
+				       char *fileNameA,
 				       char **encA);
 
   virtual ~SplashT1FontFile();
 
   // Create a new SplashT1Font, i.e., a scaled instance of this font
   // file.
-  virtual SplashFont *makeFont(SplashCoord *mat);
+  virtual SplashFont *makeFont(SplashCoord *mat,
+			       SplashCoord *textMat);
 
 private:
 
   SplashT1FontFile(SplashT1FontEngine *engineA,
 		   SplashFontFileID *idA,
-		   SplashFontSrc *src,
+		   char *fileNameA,
 		   int t1libIDA, char **encA, char *encStrA);
 
   SplashT1FontEngine *engine;

Index: SplashTypes.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashTypes.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- SplashTypes.h	23 May 2006 20:49:16 -0000	1.5
+++ SplashTypes.h	25 Apr 2007 19:59:10 -0000	1.6
@@ -21,6 +21,12 @@
 #endif
 
 //------------------------------------------------------------------------
+// antialiasing
+//------------------------------------------------------------------------
+
+#define splashAASize 4
+
+//------------------------------------------------------------------------
 // colors
 //------------------------------------------------------------------------
 
@@ -28,24 +34,16 @@
   splashModeMono1,		// 1 bit per component, 8 pixels per byte,
 				//   MSbit is on the left
   splashModeMono8,		// 1 byte per component, 1 byte per pixel
-  splashModeAMono8,		// 1 byte per component, 2 bytes per pixel:
-				//   AMAM...
   splashModeRGB8,		// 1 byte per component, 3 bytes per pixel:
 				//   RGBRGB...
   splashModeBGR8,		// 1 byte per component, 3 bytes per pixel:
 				//   BGRBGR...
-  splashModeARGB8,		// 1 byte per component, 4 bytes per pixel:
-				//   ARGBARGB...
-  splashModeRGB8Qt,		// 1 byte per component, 4 bytes per pixel:
-				//   Specially hacked to use in Qt frontends
-  splashModeBGRA8		// 1 byte per component, 4 bytes per pixel:
-				//   BGRABGRA...
+  splashModeRGBX8,	// 1 byte per component, 4 bytes per pixel:
+				//   RGBXRGBX...
 #if SPLASH_CMYK
   ,
-  splashModeCMYK8,		// 1 byte per component, 4 bytes per pixel:
+  splashModeCMYK8		// 1 byte per component, 4 bytes per pixel:
 				//   CMYKCMYK...
-  splashModeACMYK8		// 1 byte per component, 5 bytes per pixel:
-				//   ACMYKACMYK
 #endif
 };
 
@@ -55,18 +53,14 @@
 
 // max number of components in any SplashColor
 #if SPLASH_CMYK
-#  define splashMaxColorComps 5
-#else
 #  define splashMaxColorComps 4
+#else
+#  define splashMaxColorComps 3
 #endif
 
 typedef Guchar SplashColor[splashMaxColorComps];
 typedef Guchar *SplashColorPtr;
 
-// AMono8
-static inline Guchar splashAMono8A(SplashColorPtr am8) { return am8[0]; }
-static inline Guchar splashAMono8M(SplashColorPtr am8) { return am8[1]; }
-
 // RGB8
 static inline Guchar splashRGB8R(SplashColorPtr rgb8) { return rgb8[0]; }
 static inline Guchar splashRGB8G(SplashColorPtr rgb8) { return rgb8[1]; }
@@ -77,40 +71,20 @@
 static inline Guchar splashBGR8G(SplashColorPtr bgr8) { return bgr8[1]; }
 static inline Guchar splashBGR8B(SplashColorPtr bgr8) { return bgr8[0]; }
 
-// ARGB8
-static inline Guchar splashARGB8A(SplashColorPtr argb8) { return argb8[0]; }
-static inline Guchar splashARGB8R(SplashColorPtr argb8) { return argb8[1]; }
-static inline Guchar splashARGB8G(SplashColorPtr argb8) { return argb8[2]; }
-static inline Guchar splashARGB8B(SplashColorPtr argb8) { return argb8[3]; }
-
-// ARGB8
-static inline Guchar splashBGRA8A(SplashColorPtr bgra8) { return bgra8[3]; }
-static inline Guchar splashBGRA8R(SplashColorPtr bgra8) { return bgra8[2]; }
-static inline Guchar splashBGRA8G(SplashColorPtr bgra8) { return bgra8[1]; }
-static inline Guchar splashBGRA8B(SplashColorPtr bgra8) { return bgra8[0]; }
-
 #if SPLASH_CMYK
 // CMYK8
 static inline Guchar splashCMYK8C(SplashColorPtr cmyk8) { return cmyk8[0]; }
 static inline Guchar splashCMYK8M(SplashColorPtr cmyk8) { return cmyk8[1]; }
 static inline Guchar splashCMYK8Y(SplashColorPtr cmyk8) { return cmyk8[2]; }
 static inline Guchar splashCMYK8K(SplashColorPtr cmyk8) { return cmyk8[3]; }
-
-// ACMYK8
-static inline Guchar splashACMYK8A(SplashColorPtr acmyk8) { return acmyk8[0]; }
-static inline Guchar splashACMYK8C(SplashColorPtr acmyk8) { return acmyk8[1]; }
-static inline Guchar splashACMYK8M(SplashColorPtr acmyk8) { return acmyk8[2]; }
-static inline Guchar splashACMYK8Y(SplashColorPtr acmyk8) { return acmyk8[3]; }
-static inline Guchar splashACMYK8K(SplashColorPtr acmyk8) { return acmyk8[4]; }
 #endif
 
 static inline void splashColorCopy(SplashColorPtr dest, SplashColorPtr src) {
   dest[0] = src[0];
   dest[1] = src[1];
   dest[2] = src[2];
-  dest[3] = src[3];
 #if SPLASH_CMYK
-  dest[4] = src[4];
+  dest[3] = src[3];
 #endif
 }
 
@@ -118,9 +92,8 @@
   dest[0] ^= src[0];
   dest[1] ^= src[1];
   dest[2] ^= src[2];
-  dest[3] ^= src[3];
 #if SPLASH_CMYK
-  dest[4] ^= src[4];
+  dest[3] ^= src[3];
 #endif
 }
 
@@ -132,6 +105,25 @@
 				SplashColorPtr blend, SplashColorMode cm);
 
 //------------------------------------------------------------------------
+// screen parameters
+//------------------------------------------------------------------------
+
+enum SplashScreenType {
+  splashScreenDispersed,
+  splashScreenClustered,
+  splashScreenStochasticClustered
+};
+
+struct SplashScreenParams {
+  SplashScreenType type;
+  int size;
+  int dotRadius;
+  SplashCoord gamma;
+  SplashCoord blackThreshold;
+  SplashCoord whiteThreshold;
+};
+
+//------------------------------------------------------------------------
 // error results
 //------------------------------------------------------------------------
 

Index: SplashXPath.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashXPath.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- SplashXPath.cc	16 Sep 2005 18:00:43 -0000	1.3
+++ SplashXPath.cc	25 Apr 2007 19:59:10 -0000	1.4
@@ -19,7 +19,31 @@
 
 //------------------------------------------------------------------------
 
-#define maxCurveSplits (1 << 10)
+struct SplashXPathPoint {
+  SplashCoord x, y;
+};
+
+struct SplashXPathAdjust {
+  int firstPt, lastPt;		// range of points
+  GBool vert;			// vertical or horizontal hint
+  SplashCoord x0a, x0b,		// hint boundaries
+              xma, xmb,
+              x1a, x1b;
+  SplashCoord x0, x1, xm;	// adjusted coordinates
+};
+
+//------------------------------------------------------------------------
+
+// Transform a point from user space to device space.
+inline void SplashXPath::transform(SplashCoord *matrix,
+				   SplashCoord xi, SplashCoord yi,
+				   SplashCoord *xo, SplashCoord *yo) {
+  //                          [ m[0] m[1] 0 ]
+  // [xo yo 1] = [xi yi 1] *  [ m[2] m[3] 0 ]
+  //                          [ m[4] m[5] 1 ]
+  *xo = xi * matrix[0] + yi * matrix[2] + matrix[4];
+  *yo = xi * matrix[1] + yi * matrix[3] + matrix[5];
+}
 
 //------------------------------------------------------------------------
 // SplashXPath
@@ -30,32 +54,118 @@
   length = size = 0;
 }
 
-SplashXPath::SplashXPath(SplashPath *path, SplashCoord flatness,
-			 GBool closeSubpaths) {
-  SplashCoord xc, yc, dx, dy, r, x0, y0, x1, y1;
-  int quad0, quad1, quad;
-  int curSubpath, n, i, j;
+SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
+			 SplashCoord flatness, GBool closeSubpaths) {
+  SplashPathHint *hint;
+  SplashXPathPoint *pts;
+  SplashXPathAdjust *adjusts, *adjust;
+  SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xsp, ysp;
+  SplashCoord adj0, adj1, w;
+  int ww;
+  int curSubpath, curSubpathX, i, j;
+
+  // transform the points
+  pts = (SplashXPathPoint *)gmallocn(path->length, sizeof(SplashXPathPoint));
+  for (i = 0; i < path->length; ++i) {
+    transform(matrix, path->pts[i].x, path->pts[i].y, &pts[i].x, &pts[i].y);
+  }
+
+  // set up the stroke adjustment hints
+  if (path->hints) {
+    adjusts = (SplashXPathAdjust *)gmallocn(path->hintsLength,
+					    sizeof(SplashXPathAdjust));
+    for (i = 0; i < path->hintsLength; ++i) {
+      hint = &path->hints[i];
+      if (hint->ctrl0 + 1 >= path->length || hint->ctrl1 + 1 >= path->length) {
+	gfree(adjusts);
+	adjusts = NULL;
+	break;
+      }
+      x0 = pts[hint->ctrl0    ].x;    y0 = pts[hint->ctrl0    ].y;
+      x1 = pts[hint->ctrl0 + 1].x;    y1 = pts[hint->ctrl0 + 1].y;
+      x2 = pts[hint->ctrl1    ].x;    y2 = pts[hint->ctrl1    ].y;
+      x3 = pts[hint->ctrl1 + 1].x;    y3 = pts[hint->ctrl1 + 1].y;
+      if (x0 == x1 && x2 == x3) {
+	adjusts[i].vert = gTrue;
+	adj0 = x0;
+	adj1 = x2;
+      } else if (y0 == y1 && y2 == y3) {
+	adjusts[i].vert = gFalse;
+	adj0 = y0;
+	adj1 = y2;
+      } else {
+	gfree(adjusts);
+	adjusts = NULL;
+	break;
+      }
+      if (adj0 > adj1) {
+	x0 = adj0;
+	adj0 = adj1;
+	adj1 = x0;
+      }
+      w = adj1 - adj0;
+      ww = splashRound(w);
+      if (ww == 0) {
+	ww = 1;
+      }
+      adjusts[i].x0a = adj0 - 0.01;
+      adjusts[i].x0b = adj0 + 0.01;
+      adjusts[i].xma = (SplashCoord)0.5 * (adj0 + adj1) - 0.01;
+      adjusts[i].xmb = (SplashCoord)0.5 * (adj0 + adj1) + 0.01;
+      adjusts[i].x1a = adj1 - 0.01;
+      adjusts[i].x1b = adj1 + 0.01;
+      adjusts[i].x0 = (SplashCoord)splashRound(adj0);
+      adjusts[i].x1 = adjusts[i].x0 + ww - 0.01;
+      adjusts[i].xm = (SplashCoord)0.5 * (adjusts[i].x0 + adjusts[i].x1);
+      adjusts[i].firstPt = hint->firstPt;
+      adjusts[i].lastPt = hint->lastPt;
+    }
+
+  } else {
+    adjusts = NULL;
+  }
+
+  // perform stroke adjustment
+  if (adjusts) {
+    for (i = 0, adjust = adjusts; i < path->hintsLength; ++i, ++adjust) {
+      for (j = adjust->firstPt; j <= adjust->lastPt; ++j) {
+	strokeAdjust(adjust, &pts[j].x, &pts[j].y);
+      }
+    }
+    gfree(adjusts);
+  }
 
   segs = NULL;
   length = size = 0;
 
-  i = 0;
+  x0 = y0 = xsp = ysp = 0; // make gcc happy
+  adj0 = adj1 = 0; // make gcc happy
   curSubpath = 0;
+  curSubpathX = 0;
+  i = 0;
   while (i < path->length) {
 
     // first point in subpath - skip it
     if (path->flags[i] & splashPathFirst) {
+      x0 = pts[i].x;
+      y0 = pts[i].y;
+      xsp = x0;
+      ysp = y0;
       curSubpath = i;
+      curSubpathX = length;
       ++i;
 
     } else {
 
       // curve segment
       if (path->flags[i] & splashPathCurve) {
-	addCurve(path->pts[i-1].x, path->pts[i-1].y,
-		 path->pts[i  ].x, path->pts[i  ].y,
-		 path->pts[i+1].x, path->pts[i+1].y,
-		 path->pts[i+2].x, path->pts[i+2].y,
+	x1 = pts[i].x;
+	y1 = pts[i].y;
+	x2 = pts[i+1].x;
+	y2 = pts[i+1].y;
+	x3 = pts[i+2].x;
+	y3 = pts[i+2].y;
+	addCurve(x0, y0, x1, y1, x2, y2, x3, y3,
 		 flatness,
 		 (path->flags[i-1] & splashPathFirst),
 		 (path->flags[i+2] & splashPathLast),
@@ -65,83 +175,15 @@
 		 !closeSubpaths &&
 		   (path->flags[i+2] & splashPathLast) &&
 		   !(path->flags[i+2] & splashPathClosed));
+	x0 = x3;
+	y0 = y3;
 	i += 3;
 
-      // clockwise circular arc
-      } else if (path->flags[i] & splashPathArcCW) {
-	xc = path->pts[i].x;
-	yc = path->pts[i].y;
-	dx = path->pts[i+1].x - xc;
-	dy = path->pts[i+1].y - yc;
-	r = splashSqrt(dx * dx + dy * dy);
-	if (path->pts[i-1].x < xc && path->pts[i-1].y <= yc) {
-	  quad0 = 0;
-	} else if (path->pts[i-1].x >= xc && path->pts[i-1].y < yc) {
-	  quad0 = 1;
-	} else if (path->pts[i-1].x > xc && path->pts[i-1].y >= yc) {
-	  quad0 = 2;
-	} else {
-	  quad0 = 3;
-	}
-	if (path->pts[i+1].x <= xc && path->pts[i+1].y < yc) {
-	  quad1 = 0;
-	} else if (path->pts[i+1].x > xc && path->pts[i+1].y <= yc) {
-	  quad1 = 1;
-	} else if (path->pts[i+1].x >= xc && path->pts[i+1].y > yc) {
-	  quad1 = 2;
-	} else {
-	  quad1 = 3;
-	}
-	n = 0; // make gcc happy
-	if (quad0 == quad1) {
-	  switch (quad0) {
-	  case 0:
-	  case 1: n = path->pts[i-1].x < path->pts[i+1].x ? 0 : 4; break;
-	  case 2:
-	  case 3: n = path->pts[i-1].x > path->pts[i+1].x ? 0 : 4; break;
-	  }
-	} else {
-	  n = (quad1 - quad0) & 3;
-	}
-	x0 = path->pts[i-1].x;
-	y0 = path->pts[i-1].y;
-	x1 = y1 = 0; // make gcc happy
-	quad = quad0;
-	for (j = 0; j < n; ++j) {
-	  switch (quad) {
-	  case 0: x1 = xc;     y1 = yc - r; break;
-	  case 1: x1 = xc + r; y1 = yc;     break;
-	  case 2: x1 = xc;     y1 = yc + r; break;
-	  case 3: x1 = xc - r; y1 = yc;     break;
-	  }
-	  addArc(x0, y0, x1, y1,
-		 xc, yc, r, quad, flatness,
-		 quad == quad0 && (path->flags[i-1] & splashPathFirst),
-		 gFalse,
-		 quad == quad0 && !closeSubpaths &&
-		   (path->flags[i-1] & splashPathFirst) &&
-		   !(path->flags[i-1] & splashPathClosed),
-		 gFalse);
-	  x0 = x1;
-	  y0 = y1;
-	  quad = (quad + 1) & 3;
-	}
-	addArc(x0, y0, path->pts[i+1].x, path->pts[i+1].y,
-	       xc, yc, r, quad, flatness,
-	       quad == quad0 && (path->flags[i-1] & splashPathFirst),
-	       (path->flags[i+1] & splashPathLast),
-	       quad == quad0 && !closeSubpaths &&
-	         (path->flags[i-1] & splashPathFirst) &&
-	         !(path->flags[i-1] & splashPathClosed),
-	       !closeSubpaths &&
-	         (path->flags[i+1] & splashPathLast) &&
-	         !(path->flags[i+1] & splashPathClosed));
-	i += 2;
-
       // line segment
       } else {
-	addSegment(path->pts[i-1].x, path->pts[i-1].y,
-		   path->pts[i].x, path->pts[i].y,
+	x1 = pts[i].x;
+	y1 = pts[i].y;
+	addSegment(x0, y0, x1, y1,
 		   path->flags[i-1] & splashPathFirst,
 		   path->flags[i] & splashPathLast,
 		   !closeSubpaths &&
@@ -150,20 +192,49 @@
 		   !closeSubpaths &&
 		     (path->flags[i] & splashPathLast) &&
 		     !(path->flags[i] & splashPathClosed));
+	x0 = x1;
+	y0 = y1;
 	++i;
       }
 
       // close a subpath
       if (closeSubpaths &&
 	  (path->flags[i-1] & splashPathLast) &&
-	  (path->pts[i-1].x != path->pts[curSubpath].x ||
-	   path->pts[i-1].y != path->pts[curSubpath]. y)) {
-	addSegment(path->pts[i-1].x, path->pts[i-1].y,
-		   path->pts[curSubpath].x, path->pts[curSubpath].y,
+	  (pts[i-1].x != pts[curSubpath].x ||
+	   pts[i-1].y != pts[curSubpath].y)) {
+	addSegment(x0, y0, xsp, ysp,
 		   gFalse, gTrue, gFalse, gFalse);
       }
     }
   }
+
+  gfree(pts);
+}
+
+// Apply the stroke adjust hints to point <pt>: (*<xp>, *<yp>).
+void SplashXPath::strokeAdjust(SplashXPathAdjust *adjust,
+			       SplashCoord *xp, SplashCoord *yp) {
+  SplashCoord x, y;
+
+  if (adjust->vert) {
+    x = *xp;
+    if (x > adjust->x0a && x < adjust->x0b) {
+      *xp = adjust->x0;
+    } else if (x > adjust->xma && x < adjust->xmb) {
+      *xp = adjust->xm;
+    } else if (x > adjust->x1a && x < adjust->x1b) {
+      *xp = adjust->x1;
+    }
+  } else {
+    y = *yp;
+    if (y > adjust->x0a && y < adjust->x0b) {
+      *yp = adjust->x0;
+    } else if (y > adjust->xma && y < adjust->xmb) {
+      *yp = adjust->xm;
+    } else if (y > adjust->x1a && y < adjust->x1b) {
+      *yp = adjust->x1;
+    }
+  }
 }
 
 SplashXPath::SplashXPath(SplashXPath *xPath) {
@@ -196,9 +267,9 @@
 			   SplashCoord x3, SplashCoord y3,
 			   SplashCoord flatness,
 			   GBool first, GBool last, GBool end0, GBool end1) {
-  SplashCoord cx[maxCurveSplits + 1][3];
-  SplashCoord cy[maxCurveSplits + 1][3];
-  int cNext[maxCurveSplits + 1];
+  SplashCoord cx[splashMaxCurveSplits + 1][3];
+  SplashCoord cy[splashMaxCurveSplits + 1][3];
+  int cNext[splashMaxCurveSplits + 1];
   SplashCoord xl0, xl1, xl2, xr0, xr1, xr2, xr3, xx1, xx2, xh;
   SplashCoord yl0, yl1, yl2, yr0, yr1, yr2, yr3, yy1, yy2, yh;
   SplashCoord dx, dy, mx, my, d1, d2, flatness2;
@@ -208,14 +279,14 @@
 
   // initial segment
   p1 = 0;
-  p2 = maxCurveSplits;
+  p2 = splashMaxCurveSplits;
   cx[p1][0] = x0;  cy[p1][0] = y0;
   cx[p1][1] = x1;  cy[p1][1] = y1;
   cx[p1][2] = x2;  cy[p1][2] = y2;
   cx[p2][0] = x3;  cy[p2][0] = y3;
   cNext[p1] = p2;
 
-  while (p1 < maxCurveSplits) {
+  while (p1 < splashMaxCurveSplits) {
 
     // get the next segment
     xl0 = cx[p1][0];  yl0 = cy[p1][0];
@@ -242,9 +313,9 @@
     if (p2 - p1 == 1 || (d1 <= flatness2 && d2 <= flatness2)) {
       addSegment(xl0, yl0, xr3, yr3,
 		 p1 == 0 && first,
-		 p2 == maxCurveSplits && last,
+		 p2 == splashMaxCurveSplits && last,
 		 p1 == 0 && end0,
-		 p2 == maxCurveSplits && end1);
+		 p2 == splashMaxCurveSplits && end1);
       p1 = p2;
 
     // otherwise, subdivide the curve
@@ -274,73 +345,6 @@
   }
 }
 
-void SplashXPath::addArc(SplashCoord x0, SplashCoord y0,
-			 SplashCoord x1, SplashCoord y1,
-			 SplashCoord xc, SplashCoord yc,
-			 SplashCoord r, int quad,
-			 SplashCoord flatness,
-			 GBool first, GBool last, GBool end0, GBool end1) {
-  SplashCoord px[maxCurveSplits + 1];
-  SplashCoord py[maxCurveSplits + 1];
-  int pNext[maxCurveSplits + 1];
-  SplashCoord r2, flatness2;
-  SplashCoord xx0, yy0, xx1, yy1, xm, ym, t, dx, dy;
-  int p1, p2, p3;
-
-  r2 = r * r;
-  flatness2 = flatness * flatness;
-
-  // initial segment
-  p1 = 0;
-  p2 = maxCurveSplits;
-  px[p1] = x0;  py[p1] = y0;
-  px[p2] = x1;  py[p2] = y1;
-  pNext[p1] = p2;
-
-  while (p1 < maxCurveSplits) {
-
-    // get the next segment
-    xx0 = px[p1];  yy0 = py[p1];
-    p2 = pNext[p1];
-    xx1 = px[p2];  yy1 = py[p2];
-
-    // compute the arc midpoint
-    t = (xx0 - xc) * (xx1 - xc) - (yy0 - yc) * (yy1 - yc);
-    xm = splashSqrt((SplashCoord)0.5 * (r2 + t));
-    ym = splashSqrt((SplashCoord)0.5 * (r2 - t));
-    switch (quad) {
-    case 0: xm = xc - xm;  ym = yc - ym;  break;
-    case 1: xm = xc + xm;  ym = yc - ym;  break;
-    case 2: xm = xc + xm;  ym = yc + ym;  break;
-    case 3: xm = xc - xm;  ym = yc + ym;  break;
-    }
-
-    // compute distance from midpoint of straight segment to midpoint
-    // of arc
-    dx = (SplashCoord)0.5 * (xx0 + xx1) - xm;
-    dy = (SplashCoord)0.5 * (yy0 + yy1) - ym;
-
-    // if the arc is flat enough, or no more subdivisions are allowed,
-    // add the straight line segment
-    if (p2 - p1 == 1 || dx * dx + dy * dy <= flatness2) {
-      addSegment(xx0, yy0, xx1, yy1,
-		 p1 == 0 && first,
-		 p2 == maxCurveSplits && last,
-		 p1 == 0 && end0,
-		 p2 == maxCurveSplits && end1);
-      p1 = p2;
-
-    // otherwise, subdivide the arc
-    } else {
-      p3 = (p1 + p2) / 2;
-      px[p3] = xm;
-      py[p3] = ym;
-      pNext[p1] = p3;
-      pNext[p3] = p2;
-    }
-  }
-}
-
 void SplashXPath::addSegment(SplashCoord x0, SplashCoord y0,
 			     SplashCoord x1, SplashCoord y1,
 			     GBool first, GBool last, GBool end0, GBool end1) {
@@ -372,8 +376,21 @@
     segs[length].dxdy = segs[length].dydx = 0;
     segs[length].flags |= splashXPathVert;
   } else {
+#if USE_FIXEDPOINT
+    if (FixedPoint::divCheck(x1 - x0, y1 - y0, &segs[length].dxdy)) {
+      segs[length].dydx = (SplashCoord)1 / segs[length].dxdy;
+    } else {
+      segs[length].dxdy = segs[length].dydx = 0;
+      if (splashAbs(x1 - x0) > splashAbs(y1 - y0)) {
+	segs[length].flags |= splashXPathHoriz;
+      } else {
+	segs[length].flags |= splashXPathVert;
+      }
+    }
+#else
     segs[length].dxdy = (x1 - x0) / (y1 - y0);
     segs[length].dydx = (SplashCoord)1 / segs[length].dxdy;
+#endif
   }
   if (y0 > y1) {
     segs[length].flags |= splashXPathFlip;
@@ -409,6 +426,18 @@
   return 0;
 }
 
+void SplashXPath::aaScale() {
+  SplashXPathSeg *seg;
+  int i;
+
+  for (i = 0, seg = segs; i < length; ++i, ++seg) {
+    seg->x0 *= splashAASize;
+    seg->y0 *= splashAASize;
+    seg->x1 *= splashAASize;
+    seg->y1 *= splashAASize;
+  }
+}
+
 void SplashXPath::sort() {
   qsort(segs, length, sizeof(SplashXPathSeg), &cmpXPathSegs);
 }

Index: SplashXPath.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashXPath.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- SplashXPath.h	3 Mar 2005 19:45:59 -0000	1.1.1.1
+++ SplashXPath.h	25 Apr 2007 19:59:10 -0000	1.2
@@ -14,6 +14,11 @@
 #include "SplashTypes.h"
 
 class SplashPath;
+struct SplashXPathAdjust;
+
+//------------------------------------------------------------------------
+
+#define splashMaxCurveSplits (1 << 10)
 
 //------------------------------------------------------------------------
 // SplashXPathSeg
@@ -45,16 +50,21 @@
 public:
 
   // Expands (converts to segments) and flattens (converts curves to
-  // lines) <path>.  If <closeSubpaths> is true, closes all open
+  // lines) <path>.  Transforms all points from user space to device
+  // space, via <matrix>.  If <closeSubpaths> is true, closes all open
   // subpaths.
-  SplashXPath(SplashPath *path, SplashCoord flatness,
-	      GBool closeSubpaths);
+  SplashXPath(SplashPath *path, SplashCoord *matrix,
+	      SplashCoord flatness, GBool closeSubpaths);
 
   // Copy an expanded path.
   SplashXPath *copy() { return new SplashXPath(this); }
 
   ~SplashXPath();
 
+  // Multiply all coordinates by splashAASize, in preparation for
+  // anti-aliased rendering.
+  void aaScale();
+
   // Sort by upper coordinate (lower y), in y-major order.
   void sort();
 
@@ -62,6 +72,10 @@
 
   SplashXPath();
   SplashXPath(SplashXPath *xPath);
+  void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi,
+		 SplashCoord *xo, SplashCoord *yo);
+  void strokeAdjust(SplashXPathAdjust *adjust,
+		    SplashCoord *xp, SplashCoord *yp);
   void grow(int nSegs);
   void addCurve(SplashCoord x0, SplashCoord y0,
 		SplashCoord x1, SplashCoord y1,
@@ -69,12 +83,6 @@
 		SplashCoord x3, SplashCoord y3,
 		SplashCoord flatness,
 		GBool first, GBool last, GBool end0, GBool end1);
-  void addArc(SplashCoord x0, SplashCoord y0,
-	      SplashCoord x1, SplashCoord y1,
-	      SplashCoord xc, SplashCoord yc,
-	      SplashCoord r, int quad,
-	      SplashCoord flatness,
-	      GBool first, GBool last, GBool end0, GBool end1);
   void addSegment(SplashCoord x0, SplashCoord y0,
 		  SplashCoord x1, SplashCoord y1,
 		  GBool first, GBool last, GBool end0, GBool end1);

Index: SplashXPathScanner.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashXPathScanner.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- SplashXPathScanner.cc	2 Feb 2006 23:06:20 -0000	1.4
+++ SplashXPathScanner.cc	25 Apr 2007 19:59:10 -0000	1.5
@@ -11,9 +11,11 @@
 #endif
 
 #include <stdlib.h>
+#include <string.h>
 #include "goo/gmem.h"
 #include "SplashMath.h"
 #include "SplashXPath.h"
+#include "SplashBitmap.h"
 #include "SplashXPathScanner.h"
 
 //------------------------------------------------------------------------
@@ -97,6 +99,14 @@
   gfree(inter);
 }
 
+void SplashXPathScanner::getBBoxAA(int *xMinA, int *yMinA,
+				   int *xMaxA, int *yMaxA) {
+  *xMinA = xMin / splashAASize;
+  *yMinA = yMin / splashAASize;
+  *xMaxA = xMax / splashAASize;
+  *yMaxA = yMax / splashAASize;
+}
+
 void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) {
   if (interY != y) {
     computeIntersections(y);
@@ -283,3 +293,136 @@
   interIdx = 0;
   interCount = 0;
 }
+
+void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
+				      int *x0, int *x1, int y) {
+  int xx0, xx1, xx, xxMin, xxMax, yy;
+  Guchar mask;
+  SplashColorPtr p;
+
+  memset(aaBuf->getDataPtr(), 0, aaBuf->getRowSize() * aaBuf->getHeight());
+  xxMin = aaBuf->getWidth();
+  xxMax = -1;
+  for (yy = 0; yy < splashAASize; ++yy) {
+    computeIntersections(splashAASize * y + yy);
+    while (interIdx < interLen) {
+      xx0 = inter[interIdx].x0;
+      xx1 = inter[interIdx].x1;
+      interCount += inter[interIdx].count;
+      ++interIdx;
+      while (interIdx < interLen &&
+	     (inter[interIdx].x0 <= xx1 ||
+	      (eo ? (interCount & 1) : (interCount != 0)))) {
+	if (inter[interIdx].x1 > xx1) {
+	  xx1 = inter[interIdx].x1;
+	}
+	interCount += inter[interIdx].count;
+	++interIdx;
+      }
+      if (xx0 < 0) {
+	xx0 = 0;
+      }
+      ++xx1;
+      if (xx1 > aaBuf->getWidth()) {
+	xx1 = aaBuf->getWidth();
+      }
+      // set [xx0, xx1) to 1
+      if (xx0 < xx1) {
+	xx = xx0;
+	p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
+	if (xx & 7) {
+	  mask = 0xff >> (xx & 7);
+	  if ((xx & ~7) == (xx1 & ~7)) {
+	    mask &= (Guchar)(0xff00 >> (xx1 & 7));
+	  }
+	  *p++ |= mask;
+	  xx = (xx & ~7) + 8;
+	}
+	for (; xx + 7 < xx1; xx += 8) {
+	  *p++ |= 0xff;
+	}
+	if (xx < xx1) {
+	  *p |= (Guchar)(0xff00 >> (xx1 & 7));
+	}
+      }
+      if (xx0 < xxMin) {
+	xxMin = xx0;
+      }
+      if (xx1 > xxMax) {
+	xxMax = xx1;
+      }
+    }
+  }
+  *x0 = xxMin / splashAASize;
+  *x1 = (xxMax - 1) / splashAASize;
+}
+
+void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf,
+				    int *x0, int *x1, int y) {
+  int xx0, xx1, xx, yy;
+  Guchar mask;
+  SplashColorPtr p;
+
+  for (yy = 0; yy < splashAASize; ++yy) {
+    xx = *x0 * splashAASize;
+    computeIntersections(splashAASize * y + yy);
+    while (interIdx < interLen && xx < (*x1 + 1) * splashAASize) {
+      xx0 = inter[interIdx].x0;
+      xx1 = inter[interIdx].x1;
+      interCount += inter[interIdx].count;
+      ++interIdx;
+      while (interIdx < interLen &&
+	     (inter[interIdx].x0 <= xx1 ||
+	      (eo ? (interCount & 1) : (interCount != 0)))) {
+	if (inter[interIdx].x1 > xx1) {
+	  xx1 = inter[interIdx].x1;
+	}
+	interCount += inter[interIdx].count;
+	++interIdx;
+      }
+      if (xx0 > aaBuf->getWidth()) {
+	xx0 = aaBuf->getWidth();
+      }
+      // set [xx, xx0) to 0
+      if (xx < xx0) {
+	p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
+	if (xx & 7) {
+	  mask = (Guchar)(0xff00 >> (xx & 7));
+	  if ((xx & ~7) == (xx0 & ~7)) {
+	    mask |= 0xff >> (xx0 & 7);
+	  }
+	  *p++ &= mask;
+	  xx = (xx & ~7) + 8;
+	}
+	for (; xx + 7 <= xx0; xx += 8) {
+	  *p++ = 0x00;
+	}
+	if (xx <= xx0) {
+	  *p &= 0xff >> (xx0 & 7);
+	}
+      }
+      if (xx1 >= xx) {
+	xx = xx1 + 1;
+      }
+    }
+    xx0 = (*x1 + 1) * splashAASize;
+    // set [xx, xx0) to 0
+    if (xx < xx0) {
+      p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
+      if (xx & 7) {
+	mask = (Guchar)(0xff00 >> (xx & 7));
+	if ((xx & ~7) == (xx0 & ~7)) {
+	  mask &= 0xff >> (xx0 & 7);
+	}
+	*p++ &= mask;
+	xx = (xx & ~7) + 8;
+      }
+      for (; xx + 7 <= xx0; xx += 8) {
+	*p++ = 0x00;
+      }
+      if (xx <= xx0) {
+	*p &= 0xff >> (xx0 & 7);
+      }
+    }
+  }
+}

Index: SplashXPathScanner.h
===================================================================
RCS file: /cvs/poppler/poppler/splash/SplashXPathScanner.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- SplashXPathScanner.h	3 Mar 2005 19:45:59 -0000	1.1.1.1
+++ SplashXPathScanner.h	25 Apr 2007 19:59:10 -0000	1.2
@@ -14,6 +14,7 @@
 #include "SplashTypes.h"
 
 class SplashXPath;
+class SplashBitmap;
 struct SplashIntersect;
 
 //------------------------------------------------------------------------
@@ -32,6 +33,9 @@
   void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA)
     { *xMinA = xMin; *yMinA = yMin; *xMaxA = xMax; *yMaxA = yMax; }
 
+  // Return the path's bounding box.
+  void getBBoxAA(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA);
+
   // Return the min/max x values for the span at <y>.
   void getSpanBounds(int y, int *spanXMin, int *spanXMax);
 
@@ -49,6 +53,15 @@
   // no more spans at <y>.
   GBool getNextSpan(int y, int *x0, int *x1);
 
+  // Renders one anti-aliased line into <aaBuf>.  Returns the min and
+  // max x coordinates with non-zero pixels in <x0> and <x1>.
+  void renderAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y);
+
+  // Clips an anti-aliased line by setting pixels to zero.  On entry,
+  // all non-zero pixels are between <x0> and <x1>.  This function
+  // will update <x0> and <x1>.
+  void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y);
+
 private:
 
   void computeIntersections(int y);



More information about the poppler mailing list