Home | History | Annotate | Download | only in utils
      1 /*
      2  *  CAUTION: EXPERIMENTAL CODE
      3  *
      4  *  This code is not to be used and will not be supported
      5  *  if it fails on you. DO NOT USE!
      6  *
      7  */
      8 
      9 #include "SkPathUtils.h"
     10 
     11 #include "SkPath.h"
     12 #include "SkPathOps.h" // this can't be found, how do I link it?
     13 #include "SkRegion.h"
     14 
     15 typedef void (*line2path)(SkPath*, const char*, int, int);
     16 #define SQRT_2 1.41421356237f
     17 #define ON  0xFF000000 // black pixel
     18 #define OFF 0x00000000 // transparent pixel
     19 
     20 // assumes stride is in bytes
     21 /*
     22 static void FillRandomBits( int chars, char* bits ){
     23     SkTime time;
     24     SkRandom rand = SkRandom( time.GetMSecs() );
     25 
     26     for (int i = 0; i < chars; ++i){
     27         bits[i] = rand.nextU();
     28     }
     29 }OA
     30 */
     31 
     32 static int GetBit( const char* buffer, int x ) {
     33     int byte = x >> 3;
     34     int bit = x & 7;
     35 
     36     return buffer[byte] & (128 >> bit);
     37 }
     38 
     39 /*
     40 static void Line2path_pixel(SkPath* path, const char* line,
     41                             int lineIdx, int width) {
     42     for (int i = 0; i < width; ++i) {
     43         // simply makes every ON pixel into a rect path
     44         if (GetBit(line,i)) {
     45             path->addRect(SkRect::MakeXYWH(i, lineIdx, 1, 1),
     46                           SkPath::kCW_Direction);
     47         }
     48     }
     49 }
     50 
     51 static void Line2path_pixelCircle(SkPath* path, const char* line,
     52                                   int lineIdx, int width) {
     53     for (int i = 0; i < width; ++i) {
     54         // simply makes every ON pixel into a circle path
     55         if (GetBit(line,i)) {
     56             path->addCircle(i + SK_ScalarHalf,
     57                             lineIdx + SK_ScalarHalf,
     58                             SQRT_2 / 2.0f);
     59         }
     60     }
     61 }
     62 */
     63 
     64 static void Line2path_span(SkPath* path, const char* line,
     65                            int lineIdx, int width) {
     66     bool inRun = 0;
     67     int start = 1;
     68 
     69     for (int i = 0; i < width; ++i) {
     70         int curPixel = GetBit(line,i);
     71 
     72         if ( (curPixel!=0) != inRun ) { // if transition
     73             if (curPixel) { // if transition on
     74                 inRun = 1;
     75                 start = i; // mark beginning of span
     76             }else { // if transition off add the span as a path
     77                 inRun = 0;
     78                 path->addRect(SkRect::MakeXYWH(SkIntToScalar(start), SkIntToScalar(lineIdx),
     79                                                SkIntToScalar(i-start), SK_Scalar1),
     80                               SkPath::kCW_Direction);
     81             }
     82         }
     83     }
     84 
     85     if (inRun==1) { // close any open spans
     86         int end = 0;
     87         if ( GetBit(line,width-1) ) ++end;
     88         path->addRect(SkRect::MakeXYWH(SkIntToScalar(start), SkIntToScalar(lineIdx),
     89                                        SkIntToScalar(width - 1 + end - start), SK_Scalar1),
     90                       SkPath::kCW_Direction);
     91     } else if ( GetBit(line, width - 1) ) { // if last pixel on add
     92         path->addRect(SkRect::MakeXYWH(width - SK_Scalar1, SkIntToScalar(lineIdx),
     93                                        SK_Scalar1, SK_Scalar1),
     94                       SkPath::kCW_Direction);
     95     }
     96 }
     97 
     98 void SkPathUtils::BitsToPath_Path(SkPath* path,
     99                         const char* bitmap,
    100                         int w, int h, int stride) {
    101     // loop for every line in bitmap
    102     for (int i = 0; i < h; ++i) {
    103         // fn ptr handles each line separately
    104         //l2p_fn(path, &bitmap[i*stride], i, w);
    105         Line2path_span(path, &bitmap[i*stride], i, w);
    106     }
    107     Simplify(*path, path); // simplify resulting path.
    108 }
    109 
    110 void SkPathUtils::BitsToPath_Region(SkPath* path,
    111                                const char* bitmap,
    112                                int w, int h, int stride) {
    113     SkRegion region;
    114 
    115     // loop for each line
    116     for (int y = 0; y < h; ++y){
    117         bool inRun = 0;
    118         int start = 1;
    119         const char* line = &bitmap[y * stride];
    120 
    121         // loop for each pixel
    122         for (int i = 0; i < w; ++i) {
    123             int curPixel = GetBit(line,i);
    124 
    125             if ( (curPixel!=0) != inRun ) { // if transition
    126                 if (curPixel) { // if transition on
    127                     inRun = 1;
    128                     start = i; // mark beginning of span
    129                 }else { // if transition off add the span as a path
    130                     inRun = 0;
    131                     //add here
    132                     region.op(SkIRect::MakeXYWH(start, y, i-start, 1),
    133                               SkRegion::kUnion_Op );
    134                 }
    135             }
    136         }
    137         if (inRun==1) { // close any open spans
    138             int end = 0;
    139             if ( GetBit(line,w-1) ) ++end;
    140             // add the thing here
    141             region.op(SkIRect::MakeXYWH(start, y, w-1-start+end, 1),
    142                       SkRegion::kUnion_Op );
    143 
    144         } else if ( GetBit(line,w-1) ) { // if last pixel on add rect
    145             // add the thing here
    146             region.op(SkIRect::MakeXYWH(w-1, y, 1, 1),
    147                       SkRegion::kUnion_Op );
    148         }
    149     }
    150     // convert region to path
    151     region.getBoundaryPath(path);
    152 }
    153