[poppler] poppler/splash: Splash.cc, 1.10, 1.10.2.1 Splash.h, 1.3, 1.3.4.1 SplashBitmap.cc, 1.4, 1.4.4.1 SplashBitmap.h, 1.2, 1.2.4.1 SplashClip.cc, 1.2, 1.2.4.1 SplashClip.h, 1.2, 1.2.4.1 SplashFTFont.cc, 1.7, 1.7.4.1 SplashFTFont.h, 1.1.1.1, 1.1.1.1.6.1 SplashFTFontEngine.cc, 1.4, 1.4.4.1 SplashFTFontEngine.h, 1.3, 1.3.4.1 SplashFTFontFile.cc, 1.3, 1.3.4.1 SplashFTFontFile.h, 1.2, 1.2.4.1 SplashFont.cc, 1.3, 1.3.4.1 SplashFont.h, 1.2, 1.2.4.1 SplashFontEngine.cc, 1.4, 1.4.4.1 SplashFontEngine.h, 1.2, 1.2.4.1 SplashFontFile.cc, 1.3, 1.3.4.1 SplashFontFile.h, 1.2, 1.2.4.1 SplashMath.h, 1.2, 1.2.4.1 SplashPath.cc, 1.3, 1.3.4.1 SplashPath.h, 1.3, 1.3.4.1 SplashPattern.cc, 1.2, 1.2.4.1 SplashPattern.h, 1.2, 1.2.4.1 SplashScreen.cc, 1.3, 1.3.4.1 SplashScreen.h, 1.2, 1.2.4.1 SplashState.cc, 1.3, 1.3.4.1 SplashState.h, 1.2, 1.2.4.1 SplashT1Font.cc, 1.2, 1.2.4.1 SplashT1Font.h, 1.2, 1.2.4.1 SplashT1FontEngine.cc, 1.2, 1.2.4.1 SplashT1FontFile.cc, 1.3, 1.3.4.1 SplashT1FontFile.h, 1.2, 1.2.4.1 SplashTypes.h, 1.5, 1.5.4.1 SplashXPath.cc, 1.3, 1.3.4.1 SplashXPath.h, 1.1.1.1, 1.1.1.1.6.1 SplashXPathScanner.cc, 1.4, 1.4.4.1 SplashXPathScanner.h, 1.1.1.1, 1.1.1.1.6.1

Albert Astals Cid aacid at kemper.freedesktop.org
Fri Apr 6 07:22:26 PDT 2007


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

Modified Files:
      Tag: xpdf302merge
	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:
The big xpdf 3.02 merge, it's mostly working except
Annot has still to be merged, i'll leave that to jrebetez
DCTStream and FlateStream classes have not been tested
ArthurOutputDev had some code commented, but as it was nto working it's not crucial
UGooString got removed as i got clear it was not needed, yay!
HtmlOutputDev won't detect links as the base outputdev changed signature
Did not test CairoOutputDev but i have 0 knowledge of Cairo so i need someone here anyway
glib frontend has some nasty warnings probably due to changed signatures, have a look
And in all i'm quite happy of the merge as it renders "something" and my kpdf port all it had was crashes :D


Index: Splash.cc
===================================================================
RCS file: /cvs/poppler/poppler/splash/Splash.cc,v
retrieving revision 1.10
retrieving revision 1.10.2.1
diff -u -d -r1.10 -r1.10.2.1
--- Splash.cc	19 Nov 2006 12:59:48 -0000	1.10
+++ Splash.cc	6 Apr 2007 14:22:23 -0000	1.10.2.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- Splash.h	30 Oct 2005 20:29:05 -0000	1.3
+++ Splash.h	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.4.4.1
diff -u -d -r1.4 -r1.4.4.1
--- SplashBitmap.cc	23 May 2006 20:49:16 -0000	1.4
+++ SplashBitmap.cc	6 Apr 2007 14:22:23 -0000	1.4.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashBitmap.h	30 Oct 2005 20:29:05 -0000	1.2
+++ SplashBitmap.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashClip.cc	27 Aug 2005 08:43:43 -0000	1.2
+++ SplashClip.cc	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashClip.h	15 Sep 2005 21:51:16 -0000	1.2
+++ SplashClip.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.7.4.1
diff -u -d -r1.7 -r1.7.4.1
--- SplashFTFont.cc	4 Apr 2006 20:42:08 -0000	1.7
+++ SplashFTFont.cc	6 Apr 2007 14:22:23 -0000	1.7.4.1
@@ -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.1.1.1.6.1
diff -u -d -r1.1.1.1 -r1.1.1.1.6.1
--- SplashFTFont.h	3 Mar 2005 19:45:59 -0000	1.1.1.1
+++ SplashFTFont.h	6 Apr 2007 14:22:23 -0000	1.1.1.1.6.1
@@ -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.4.4.1
diff -u -d -r1.4 -r1.4.4.1
--- SplashFTFontEngine.cc	2 Feb 2006 22:50:01 -0000	1.4
+++ SplashFTFontEngine.cc	6 Apr 2007 14:22:23 -0000	1.4.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashFTFontEngine.h	2 Feb 2006 22:50:01 -0000	1.3
+++ SplashFTFontEngine.h	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashFTFontFile.cc	2 Feb 2006 22:50:01 -0000	1.3
+++ SplashFTFontFile.cc	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashFTFontFile.h	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashFTFontFile.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashFont.cc	15 Sep 2005 22:15:47 -0000	1.3
+++ SplashFont.cc	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashFont.h	15 Sep 2005 22:15:47 -0000	1.2
+++ SplashFont.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.4.4.1
diff -u -d -r1.4 -r1.4.4.1
--- SplashFontEngine.cc	30 Jul 2006 09:38:28 -0000	1.4
+++ SplashFontEngine.cc	6 Apr 2007 14:22:23 -0000	1.4.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashFontEngine.h	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashFontEngine.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashFontFile.cc	2 Feb 2006 22:50:01 -0000	1.3
+++ SplashFontFile.cc	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashFontFile.h	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashFontFile.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashMath.h	16 Sep 2005 18:21:38 -0000	1.2
+++ SplashMath.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashPath.cc	15 Sep 2005 22:20:37 -0000	1.3
+++ SplashPath.cc	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashPath.h	15 Sep 2005 22:20:37 -0000	1.3
+++ SplashPath.h	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashPattern.cc	30 Oct 2005 20:29:05 -0000	1.2
+++ SplashPattern.cc	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashPattern.h	30 Oct 2005 20:29:05 -0000	1.2
+++ SplashPattern.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashScreen.cc	16 Oct 2005 14:25:32 -0000	1.3
+++ SplashScreen.cc	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashScreen.h	16 Oct 2005 14:25:32 -0000	1.2
+++ SplashScreen.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashState.cc	30 Oct 2005 20:29:05 -0000	1.3
+++ SplashState.cc	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashState.h	30 Oct 2005 20:29:05 -0000	1.2
+++ SplashState.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashT1Font.cc	15 Sep 2005 22:24:55 -0000	1.2
+++ SplashT1Font.cc	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashT1Font.h	15 Sep 2005 22:24:57 -0000	1.2
+++ SplashT1Font.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashT1FontEngine.cc	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashT1FontEngine.cc	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashT1FontFile.cc	2 Feb 2006 22:50:01 -0000	1.3
+++ SplashT1FontFile.cc	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.2.4.1
diff -u -d -r1.2 -r1.2.4.1
--- SplashT1FontFile.h	2 Feb 2006 22:50:01 -0000	1.2
+++ SplashT1FontFile.h	6 Apr 2007 14:22:23 -0000	1.2.4.1
@@ -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.5.4.1
diff -u -d -r1.5 -r1.5.4.1
--- SplashTypes.h	23 May 2006 20:49:16 -0000	1.5
+++ SplashTypes.h	6 Apr 2007 14:22:23 -0000	1.5.4.1
@@ -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.3.4.1
diff -u -d -r1.3 -r1.3.4.1
--- SplashXPath.cc	16 Sep 2005 18:00:43 -0000	1.3
+++ SplashXPath.cc	6 Apr 2007 14:22:23 -0000	1.3.4.1
@@ -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.1.1.1.6.1
diff -u -d -r1.1.1.1 -r1.1.1.1.6.1
--- SplashXPath.h	3 Mar 2005 19:45:59 -0000	1.1.1.1
+++ SplashXPath.h	6 Apr 2007 14:22:23 -0000	1.1.1.1.6.1
@@ -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.4.4.1
diff -u -d -r1.4 -r1.4.4.1
--- SplashXPathScanner.cc	2 Feb 2006 23:06:20 -0000	1.4
+++ SplashXPathScanner.cc	6 Apr 2007 14:22:23 -0000	1.4.4.1
@@ -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.1.1.1.6.1
diff -u -d -r1.1.1.1 -r1.1.1.1.6.1
--- SplashXPathScanner.h	3 Mar 2005 19:45:59 -0000	1.1.1.1
+++ SplashXPathScanner.h	6 Apr 2007 14:22:23 -0000	1.1.1.1.6.1
@@ -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