⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 splash.cc

📁 将pdf文档转换为高质量的html文档
💻 CC
📖 第 1 页 / 共 5 页
字号:
      }    // segment with |dy| > |dx|    } else {      dxdy = seg->dxdy;      if (y0 > y1) {	t = x0; x0 = x1; x1 = t;	t = y0; y0 = y1; y1 = t;      }      if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,					   x0 <= x1 ? x1 : x0, y1))	  != splashClipAllOutside) {	drawPixel(x0, y0, state->strokePattern, state->strokeAlpha,		  clipRes == splashClipAllInside);	for (y = y0 + 1; y <= y1 - 1; ++y) {	  x = splashFloor(seg->x0 + ((SplashCoord)y - seg->y0) * dxdy);	  drawPixel(x, y, state->strokePattern, state->strokeAlpha,		    clipRes == splashClipAllInside);	}	drawPixel(x1, y1, state->strokePattern, state->strokeAlpha,		  clipRes == splashClipAllInside);      }    }    ++nClipRes[clipRes];  }  if (nClipRes[splashClipPartial] ||      (nClipRes[splashClipAllInside] && nClipRes[splashClipAllOutside])) {    opClipRes = splashClipPartial;  } else if (nClipRes[splashClipAllInside]) {    opClipRes = splashClipAllInside;  } else {    opClipRes = splashClipAllOutside;  }}void Splash::strokeWide(SplashXPath *xPath) {  SplashXPathSeg *seg, *seg2;  SplashPath *widePath;  SplashCoord d, dx, dy, wdx, wdy, dxPrev, dyPrev, wdxPrev, wdyPrev;  SplashCoord dotprod, miter;  int i, j;  dx = dy = wdx = wdy = 0; // make gcc happy  dxPrev = dyPrev = wdxPrev = wdyPrev = 0; // make gcc happy  for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) {    // save the deltas for the previous segment; if this is the first    // segment on a subpath, compute the deltas for the last segment    // on the subpath (which may be used to draw a line join)    if (seg->flags & splashXPathFirst) {      for (j = i + 1, seg2 = &xPath->segs[j]; j < xPath->length; ++j, ++seg2) {	if (seg2->flags & splashXPathLast) {	  d = splashDist(seg2->x0, seg2->y0, seg2->x1, seg2->y1);	  if (d == 0) {	    //~ not clear what the behavior should be for joins with d==0	    dxPrev = 0;	    dyPrev = 1;	  } else {	    d = (SplashCoord)1 / d;	    dxPrev = d * (seg2->x1 - seg2->x0);	    dyPrev = d * (seg2->y1 - seg2->y0);	  }	  wdxPrev = (SplashCoord)0.5 * state->lineWidth * dxPrev;	  wdyPrev = (SplashCoord)0.5 * state->lineWidth * dyPrev;	  break;	}      }    } else {      dxPrev = dx;      dyPrev = dy;      wdxPrev = wdx;      wdyPrev = wdy;    }    // compute deltas for this line segment    d = splashDist(seg->x0, seg->y0, seg->x1, seg->y1);    if (d == 0) {      // we need to draw end caps on zero-length lines      //~ not clear what the behavior should be for splashLineCapButt with d==0      dx = 0;      dy = 1;    } else {      d = (SplashCoord)1 / d;      dx = d * (seg->x1 - seg->x0);      dy = d * (seg->y1 - seg->y0);    }    wdx = (SplashCoord)0.5 * state->lineWidth * dx;    wdy = (SplashCoord)0.5 * state->lineWidth * dy;    // initialize the path (which will be filled)    widePath = new SplashPath();    widePath->moveTo(seg->x0 - wdy, seg->y0 + wdx);    // draw the start cap    if (seg->flags & splashXPathEnd0) {      switch (state->lineCap) {      case splashLineCapButt:	widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);	break;      case splashLineCapRound:	widePath->arcCWTo(seg->x0 + wdy, seg->y0 - wdx, seg->x0, seg->y0);	break;      case splashLineCapProjecting:	widePath->lineTo(seg->x0 - wdx - wdy, seg->y0 + wdx - wdy);	widePath->lineTo(seg->x0 - wdx + wdy, seg->y0 - wdx - wdy);	widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);	break;      }    } else {      widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);    }    // draw the left side of the segment    widePath->lineTo(seg->x1 + wdy, seg->y1 - wdx);    // draw the end cap    if (seg->flags & splashXPathEnd1) {      switch (state->lineCap) {      case splashLineCapButt:	widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx);	break;      case splashLineCapRound:	widePath->arcCWTo(seg->x1 - wdy, seg->y1 + wdx, seg->x1, seg->y1);	break;      case splashLineCapProjecting:	widePath->lineTo(seg->x1 + wdx + wdy, seg->y1 - wdx + wdy);	widePath->lineTo(seg->x1 + wdx - wdy, seg->y1 + wdx + wdy);	widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx);	break;      }    } else {      widePath->lineTo(seg->x1 - wdy, seg->y1 + wdx);    }    // draw the right side of the segment    widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx);    // fill the segment    fillWithPattern(widePath, gTrue, state->strokePattern, state->strokeAlpha);    delete widePath;    // draw the line join    if (!(seg->flags & splashXPathEnd0)) {      widePath = NULL;      switch (state->lineJoin) {      case splashLineJoinMiter:	dotprod = -(dx * dxPrev + dy * dyPrev);	if (splashAbs(splashAbs(dotprod) - 1) > 0.01) {	  widePath = new SplashPath();	  widePath->moveTo(seg->x0, seg->y0);	  miter = (SplashCoord)2 / ((SplashCoord)1 - dotprod);	  if (splashSqrt(miter) <= state->miterLimit) {	    miter = splashSqrt(miter - 1);	    if (dy * dxPrev > dx * dyPrev) {	      widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev);	      widePath->lineTo(seg->x0 + wdy - miter * wdx,			       seg->y0 - wdx - miter * wdy);	      widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);	    } else {	      widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev);	      widePath->lineTo(seg->x0 - wdy - miter * wdx,			       seg->y0 + wdx - miter * wdy);	      widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx);	    }	  } else {	    if (dy * dxPrev > dx * dyPrev) {	      widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev);	      widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);	    } else {	      widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev);	      widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx);	    }	  }	}	break;      case splashLineJoinRound:	widePath = new SplashPath();	widePath->moveTo(seg->x0 + wdy, seg->y0 - wdx);	widePath->arcCWTo(seg->x0 + wdy, seg->y0 - wdx, seg->x0, seg->y0);	break;      case splashLineJoinBevel:	widePath = new SplashPath();	widePath->moveTo(seg->x0, seg->y0);	if (dy * dxPrev > dx * dyPrev) {	  widePath->lineTo(seg->x0 + wdyPrev, seg->y0 - wdxPrev);	  widePath->lineTo(seg->x0 + wdy, seg->y0 - wdx);	} else {	  widePath->lineTo(seg->x0 - wdyPrev, seg->y0 + wdxPrev);	  widePath->lineTo(seg->x0 - wdy, seg->y0 + wdx);	}	break;      }      if (widePath) {	fillWithPattern(widePath, gTrue, state->strokePattern,			state->strokeAlpha);	delete widePath;      }    }  }}SplashXPath *Splash::makeDashedPath(SplashXPath *xPath) {  SplashXPath *dPath;  GBool lineDashStartOn, lineDashOn;  GBool atSegStart, atSegEnd, atDashStart, atDashEnd;  int lineDashStartIdx, lineDashIdx, subpathStart;  SplashCoord lineDashTotal, lineDashStartPhase, lineDashDist;  int segIdx;  SplashXPathSeg *seg;  SplashCoord sx0, sy0, sx1, sy1, ax0, ay0, ax1, ay1, dist;  int i;  dPath = new SplashXPath();  lineDashTotal = 0;  for (i = 0; i < state->lineDashLength; ++i) {    lineDashTotal += state->lineDash[i];  }  lineDashStartPhase = state->lineDashPhase;  i = splashFloor(lineDashStartPhase / lineDashTotal);  lineDashStartPhase -= (SplashCoord)i * lineDashTotal;  lineDashStartOn = gTrue;  lineDashStartIdx = 0;  while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {    lineDashStartOn = !lineDashStartOn;    lineDashStartPhase -= state->lineDash[lineDashStartIdx];    ++lineDashStartIdx;  }  segIdx = 0;  seg = xPath->segs;  sx0 = seg->x0;  sy0 = seg->y0;  sx1 = seg->x1;  sy1 = seg->y1;  dist = splashDist(sx0, sy0, sx1, sy1);  lineDashOn = lineDashStartOn;  lineDashIdx = lineDashStartIdx;  lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase;  atSegStart = gTrue;  atDashStart = gTrue;  subpathStart = dPath->length;  while (segIdx < xPath->length) {    ax0 = sx0;    ay0 = sy0;    if (dist <= lineDashDist) {      ax1 = sx1;      ay1 = sy1;      lineDashDist -= dist;      dist = 0;      atSegEnd = gTrue;      atDashEnd = lineDashDist == 0 || (seg->flags & splashXPathLast);    } else {      ax1 = sx0 + (lineDashDist / dist) * (sx1 - sx0);      ay1 = sy0 + (lineDashDist / dist) * (sy1 - sy0);      sx0 = ax1;      sy0 = ay1;      dist -= lineDashDist;      lineDashDist = 0;      atSegEnd = gFalse;      atDashEnd = gTrue;    }    if (lineDashOn) {      dPath->addSegment(ax0, ay0, ax1, ay1,			atDashStart, atDashEnd,			atDashStart, atDashEnd);      // end of closed subpath      if (atSegEnd &&	  (seg->flags & splashXPathLast) &&	  !(seg->flags & splashXPathEnd1)) {	dPath->segs[subpathStart].flags &= ~splashXPathEnd0;	dPath->segs[dPath->length - 1].flags &= ~splashXPathEnd1;      }    }    if (atDashEnd) {      lineDashOn = !lineDashOn;      if (++lineDashIdx == state->lineDashLength) {	lineDashIdx = 0;      }      lineDashDist = state->lineDash[lineDashIdx];      atDashStart = gTrue;    } else {      atDashStart = gFalse;    }    if (atSegEnd) {      if (++segIdx < xPath->length) {	++seg;	sx0 = seg->x0;	sy0 = seg->y0;	sx1 = seg->x1;	sy1 = seg->y1;	dist = splashDist(sx0, sy0, sx1, sy1);	if (seg->flags & splashXPathFirst) {	  lineDashOn = lineDashStartOn;	  lineDashIdx = lineDashStartIdx;	  lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase;	  atDashStart = gTrue;	  subpathStart = dPath->length;	}      }      atSegStart = gTrue;    } else {      atSegStart = gFalse;    }  }  return dPath;}SplashError Splash::fill(SplashPath *path, GBool eo) {  if (debugMode) {    printf("fill [eo:%d]:\n", eo);    dumpPath(path);  }  return fillWithPattern(path, eo, state->fillPattern, state->fillAlpha);}SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,				    SplashPattern *pattern,				    SplashCoord alpha) {  SplashXPath *xPath;  SplashXPathScanner *scanner;  int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;  SplashClipResult clipRes, clipRes2;  if (path->length == 0) {    return splashErrEmptyPath;  }  xPath = new SplashXPath(path, state->flatness, gTrue);  xPath->sort();  scanner = new SplashXPathScanner(xPath, eo);  // get the min and max x and y values  scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);  // check clipping  if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))      != splashClipAllOutside) {    // limit the y range    if (yMinI < state->clip->getYMin()) {      yMinI = state->clip->getYMin();    }    if (yMaxI > state->clip->getYMax()) {      yMaxI = state->clip->getYMax();    }    // draw the spans    for (y = yMinI; y <= yMaxI; ++y) {      while (scanner->getNextSpan(y, &x0, &x1)) {	if (clipRes == splashClipAllInside) {	  drawSpan(x0, x1, y, pattern, alpha, gTrue);	} else {	  // limit the x range	  if (x0 < state->clip->getXMin()) {	    x0 = state->clip->getXMin();	  }	  if (x1 > state->clip->getXMax()) {	    x1 = state->clip->getXMax();	  }	  clipRes2 = state->clip->testSpan(x0, x1, y);	  drawSpan(x0, x1, y, pattern, alpha, clipRes2 == splashClipAllInside);	}      }    }  }  opClipRes = clipRes;  delete scanner;  delete xPath;  return splashOk;}SplashError Splash::xorFill(SplashPath *path, GBool eo) {  SplashXPath *xPath;  SplashXPathScanner *scanner;  int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;  SplashClipResult clipRes, clipRes2;  if (path->length == 0) {    return splashErrEmptyPath;  }  xPath = new SplashXPath(path, state->flatness, gTrue);  xPath->sort();  scanner = new SplashXPathScanner(xPath, eo);  // get the min and max x and y values  scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);  // check clipping  if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))      != splashClipAllOutside) {    // limit the y range    if (yMinI < state->clip->getYMin()) {      yMinI = state->clip->getYMin();    }    if (yMaxI > state->clip->getYMax()) {      yMaxI = state->clip->getYMax();    }    // draw the spans    for (y = yMinI; y <= yMaxI; ++y) {      while (scanner->getNextSpan(y, &x0, &x1)) {	if (clipRes == splashClipAllInside) {	  xorSpan(x0, x1, y, state->fillPattern, gTrue);	} else {	  // limit the x range	  if (x0 < state->clip->getXMin()) {	    x0 = state->clip->getXMin();	  }	  if (x1 > state->clip->getXMax()) {	    x1 = state->clip->getXMax();	  }	  clipRes2 = state->clip->testSpan(x0, x1, y);	  xorSpan(x0, x1, y, state->fillPattern,		  clipRes2 == splashClipAllInside);	}      }    }  }  opClipRes = clipRes;  delete scanner;  delete xPath;  return splashOk;}void Splash::drawPixel(int x, int y, SplashColorPtr color,		       SplashCoord alpha, GBool noClip) {  SplashBlendFunc blendFunc;  SplashColorPtr p;  SplashColor dest, blend;  int alpha2, ialpha2;  Guchar t;  if (noClip || state->clip->test(x, y)) {    if (alpha != 1 || softMask || state->blendFunc) {      blendFunc = state->blendFunc ? state->blendFunc : &blendNormal;      if (softMask) {	alpha2 = (int)(alpha * softMask->data[y * softMask->rowSize + x]);      } else {	alpha2 = (int)(alpha * 255);      }      ialpha2 = 255 - alpha2;      switch (bitmap->mode) {      case splashModeMono1:	p = &bitmap->data[y * bitmap->rowSize + (x >> 3)];	dest[0] = (*p >> (7 - (x & 7))) & 1;	(*blendFunc)(color, dest, blend, bitmap->mode);	t = (alpha2 * blend[0] + ialpha2 * dest[0]) >> 8;	if (t) {	  *p |= 0x80 >> (x & 7);	} else {	  *p &= ~(0x80 >> (x & 7));	}	break;      case splashModeMono8:	p = &bitmap->data[y * bitmap->rowSize + x];	(*blendFunc)(color, p, blend, bitmap->mode);	// note: floor(x / 255) = x >> 8 (for 16-bit x)	p[0] = (alpha2 * blend[0] + ialpha2 * p[0]) >> 8;	break;      case splashModeAMono8:	p = &bitmap->data[y * bitmap->rowSize + 2 * x];	(*blendFunc)(color, p, blend, bitmap->mode);	p[0] = (alpha2 * blend[0] + ialpha2 * p[0]) >> 8;	p[1] = (alpha2 * blend[1] + ialpha2 * p[1]) >> 8;	break;      case splashModeRGB8:      case splashModeBGR8:	p = &bitmap->data[y * bitmap->rowSize + 3 * x];	(*blendFunc)(color, p, blend, bitmap->mode);	p[0] = (alpha2 * blend[0] + ialpha2 * p[0]) >> 8;	p[1] = (alpha2 * blend[1] + ialpha2 * p[1]) >> 8;	p[2] = (alpha2 * blend[2] + ialpha2 * p[2]) >> 8;	break;      case splashModeARGB8:      case splashModeBGRA8:#if SPLASH_CMYK      case splashModeCMYK8:#endif	p = &bitmap->data[y * bitmap->rowSize + 4 * x];	(*blendFunc)(color, p, blend, bitmap->mode);	p[0] = (alpha2 * blend[0] + ialpha2 * p[0]) >> 8;	p[1] = (alpha2 * blend[1] + ialpha2 * p[1]) >> 8;	p[2] = (alpha2 * blend[2] + ialpha2 * p[2]) >> 8;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -