[poppler] [PATCH] cairo: drawChar->drawString

Jeff Muizelaar jrmuizel at nit.ca
Fri Mar 4 10:59:43 PST 2005


2005-03-02  Jeff Muizelaar  <jrmuizel at nit.ca>

	* poppler/CairoOutputDev.cc (CairoOutputDev::drawString):
	Implement drawString instead of drawChar. This change should
	make clipping to a text path work and has a performance
	improvement. Currently the code is a little ugly because we
	can't concat matrices to cairo without losing our current font.

	* poppler/CairoOutputDev.h (CairoOutputDev::useDrawChar):
	Tell Gfx.cc that it should use drawString instead of drawChar.
							

diff -urp 01-cleanup/poppler/CairoOutputDev.cc 02-drawString/poppler/CairoOutputDev.cc
--- 01-cleanup/poppler/CairoOutputDev.cc	2005-03-02 12:22:08.000000000 -0500
+++ 02-drawString/poppler/CairoOutputDev.cc	2005-03-02 12:30:42.000000000 -0500
@@ -321,62 +321,112 @@ void CairoOutputDev::eoClip(GfxState *st
   LOG (printf ("clip-eo\n"));
 }
 
-void CairoOutputDev::drawChar(GfxState *state, double x, double y,
-			       double dx, double dy,
-			       double originX, double originY,
-			       CharCode code, Unicode *u, int uLen) {
-  cairo_glyph_t glyph;
-  double x1, y1;
+void CairoOutputDev::drawString(GfxState *state, GooString *s)
+{
+  GfxFont *font;
+  int wMode;
   int render;
-
-  LOG (printf ("drawChar %d '%c'\n", code, code));
+  // the number of bytes in the string and not the number of glyphs?
+  int len = s->getLength();
+  // need at most len glyphs
+  cairo_glyph_t glyphs[len];
   
+  char *p = s->getCString();
+  int count = 0;
+  double curX, curY;
+  double riseX, riseY;
+
+  font = state->getFont();
+  wMode = font->getWMode();
+ 
   if (needFontUpdate) {
     updateFont(state);
   }
   if (!currentFont) {
     return;
   }
-  
+   
   // check for invisible text -- this is used by Acrobat Capture
   render = state->getRender();
   if (render == 3) {
     return;
   }
 
-  x -= originX;
-  y -= originY;
-  state->transform(x, y, &x1, &y1);
-
-  glyph.index = currentFont->getGlyph (code, u, uLen);
-  glyph.x = x1;
-  glyph.y = y1;
-
+  // ignore empty strings
+  if (len == 0)
+    return;
+  
+  state->textTransformDelta(0, state->getRise(), &riseX, &riseY);
+  curX = state->getCurX();
+  curY = state->getCurY();
+  while (len > 0) {
+    double x, y;
+    double x1, y1;
+    double dx, dy, tdx, tdy;
+    double originX, originY, tOriginX, tOriginY;
+    int n, uLen;
+    CharCode code;
+    Unicode u[8];
+    n = font->getNextChar(p, len, &code,
+	                  u, (int)(sizeof(u) / sizeof(Unicode)), &uLen,
+			  &dx, &dy, &originX, &originY);
+    if (wMode) {
+      dx *= state->getFontSize();
+      dy = dy * state->getFontSize() + state->getCharSpace();
+      if (n == 1 && *p == ' ') {
+	dy += state->getWordSpace();
+      }
+    } else {
+      dx = dx * state->getFontSize() + state->getCharSpace();
+      if (n == 1 && *p == ' ') {
+	dx += state->getWordSpace();
+      }
+      dx *= state->getHorizScaling();
+      dy *= state->getFontSize();
+    }
+    originX *= state->getFontSize();
+    originY *= state->getFontSize();
+    state->textTransformDelta(dx, dy, &tdx, &tdy);
+    state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
+    x = curX + riseX;
+    y = curY + riseY;
+    x -= tOriginX;
+    y -= tOriginY;
+    state->transform(x, y, &x1, &y1);
+
+    glyphs[count].index = currentFont->getGlyph (code, u, uLen);
+    glyphs[count].x = x1;
+    glyphs[count].y = y1;
+    curX += tdx;
+    curY += tdy;
+    p += n;
+    len -= n;
+    count++;
+  }
   // fill
   if (!(render & 1)) {
-    LOG (printf ("fill glyph\n"));
+    LOG (printf ("fill string\n"));
     cairo_set_rgb_color (cairo,
 			 fill_color.r, fill_color.g, fill_color.b);
-    cairo_show_glyphs (cairo, &glyph, 1);
+    cairo_show_glyphs (cairo, glyphs, count);
   }
-
+  
   // stroke
   if ((render & 3) == 1 || (render & 3) == 2) {
-    LOG (printf ("stroke glyph\n"));
+    LOG (printf ("stroke string\n"));
     cairo_set_rgb_color (cairo,
 			 stroke_color.r, stroke_color.g, stroke_color.b);
-    cairo_glyph_path (cairo, &glyph, 1);
+    cairo_glyph_path (cairo, glyphs, count);
     cairo_stroke (cairo);
   }
-  
 
   // clip
   if (render & 4) {
-    printf ("TODO: clip to glyph\n");
-    /* TODO: This reqires us to concatenat all clip paths
-       until endTextObject */
+    LOG (printf ("clip string\n"));
+    cairo_glyph_path (cairo, glyphs, count);
+    cairo_clip (cairo);
   }
-
+  
 }
 
 GBool CairoOutputDev::beginType3Char(GfxState *state, double x, double y,
diff -urp 01-cleanup/poppler/CairoOutputDev.h 02-drawString/poppler/CairoOutputDev.h
--- 01-cleanup/poppler/CairoOutputDev.h	2005-03-02 12:27:40.000000000 -0500
+++ 02-drawString/poppler/CairoOutputDev.h	2005-03-02 12:30:32.000000000 -0500
@@ -48,7 +48,7 @@ public:
   virtual GBool upsideDown() { return gTrue; }
 
   // Does this device use drawChar() or drawString()?
-  virtual GBool useDrawChar() { return gTrue; }
+  virtual GBool useDrawChar() { return gFalse; }
 
   // Does this device use beginType3Char/endType3Char?  Otherwise,
   // text in Type 3 fonts will be drawn with drawChar/drawString.
@@ -95,10 +95,7 @@ public:
   virtual void eoClip(GfxState *state);
 
   //----- text drawing
-  virtual void drawChar(GfxState *state, double x, double y,
-			double dx, double dy,
-			double originX, double originY,
-			CharCode code, Unicode *u, int uLen);
+  virtual void drawString(GfxState *state, GooString *s);
   virtual GBool beginType3Char(GfxState *state, double x, double y,
 			       double dx, double dy,
 			       CharCode code, Unicode *u, int uLen);


More information about the poppler mailing list