📄 splash.cc
字号:
// limit the y range if (yMinI < state->clip->getYMinI()) { yMinI = state->clip->getYMinI(); } if (yMaxI > state->clip->getYMaxI()) { yMaxI = state->clip->getYMaxI(); } pipeInit(&pipe, 0, yMinI, pattern, NULL, alpha, vectorAntialias, gFalse); // draw the spans if (vectorAntialias) { for (y = yMinI; y <= yMaxI; ++y) { scanner->renderAALine(aaBuf, &x0, &x1, y); if (clipRes != splashClipAllInside) { state->clip->clipAALine(aaBuf, &x0, &x1, y); } drawAALine(&pipe, x0, x1, y); } } else { for (y = yMinI; y <= yMaxI; ++y) { while (scanner->getNextSpan(y, &x0, &x1)) { if (clipRes == splashClipAllInside) { drawSpan(&pipe, x0, x1, y, gTrue); } else { // limit the x range if (x0 < state->clip->getXMinI()) { x0 = state->clip->getXMinI(); } if (x1 > state->clip->getXMaxI()) { x1 = state->clip->getXMaxI(); } clipRes2 = state->clip->testSpan(x0, x1, y); drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside); } } } } } opClipRes = clipRes; delete scanner; delete xPath; return splashOk;}SplashError Splash::xorFill(SplashPath *path, GBool eo) { SplashPipe pipe; SplashXPath *xPath; SplashXPathScanner *scanner; int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; SplashClipResult clipRes, clipRes2; SplashBlendFunc origBlendFunc; if (path->length == 0) { return splashErrEmptyPath; } xPath = new SplashXPath(path, state->matrix, 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->getYMinI()) { yMinI = state->clip->getYMinI(); } if (yMaxI > state->clip->getYMaxI()) { yMaxI = state->clip->getYMaxI(); } origBlendFunc = state->blendFunc; state->blendFunc = &blendXor; pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 1, gFalse, gFalse); // draw the spans for (y = yMinI; y <= yMaxI; ++y) { while (scanner->getNextSpan(y, &x0, &x1)) { if (clipRes == splashClipAllInside) { drawSpan(&pipe, x0, x1, y, gTrue); } else { // limit the x range if (x0 < state->clip->getXMinI()) { x0 = state->clip->getXMinI(); } if (x1 > state->clip->getXMaxI()) { x1 = state->clip->getXMaxI(); } clipRes2 = state->clip->testSpan(x0, x1, y); drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside); } } } state->blendFunc = origBlendFunc; } opClipRes = clipRes; delete scanner; delete xPath; return splashOk;}SplashError Splash::fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font) { SplashGlyphBitmap glyph; SplashCoord xt, yt; int x0, y0, xFrac, yFrac; SplashError err; if (debugMode) { printf("fillChar: x=%.2f y=%.2f c=%3d=0x%02x='%c'\n", (double)x, (double)y, c, c, c); } transform(state->matrix, x, y, &xt, &yt); x0 = splashFloor(xt); xFrac = splashFloor((xt - x0) * splashFontFraction); y0 = splashFloor(yt); yFrac = splashFloor((yt - y0) * splashFontFraction); if (!font->getGlyph(c, xFrac, yFrac, &glyph)) { return splashErrNoGlyph; } err = fillGlyph2(x0, y0, &glyph); if (glyph.freeData) { gfree(glyph.data); } return err;}SplashError Splash::fillGlyph(SplashCoord x, SplashCoord y, SplashGlyphBitmap *glyph) { SplashCoord xt, yt; int x0, y0; transform(state->matrix, x, y, &xt, &yt); x0 = splashFloor(xt); y0 = splashFloor(yt); return fillGlyph2(x0, y0, glyph);}SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) { SplashPipe pipe; SplashClipResult clipRes; GBool noClip; int alpha0, alpha; Guchar *p; int x1, y1, xx, xx1, yy; if ((clipRes = state->clip->testRect(x0 - glyph->x, y0 - glyph->y, x0 - glyph->x + glyph->w - 1, y0 - glyph->y + glyph->h - 1)) != splashClipAllOutside) { noClip = clipRes == splashClipAllInside; if (noClip) { if (glyph->aa) { pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse); p = glyph->data; for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { pipeSetXY(&pipe, x0 - glyph->x, y1); for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) { alpha = *p++; if (alpha != 0) { pipe.shape = (SplashCoord)(alpha / 255.0); pipeRun(&pipe); updateModX(x1); updateModY(y1); } else { pipeIncX(&pipe); } } } } else { pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse); p = glyph->data; for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { pipeSetXY(&pipe, x0 - glyph->x, y1); for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) { alpha0 = *p++; for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) { if (alpha0 & 0x80) { pipeRun(&pipe); updateModX(x1); updateModY(y1); } else { pipeIncX(&pipe); } alpha0 <<= 1; } } } } } else { if (glyph->aa) { pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse); p = glyph->data; for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { pipeSetXY(&pipe, x0 - glyph->x, y1); for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) { if (state->clip->test(x1, y1)) { alpha = *p++; if (alpha != 0) { pipe.shape = (SplashCoord)(alpha / 255.0); pipeRun(&pipe); updateModX(x1); updateModY(y1); } else { pipeIncX(&pipe); } } else { pipeIncX(&pipe); ++p; } } } } else { pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse); p = glyph->data; for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) { pipeSetXY(&pipe, x0 - glyph->x, y1); for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; xx += 8) { alpha0 = *p++; for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) { if (state->clip->test(x1, y1)) { if (alpha0 & 0x80) { pipeRun(&pipe); updateModX(x1); updateModY(y1); } else { pipeIncX(&pipe); } } else { pipeIncX(&pipe); } alpha0 <<= 1; } } } } } } opClipRes = clipRes; return splashOk;}SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData, int w, int h, SplashCoord *mat, GBool glyphMode) { SplashPipe pipe; GBool rot; SplashCoord xScale, yScale, xShear, yShear, yShear1; int tx, tx2, ty, ty2, scaledWidth, scaledHeight, xSign, ySign; int ulx, uly, llx, lly, urx, ury, lrx, lry; int ulx1, uly1, llx1, lly1, urx1, ury1, lrx1, lry1; int xMin, xMax, yMin, yMax; SplashClipResult clipRes, clipRes2; int yp, yq, yt, yStep, lastYStep; int xp, xq, xt, xStep, xSrc; int k1, spanXMin, spanXMax, spanY; SplashColorPtr pixBuf, p; int pixAcc; int x, y, x1, x2, y2; SplashCoord y1; int n, m, i, j; if (debugMode) { printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", w, h, (double)mat[0], (double)mat[1], (double)mat[2], (double)mat[3], (double)mat[4], (double)mat[5]); } // check for singular matrix if (splashAbs(mat[0] * mat[3] - mat[1] * mat[2]) < 0.000001) { return splashErrSingularMatrix; } // compute scale, shear, rotation, translation parameters rot = splashAbs(mat[1]) > splashAbs(mat[0]); if (rot) { xScale = -mat[1]; yScale = mat[2] - (mat[0] * mat[3]) / mat[1]; xShear = -mat[3] / yScale; yShear = -mat[0] / mat[1]; } else { xScale = mat[0]; yScale = mat[3] - (mat[1] * mat[2]) / mat[0]; xShear = mat[2] / yScale; yShear = mat[1] / mat[0]; } // Note 1: The PDF spec says that all pixels whose *centers* lie // within the region get painted -- but that doesn't seem to match // up with what Acrobat actually does: it ends up leaving gaps // between image stripes. So we use the same rule here as for // fills: any pixel that overlaps the region gets painted. // Note 2: The "glyphMode" flag is a kludge: it switches back to // "correct" behavior (matching the spec), for use in rendering Type // 3 fonts. // Note 3: The +/-0.01 in these computations is to avoid floating // point precision problems which can lead to gaps between image // stripes (it can cause image stripes to overlap, but that's a much // less visible problem). if (glyphMode) { if (xScale >= 0) { tx = splashRound(mat[4]); tx2 = splashRound(mat[4] + xScale) - 1; } else { tx = splashRound(mat[4]) - 1; tx2 = splashRound(mat[4] + xScale); } } else { if (xScale >= 0) { tx = splashFloor(mat[4] - 0.01); tx2 = splashFloor(mat[4] + xScale + 0.01); } else { tx = splashFloor(mat[4] + 0.01); tx2 = splashFloor(mat[4] + xScale - 0.01); } } scaledWidth = abs(tx2 - tx) + 1; if (glyphMode) { if (yScale >= 0) { ty = splashRound(mat[5]); ty2 = splashRound(mat[5] + yScale) - 1; } else { ty = splashRound(mat[5]) - 1; ty2 = splashRound(mat[5] + yScale); } } else { if (yScale >= 0) { ty = splashFloor(mat[5] - 0.01); ty2 = splashFloor(mat[5] + yScale + 0.01); } else { ty = splashFloor(mat[5] + 0.01); ty2 = splashFloor(mat[5] + yScale - 0.01); } } scaledHeight = abs(ty2 - ty) + 1; xSign = (xScale < 0) ? -1 : 1; ySign = (yScale < 0) ? -1 : 1; yShear1 = (SplashCoord)xSign * yShear; // clipping ulx1 = 0; uly1 = 0; urx1 = xSign * (scaledWidth - 1); ury1 = (int)(yShear * urx1); llx1 = splashRound(xShear * ySign * (scaledHeight - 1)); lly1 = ySign * (scaledHeight - 1) + (int)(yShear * llx1); lrx1 = xSign * (scaledWidth - 1) + splashRound(xShear * ySign * (scaledHeight - 1)); lry1 = ySign * (scaledHeight - 1) + (int)(yShear * lrx1); if (rot) { ulx = tx + uly1; uly = ty - ulx1; urx = tx + ury1; ury = ty - urx1; llx = tx + lly1; lly = ty - llx1; lrx = tx + lry1; lry = ty - lrx1; } else { ulx = tx + ulx1; uly = ty + uly1; urx = tx + urx1; ury = ty + ury1; llx = tx + llx1; lly = ty + lly1; lrx = tx + lrx1; lry = ty + lry1; } xMin = (ulx < urx) ? (ulx < llx) ? (ulx < lrx) ? ulx : lrx : (llx < lrx) ? llx : lrx : (urx < llx) ? (urx < lrx) ? urx : lrx : (llx < lrx) ? llx : lrx; xMax = (ulx > urx) ? (ulx > llx) ? (ulx > lrx) ? ulx : lrx : (llx > lrx) ? llx : lrx : (urx > llx) ? (urx > lrx) ? urx : lrx : (llx > lrx) ? llx : lrx; yMin = (uly < ury) ? (uly < lly) ? (uly < lry) ? uly : lry : (lly < lry) ? lly : lry : (ury < lly) ? (ury < lry) ? ury : lry : (lly < lry) ? lly : lry; yMax = (uly > ury) ? (uly > lly) ? (uly > lry) ? uly : lry : (lly > lry) ? lly : lry : (ury > lly) ? (ury > lry) ? ury : lry : (lly > lry) ? lly : lry; clipRes = state->clip->testRect(xMin, yMin, xMax, yMax); opClipRes = clipRes; // compute Bresenham parameters for x and y scaling yp = h / scaledHeight; yq = h % scaledHeight; xp = w / scaledWidth; xq = w % scaledWidth; // allocate pixel buffer pixBuf = (SplashColorPtr)gmalloc((yp + 1) * w); // initialize the pixel pipe pipeInit(&pipe, 0, 0, state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse); if (vectorAntialias) { drawAAPixelInit(); } // init y scale Bresenham yt = 0; lastYStep = 1; for (y = 0; y < scaledHeight; ++y) { // y scale Bresenham yStep = yp; yt += yq; if (yt >= scaledHeight) { yt -= scaledHeight; ++yStep; } // read row(s) from image n = (yp > 0) ? yStep : lastYStep; if (n > 0) { p = pixBuf; for (i = 0; i < n; ++i) { (*src)(srcData, p); p += w; } } lastYStep = yStep; // loop-invariant constants k1 = splashRound(xShear * ySign * y); // clipping test if (clipRes != splashClipAllInside && !rot && (int)(yShear * k1) == (int)(yShear * (xSign * (scaledWidth - 1) + k1))) { if (xSign > 0) { spanXMin = tx + k1; spanXMax = spanXMin + (scaledWidth - 1); } else { spanXMax = tx + k1; spanXMin = spanXMax - (scaledWidth - 1); } spanY = ty + ySign * y + (int)(yShear * k1); clipRes2 = state->clip->testSpan(spanXMin, spanXMax, spanY); if (clipRes2 == splashClipAllOutside) { continue; } } else { clipRes2 = clipRes; } // init x scale Bresenham xt = 0; xSrc = 0; // x shear x1 = k1; // y shear y1 = (SplashCoord)ySign * y + yShear * x1; // this is a kludge: if yShear1 is negative, then (int)y1 would // change immediately after the first pixel, which is not what we // want if (yShear1 < 0) { y1 += 0.999; } // loop-invariant constants n = yStep > 0 ? yStep : 1; for (x = 0; x < scaledWidth; ++x) { // x scale Bresenham xStep = xp; xt += xq; if (xt >= scaledWidth) { xt -= scaledWidth; ++xStep; } // rotation if (rot) { x2 = (int)y1; y2 = -x1; } else { x2 = x1; y2 = (int)y1; } // compute the alpha value for (x,y) after the x and y scaling // operations m = xStep > 0 ? xStep : 1; p = pixBuf + xSrc; pixAcc = 0; for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) { pixAcc += *p++; } p += w - m;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -