Annotation of embedaddon/php/ext/gd/libgd/gd_rotate.c, revision 1.1.1.1

1.1       misho       1: #if HAVE_GD_BUNDLED
                      2: # include "gd.h"
                      3: #else
                      4: # include <gd.h>
                      5: #endif
                      6: 
                      7: #include "gd_intern.h"
                      8: #include <math.h>
                      9: 
                     10: /*
                     11:  * Rotate function Added on 2003/12
                     12:  * by Pierre-Alain Joye (pierre@php.net)
                     13:  **/
                     14: /* Begin rotate function */
                     15: #ifdef ROTATE_PI
                     16: #undef ROTATE_PI
                     17: #endif /* ROTATE_PI */
                     18: 
                     19: #define ROTATE_DEG2RAD  3.1415926535897932384626433832795/180
                     20: void gdImageSkewX (gdImagePtr dst, gdImagePtr src, int uRow, int iOffset, double dWeight, int clrBack, int ignoretransparent)
                     21: {
                     22:        typedef int (*FuncPtr)(gdImagePtr, int, int);
                     23:        int i, r, g, b, a, clrBackR, clrBackG, clrBackB, clrBackA;
                     24:        FuncPtr f;
                     25: 
                     26:        int pxlOldLeft, pxlLeft=0, pxlSrc;
                     27: 
                     28:        /* Keep clrBack as color index if required */
                     29:        if (src->trueColor) {
                     30:                pxlOldLeft = clrBack;
                     31:                f = gdImageGetTrueColorPixel;
                     32:        } else {
                     33:                pxlOldLeft = clrBack;
                     34:                clrBackR = gdImageRed(src, clrBack);
                     35:                clrBackG = gdImageGreen(src, clrBack);
                     36:                clrBackB = gdImageBlue(src, clrBack);
                     37:                clrBackA = gdImageAlpha(src, clrBack);
                     38:                clrBack =  gdTrueColorAlpha(clrBackR, clrBackG, clrBackB, clrBackA);
                     39:                f = gdImageGetPixel;
                     40:        }
                     41: 
                     42:        for (i = 0; i < iOffset; i++) {
                     43:                gdImageSetPixel (dst, i, uRow, clrBack);
                     44:        }
                     45: 
                     46:        if (i < dst->sx) {
                     47:                gdImageSetPixel (dst, i, uRow, clrBack);
                     48:        }
                     49: 
                     50:        for (i = 0; i < src->sx; i++) {
                     51:                pxlSrc = f (src,i,uRow);
                     52: 
                     53:                r = (int)(gdImageRed(src,pxlSrc) * dWeight);
                     54:                g = (int)(gdImageGreen(src,pxlSrc) * dWeight);
                     55:                b = (int)(gdImageBlue(src,pxlSrc) * dWeight);
                     56:                a = (int)(gdImageAlpha(src,pxlSrc) * dWeight);
                     57: 
                     58:                pxlLeft = gdImageColorAllocateAlpha(src, r, g, b, a);
                     59: 
                     60:                if (pxlLeft == -1) {
                     61:                        pxlLeft = gdImageColorClosestAlpha(src, r, g, b, a);
                     62:                }
                     63: 
                     64:                r = gdImageRed(src,pxlSrc) - (gdImageRed(src,pxlLeft) - gdImageRed(src,pxlOldLeft));
                     65:                g = gdImageGreen(src,pxlSrc) - (gdImageGreen(src,pxlLeft) - gdImageGreen(src,pxlOldLeft));
                     66:                b = gdImageBlue(src,pxlSrc) - (gdImageBlue(src,pxlLeft) - gdImageBlue(src,pxlOldLeft));
                     67:                a = gdImageAlpha(src,pxlSrc) - (gdImageAlpha(src,pxlLeft) - gdImageAlpha(src,pxlOldLeft));
                     68: 
                     69:         if (r>255) {
                     70:                r = 255;
                     71:         }
                     72: 
                     73:                if (g>255) {
                     74:                        g = 255;
                     75:                }
                     76: 
                     77:                if (b>255) {
                     78:                        b = 255;
                     79:                }
                     80: 
                     81:                if (a>127) {
                     82:                        a = 127;
                     83:                }
                     84: 
                     85:                if (ignoretransparent && pxlSrc == dst->transparent) {
                     86:                        pxlSrc = dst->transparent;
                     87:                } else {
                     88:                        pxlSrc = gdImageColorAllocateAlpha(dst, r, g, b, a);
                     89: 
                     90:                        if (pxlSrc == -1) {
                     91:                                pxlSrc = gdImageColorClosestAlpha(dst, r, g, b, a);
                     92:                        }
                     93:                }
                     94: 
                     95:                if ((i + iOffset >= 0) && (i + iOffset < dst->sx)) {
                     96:                        gdImageSetPixel (dst, i+iOffset, uRow,  pxlSrc);
                     97:                }
                     98: 
                     99:                pxlOldLeft = pxlLeft;
                    100:        }
                    101: 
                    102:        i += iOffset;
                    103: 
                    104:        if (i < dst->sx) {
                    105:                gdImageSetPixel (dst, i, uRow, pxlLeft);
                    106:        }
                    107: 
                    108:        gdImageSetPixel (dst, iOffset, uRow, clrBack);
                    109: 
                    110:        i--;
                    111: 
                    112:        while (++i < dst->sx) {
                    113:                gdImageSetPixel (dst, i, uRow, clrBack);
                    114:        }
                    115: }
                    116: 
                    117: void gdImageSkewY (gdImagePtr dst, gdImagePtr src, int uCol, int iOffset, double dWeight, int clrBack, int ignoretransparent)
                    118: {
                    119:        typedef int (*FuncPtr)(gdImagePtr, int, int);
                    120:        int i, iYPos=0, r, g, b, a;
                    121:        FuncPtr f;
                    122:        int pxlOldLeft, pxlLeft=0, pxlSrc;
                    123: 
                    124:        if (src->trueColor) {
                    125:                f = gdImageGetTrueColorPixel;
                    126:        } else {
                    127:                f = gdImageGetPixel;
                    128:        }
                    129: 
                    130:        for (i = 0; i<=iOffset; i++) {
                    131:                gdImageSetPixel (dst, uCol, i, clrBack);
                    132:        }
                    133:        r = (int)((double)gdImageRed(src,clrBack) * dWeight);
                    134:        g = (int)((double)gdImageGreen(src,clrBack) * dWeight);
                    135:        b = (int)((double)gdImageBlue(src,clrBack) * dWeight);
                    136:        a = (int)((double)gdImageAlpha(src,clrBack) * dWeight);
                    137: 
                    138:        pxlOldLeft = gdImageColorAllocateAlpha(dst, r, g, b, a);
                    139: 
                    140:        for (i = 0; i < src->sy; i++) {
                    141:                pxlSrc = f (src, uCol, i);
                    142:                iYPos = i + iOffset;
                    143: 
                    144:                r = (int)((double)gdImageRed(src,pxlSrc) * dWeight);
                    145:                g = (int)((double)gdImageGreen(src,pxlSrc) * dWeight);
                    146:                b = (int)((double)gdImageBlue(src,pxlSrc) * dWeight);
                    147:                a = (int)((double)gdImageAlpha(src,pxlSrc) * dWeight);
                    148: 
                    149:                pxlLeft = gdImageColorAllocateAlpha(src, r, g, b, a);
                    150: 
                    151:                if (pxlLeft == -1) {
                    152:                        pxlLeft = gdImageColorClosestAlpha(src, r, g, b, a);
                    153:                }
                    154: 
                    155:                r = gdImageRed(src,pxlSrc) - (gdImageRed(src,pxlLeft) - gdImageRed(src,pxlOldLeft));
                    156:                g = gdImageGreen(src,pxlSrc) - (gdImageGreen(src,pxlLeft) - gdImageGreen(src,pxlOldLeft));
                    157:                b = gdImageBlue(src,pxlSrc) - (gdImageBlue(src,pxlLeft) - gdImageBlue(src,pxlOldLeft));
                    158:                a = gdImageAlpha(src,pxlSrc) - (gdImageAlpha(src,pxlLeft) - gdImageAlpha(src,pxlOldLeft));
                    159: 
                    160:                if (r>255) {
                    161:                        r = 255;
                    162:                }
                    163: 
                    164:                if (g>255) {
                    165:                        g = 255;
                    166:                }
                    167: 
                    168:                if (b>255) {
                    169:                        b = 255;
                    170:                }
                    171: 
                    172:                if (a>127) {
                    173:                        a = 127;
                    174:                }
                    175: 
                    176:                if (ignoretransparent && pxlSrc == dst->transparent) {
                    177:                        pxlSrc = dst->transparent;
                    178:                } else {
                    179:                        pxlSrc = gdImageColorAllocateAlpha(dst, r, g, b, a);
                    180: 
                    181:                        if (pxlSrc == -1) {
                    182:                                pxlSrc = gdImageColorClosestAlpha(dst, r, g, b, a);
                    183:                        }
                    184:                }
                    185: 
                    186:                if ((iYPos >= 0) && (iYPos < dst->sy)) {
                    187:                        gdImageSetPixel (dst, uCol, iYPos, pxlSrc);
                    188:                }
                    189: 
                    190:                pxlOldLeft = pxlLeft;
                    191:        }
                    192: 
                    193:        i = iYPos;
                    194:        if (i < dst->sy) {
                    195:                gdImageSetPixel (dst, uCol, i, pxlLeft);
                    196:        }
                    197: 
                    198:        i--;
                    199:        while (++i < dst->sy) {
                    200:                gdImageSetPixel (dst, uCol, i, clrBack);
                    201:        }
                    202: }
                    203: 
                    204: /* Rotates an image by 90 degrees (counter clockwise) */
                    205: gdImagePtr gdImageRotate90 (gdImagePtr src, int ignoretransparent)
                    206: {
                    207:        int uY, uX;
                    208:        int c,r,g,b,a;
                    209:        gdImagePtr dst;
                    210:        typedef int (*FuncPtr)(gdImagePtr, int, int);
                    211:        FuncPtr f;
                    212: 
                    213:        if (src->trueColor) {
                    214:                f = gdImageGetTrueColorPixel;
                    215:        } else {
                    216:                f = gdImageGetPixel;
                    217:        }
                    218:        dst = gdImageCreateTrueColor(src->sy, src->sx);
                    219:        dst->transparent = src->transparent;
                    220: 
                    221:        if (dst != NULL) {
                    222:                int old_blendmode = dst->alphaBlendingFlag;
                    223:                dst->alphaBlendingFlag = 0;
                    224: 
                    225:                gdImagePaletteCopy (dst, src);
                    226: 
                    227:                for (uY = 0; uY<src->sy; uY++) {
                    228:                        for (uX = 0; uX<src->sx; uX++) {
                    229:                                c = f (src, uX, uY);
                    230:                                if (!src->trueColor) {
                    231:                                        r = gdImageRed(src,c);
                    232:                                        g = gdImageGreen(src,c);
                    233:                                        b = gdImageBlue(src,c);
                    234:                                        a = gdImageAlpha(src,c);
                    235:                                        c = gdTrueColorAlpha(r, g, b, a);
                    236:                                }
                    237:                                if (ignoretransparent && c == dst->transparent) {
                    238:                                        gdImageSetPixel(dst, uY, (dst->sy - uX - 1), dst->transparent);
                    239:                                } else {
                    240:                                        gdImageSetPixel(dst, uY, (dst->sy - uX - 1), c);
                    241:                                }
                    242:                        }
                    243:                }
                    244:                dst->alphaBlendingFlag = old_blendmode;
                    245:        }
                    246: 
                    247:        return dst;
                    248: }
                    249: 
                    250: /* Rotates an image by 180 degrees (counter clockwise) */
                    251: gdImagePtr gdImageRotate180 (gdImagePtr src, int ignoretransparent)
                    252: {
                    253:        int uY, uX;
                    254:        int c,r,g,b,a;
                    255:        gdImagePtr dst;
                    256:        typedef int (*FuncPtr)(gdImagePtr, int, int);
                    257:        FuncPtr f;
                    258: 
                    259:        if (src->trueColor) {
                    260:                f = gdImageGetTrueColorPixel;
                    261:        } else {
                    262:                f = gdImageGetPixel;
                    263:        }
                    264:        dst = gdImageCreateTrueColor(src->sx, src->sy);
                    265:        dst->transparent = src->transparent;
                    266: 
                    267:        if (dst != NULL) {
                    268:                int old_blendmode = dst->alphaBlendingFlag;
                    269:                dst->alphaBlendingFlag = 0;
                    270: 
                    271:                gdImagePaletteCopy (dst, src);
                    272: 
                    273:                for (uY = 0; uY<src->sy; uY++) {
                    274:                        for (uX = 0; uX<src->sx; uX++) {
                    275:                                c = f (src, uX, uY);
                    276:                                if (!src->trueColor) {
                    277:                                        r = gdImageRed(src,c);
                    278:                                        g = gdImageGreen(src,c);
                    279:                                        b = gdImageBlue(src,c);
                    280:                                        a = gdImageAlpha(src,c);
                    281:                                        c = gdTrueColorAlpha(r, g, b, a);
                    282:                                }
                    283: 
                    284:                                if (ignoretransparent && c == dst->transparent) {
                    285:                                        gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), dst->transparent);
                    286:                                } else {
                    287:                                        gdImageSetPixel(dst, (dst->sx - uX - 1), (dst->sy - uY - 1), c);
                    288:                                }
                    289:                        }
                    290:                }
                    291:                dst->alphaBlendingFlag = old_blendmode;
                    292:        }
                    293: 
                    294:        return dst;
                    295: }
                    296: 
                    297: /* Rotates an image by 270 degrees (counter clockwise) */
                    298: gdImagePtr gdImageRotate270 (gdImagePtr src, int ignoretransparent)
                    299: {
                    300:        int uY, uX;
                    301:        int c,r,g,b,a;
                    302:        gdImagePtr dst;
                    303:        typedef int (*FuncPtr)(gdImagePtr, int, int);
                    304:        FuncPtr f;
                    305: 
                    306:        if (src->trueColor) {
                    307:                f = gdImageGetTrueColorPixel;
                    308:        } else {
                    309:                f = gdImageGetPixel;
                    310:        }
                    311:        dst = gdImageCreateTrueColor (src->sy, src->sx);
                    312:        dst->transparent = src->transparent;
                    313: 
                    314:        if (dst != NULL) {
                    315:                int old_blendmode = dst->alphaBlendingFlag;
                    316:                dst->alphaBlendingFlag = 0;
                    317: 
                    318:                gdImagePaletteCopy (dst, src);
                    319: 
                    320:                for (uY = 0; uY<src->sy; uY++) {
                    321:                        for (uX = 0; uX<src->sx; uX++) {
                    322:                                c = f (src, uX, uY);
                    323:                                if (!src->trueColor) {
                    324:                                        r = gdImageRed(src,c);
                    325:                                        g = gdImageGreen(src,c);
                    326:                                        b = gdImageBlue(src,c);
                    327:                                        a = gdImageAlpha(src,c);
                    328:                                        c = gdTrueColorAlpha(r, g, b, a);
                    329:                                }
                    330: 
                    331:                                if (ignoretransparent && c == dst->transparent) {
                    332:                                        gdImageSetPixel(dst, (dst->sx - uY - 1), uX, dst->transparent);
                    333:                                } else {
                    334:                                        gdImageSetPixel(dst, (dst->sx - uY - 1), uX, c);
                    335:                                }
                    336:                        }
                    337:                }
                    338:                dst->alphaBlendingFlag = old_blendmode;
                    339:        }
                    340: 
                    341:        return dst;
                    342: }
                    343: 
                    344: gdImagePtr gdImageRotate45 (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent)
                    345: {
                    346:        typedef int (*FuncPtr)(gdImagePtr, int, int);
                    347:        gdImagePtr dst1,dst2,dst3;
                    348:        FuncPtr f;
                    349:        double dRadAngle, dSinE, dTan, dShear;
                    350:        double dOffset;     /* Variable skew offset */
                    351:        int u, iShear, newx, newy;
                    352:        int clrBackR, clrBackG, clrBackB, clrBackA;
                    353: 
                    354:        /* See GEMS I for the algorithm details */
                    355:        dRadAngle = dAngle * ROTATE_DEG2RAD; /* Angle in radians */
                    356:        dSinE = sin (dRadAngle);
                    357:        dTan = tan (dRadAngle / 2.0);
                    358: 
                    359:        newx = (int)(src->sx + src->sy * fabs(dTan));
                    360:        newy = src->sy;
                    361: 
                    362:        /* 1st shear */
                    363:        if (src->trueColor) {
                    364:                f = gdImageGetTrueColorPixel;
                    365:        } else {
                    366:                f = gdImageGetPixel;
                    367:        }
                    368: 
                    369:        dst1 = gdImageCreateTrueColor(newx, newy);
                    370:        /******* Perform 1st shear (horizontal) ******/
                    371:        if (dst1 == NULL) {
                    372:                return NULL;
                    373:        }
                    374: #ifdef HAVE_GD_BUNDLED
                    375:        dst1->alphaBlendingFlag = gdEffectReplace;
                    376: #else
                    377:        gdImageAlphaBlending(dst1, 0);
                    378: #endif
                    379:        if (dAngle == 0.0) {
                    380:                /* Returns copy of src */
                    381:                gdImageCopy (dst1, src,0,0,0,0,src->sx,src->sy);
                    382:                return dst1;
                    383:        }
                    384: 
                    385:        gdImagePaletteCopy (dst1, src);
                    386: 
                    387:        if (ignoretransparent) {
                    388:                if (gdImageTrueColor(src)) {
                    389:                        dst1->transparent = src->transparent;
                    390:                } else {
                    391: 
                    392:                        dst1->transparent = gdTrueColorAlpha(gdImageRed(src, src->transparent), gdImageBlue(src, src->transparent), gdImageGreen(src, src->transparent), 127);
                    393:                }
                    394:        }
                    395: 
                    396:        dRadAngle = dAngle * ROTATE_DEG2RAD; /* Angle in radians */
                    397:        dSinE = sin (dRadAngle);
                    398:        dTan = tan (dRadAngle / 2.0);
                    399: 
                    400:        for (u = 0; u < dst1->sy; u++) {
                    401:                if (dTan >= 0.0) {
                    402:                        dShear = ((double)(u + 0.5)) * dTan;
                    403:                } else {
                    404:                        dShear = ((double)(u - dst1->sy) + 0.5) * dTan;
                    405:                }
                    406: 
                    407:                iShear = (int)floor(dShear);
                    408:                gdImageSkewX(dst1, src, u, iShear, (dShear - iShear), clrBack, ignoretransparent);
                    409:        }
                    410: 
                    411:        /*
                    412:        The 1st shear may use the original clrBack as color index
                    413:        Convert it once here
                    414:        */
                    415:        if(!src->trueColor) {
                    416:                clrBackR = gdImageRed(src, clrBack);
                    417:                clrBackG = gdImageGreen(src, clrBack);
                    418:                clrBackB = gdImageBlue(src, clrBack);
                    419:                clrBackA = gdImageAlpha(src, clrBack);
                    420:                clrBack =  gdTrueColorAlpha(clrBackR, clrBackG, clrBackB, clrBackA);
                    421:        }
                    422:        /* 2nd shear */
                    423:        newx = dst1->sx;
                    424: 
                    425:        if (dSinE > 0.0) {
                    426:                dOffset = (src->sx-1) * dSinE;
                    427:        } else {
                    428:                dOffset = -dSinE *  (src->sx - newx);
                    429:        }
                    430: 
                    431:        newy = (int) ((double) src->sx * fabs( dSinE ) + (double) src->sy * cos (dRadAngle))+1;
                    432: 
                    433:        if (src->trueColor) {
                    434:                f = gdImageGetTrueColorPixel;
                    435:        } else {
                    436:                f = gdImageGetPixel;
                    437:        }
                    438:        dst2 = gdImageCreateTrueColor(newx, newy);
                    439:        if (dst2 == NULL) {
                    440:                gdImageDestroy(dst1);
                    441:                return NULL;
                    442:        }
                    443: 
                    444: #ifdef HAVE_GD_BUNDLED
                    445:        dst2->alphaBlendingFlag = gdEffectReplace;
                    446: #else
                    447:        gdImageAlphaBlending(dst2, 0);
                    448: #endif
                    449: 
                    450:        if (ignoretransparent) {
                    451:                dst2->transparent = dst1->transparent;
                    452:        }
                    453: 
                    454:        for (u = 0; u < dst2->sx; u++, dOffset -= dSinE) {
                    455:                iShear = (int)floor (dOffset);
                    456:                gdImageSkewY(dst2, dst1, u, iShear, (dOffset - (double)iShear), clrBack, ignoretransparent);
                    457:        }
                    458: 
                    459:        /* 3rd shear */
                    460:        gdImageDestroy(dst1);
                    461: 
                    462:        newx = (int) ((double)src->sy * fabs (dSinE) + (double)src->sx * cos (dRadAngle)) + 1;
                    463:        newy = dst2->sy;
                    464: 
                    465:        if (src->trueColor) {
                    466:                f = gdImageGetTrueColorPixel;
                    467:        } else {
                    468:                f = gdImageGetPixel;
                    469:        }
                    470:        dst3 = gdImageCreateTrueColor(newx, newy);
                    471:        if (dst3 == NULL) {
                    472:                gdImageDestroy(dst2);
                    473:                return NULL;
                    474:        }
                    475: 
                    476: #ifdef HAVE_GD_BUNDLED
                    477:        dst3->alphaBlendingFlag = gdEffectReplace;
                    478: #else
                    479:        gdImageAlphaBlending(dst3, 0);
                    480: #endif
                    481: 
                    482:        if (ignoretransparent) {
                    483:                dst3->transparent = dst2->transparent;
                    484:        }
                    485: 
                    486:        if (dSinE >= 0.0) {
                    487:                dOffset = (double)(src->sx - 1) * dSinE * -dTan;
                    488:        } else {
                    489:                dOffset = dTan * ((double)(src->sx - 1) * -dSinE + (double)(1 - newy));
                    490:        }
                    491: 
                    492:        for (u = 0; u < dst3->sy; u++, dOffset += dTan) {
                    493:                int iShear = (int)floor(dOffset);
                    494:                gdImageSkewX(dst3, dst2, u, iShear, (dOffset - iShear), clrBack, ignoretransparent);
                    495:        }
                    496: 
                    497:        gdImageDestroy(dst2);
                    498: 
                    499:        return dst3;
                    500: }
                    501: 
                    502: gdImagePtr gdImageRotate (gdImagePtr src, double dAngle, int clrBack, int ignoretransparent)
                    503: {
                    504:        gdImagePtr pMidImg;
                    505:        gdImagePtr rotatedImg;
                    506: 
                    507:        if (src == NULL) {
                    508:                return NULL;
                    509:        }
                    510: 
                    511:        if (!gdImageTrueColor(src) && (clrBack < 0 || clrBack>=gdImageColorsTotal(src))) {
                    512:                return NULL;
                    513:        }
                    514: 
                    515:        while (dAngle >= 360.0) {
                    516:                dAngle -= 360.0;
                    517:        }
                    518: 
                    519:        while (dAngle < 0) {
                    520:                dAngle += 360.0;
                    521:        }
                    522: 
                    523:        if (dAngle == 90.00) {
                    524:                return gdImageRotate90(src, ignoretransparent);
                    525:        }
                    526:        if (dAngle == 180.00) {
                    527:                return gdImageRotate180(src, ignoretransparent);
                    528:        }
                    529:        if(dAngle == 270.00) {
                    530:                return gdImageRotate270 (src, ignoretransparent);
                    531:        }
                    532: 
                    533:        if ((dAngle > 45.0) && (dAngle <= 135.0)) {
                    534:                pMidImg = gdImageRotate90 (src, ignoretransparent);
                    535:                dAngle -= 90.0;
                    536:        } else if ((dAngle > 135.0) && (dAngle <= 225.0)) {
                    537:                pMidImg = gdImageRotate180 (src, ignoretransparent);
                    538:                dAngle -= 180.0;
                    539:        } else if ((dAngle > 225.0) && (dAngle <= 315.0)) {
                    540:                pMidImg = gdImageRotate270 (src, ignoretransparent);
                    541:                dAngle -= 270.0;
                    542:        } else {
                    543:                return gdImageRotate45 (src, dAngle, clrBack, ignoretransparent);
                    544:        }
                    545: 
                    546:        if (pMidImg == NULL) {
                    547:                return NULL;
                    548:        }
                    549: 
                    550:        rotatedImg = gdImageRotate45 (pMidImg, dAngle, clrBack, ignoretransparent);
                    551:        gdImageDestroy(pMidImg);
                    552: 
                    553:        return rotatedImg;
                    554: }
                    555: /* End Rotate function */
                    556: 
                    557: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>