Esempio n. 1
0
void MyCanvas::shadeRect(const GRect& rect, GShader* shader)
{
  assert(shader != nullptr);
  if (rect.isEmpty())
  {
    printf("Error: ShadeRect rectangle is empty\n");
    return;
  }

  /* Convert the rectangle into points, then CTM the resulting points */
  auto Points = Utility::RectToPoints(rect);  
  CTMPoints(Points);  
 
  if ( !CTM.preservesRect())  //If the CTM does not preserve a rectangle, draw a polygon
  {
    auto Edges = pointsToEdges(Points);
    shadeDevicePolygon(Edges, shader);
    return;
  }
  
  //Convert the CTM'd points back into a rect since we know it preserves it
  GIRect ConvertedRect = Utility::PointsToRect(Points).round();

  // Make sure rect is not an empty one and clip the edges from the bitmap with intersect
  if (ConvertedRect.isEmpty() || !ConvertedRect.intersect(BmpRect)) { return; }

  shadeDeviceRect(ConvertedRect, shader);
}
Esempio n. 2
0
  void drawRect(const GRect &rect, const GPaint &p) {
    const GBitmap &ctxbm = GetInternalBitmap();
    GRect ctxRect = GRect::MakeXYWH(0, 0, ctxbm.width(), ctxbm.height());
    GRect pixelRect = GetTransformedBoundingBox(rect);

    if(pixelRect.isEmpty()) {
      return;
    }

    GRect trRect;
    if(!(trRect.setIntersection(ctxRect, pixelRect))) {
      return;
    }

    // Rein everything back into integer land
    GIRect dstRect = trRect.round();
    if(dstRect.isEmpty()) {
      return;
    }

    if(!(CheckSkew(m_CTM))) {
      fillIRect(dstRect, p.getColor(), eBlendOp_SrcOver);
      return;
    }

    GPixel clearValue = ColorToPixel(p.getColor());

    // If the alpha value is above this value, then it will round to
    // an opaque pixel during quantization.
    const float kOpaqueAlpha = (254.5f / 255.0f);
    float alpha = p.getAlpha();

    // Blend func is currently just srcover
    BlendFunc blend = blend_srcover;

    for(uint32_t j = 0; j < dstRect.height(); j++) {
      for(uint32_t i = 0; i < dstRect.width(); i++) {

        GVec3f ctxPt(static_cast<float>(dstRect.fLeft + i) + 0.5f,
                     static_cast<float>(dstRect.fTop + j) + 0.5f,
                     1.0f);

        ctxPt = m_CTMInv * ctxPt;

        if(ContainsPoint(rect, ctxPt[0], ctxPt[1])) {
          uint32_t x = static_cast<uint32_t>(ctxPt[0] - rect.fLeft);
          uint32_t y = static_cast<uint32_t>(ctxPt[1] - rect.fTop);

          GPixel *dstRow = GetRow(ctxbm, j+dstRect.fTop) + dstRect.fLeft;
          dstRow[i] = blend(dstRow[i], clearValue);
        }
      }
    }
  }
Esempio n. 3
0
    virtual void fillRect(const GRect& rect, const GColor& color) {
        GPixel c = color.premulToPixel();
        if (0 == GPixel_GetA(c)) {
            return;
        }

        GIRect ir = fIBounds;
        if (ir.intersect(rect.round())) {
            srcover_rect(fDevice, ir, c);
        }
    }
Esempio n. 4
0
static void srcover_rect(const GBitmap& bitmap, const GIRect& rect, const GPixel& color) {
    unsigned a = GPixel_GetA(color);
    if (0 == a) {
        return;
    }

    RowProc proc = (255 == a) ? src_row : srcover_row;
    const int width = rect.width();

    for (int y = rect.top(); y < rect.bottom(); ++y) {
        proc(get_addr(bitmap, rect.x(), y), width, color);
    }
}
Esempio n. 5
0
void MyCanvas::shadeDeviceRect(const GIRect& rect, GShader* shader)
{  
  assert(shader != nullptr);
  if (rect.isEmpty())
  {
    printf("Error: ShadeDeviceRect rect is empty can't draw\n");
    return;
  }

  // Get dst bitmap address and offset to the rect top
  GPixel* DstPixels = (GPixel*)((char*)Bitmap.pixels() + Bitmap.fRowBytes * rect.top());
  
  // Set the context of the shader to the CTM
  float TwoRows[6];
  CTM.GetTwoRows(TwoRows);
  shader->setContext(TwoRows);

  //All rows will have the same number of pixels so we can allocate once for the whole rect
  int count = rect.width();
  GPixel* row = new GPixel[count];
  for (int y = rect.top(); y < rect.bottom(); ++y)
  {
    shader->shadeRow(rect.left(), y, count, row);
    blendRow(DstPixels, rect.left(), row, count);
    DstPixels = (GPixel*)((char*)DstPixels + Bitmap.fRowBytes);
  }

  delete[] row;
}
Esempio n. 6
0
  // This code draws a bitmap using the full m_CTM transform without any thought
  // to whether or not the transform has any special properties.
  void drawBitmapXForm(const GBitmap &bm, const GPaint &paint) {
    const GBitmap &ctxbm = GetInternalBitmap();
    GRect ctxRect = GRect::MakeXYWH(0, 0, ctxbm.width(), ctxbm.height());
    GIRect bmRect = GIRect::MakeXYWH(0, 0, bm.width(), bm.height());
    GRect pixelRect = GetTransformedBoundingBox(bmRect);

    GRect rect;
    if(!(rect.setIntersection(ctxRect, pixelRect))) {
      return;
    }

    // Rein everything back into integer land
    GIRect dstRect = rect.round();
    if(dstRect.isEmpty()) {
      return;
    }

    float alpha = paint.getAlpha();
    if(alpha >= kOpaqueAlpha) {
      for(uint32_t j = 0; j < dstRect.height(); j++) {
        for(uint32_t i = 0; i < dstRect.width(); i++) {
          drawXFormPixel(i, j, dstRect, bmRect, bm, ctxbm);
        }
      }
    } else {
      const uint32_t alphaVal = static_cast<uint32_t>((alpha * 255.0f) + 0.5f);
      for(uint32_t j = 0; j < dstRect.height(); j++) {
        for(uint32_t i = 0; i < dstRect.width(); i++) {
          drawXFormPixelWithAlpha(i, j, dstRect, bmRect, bm, ctxbm, alphaVal);
        }
      }
    }
  }
Esempio n. 7
0
static void src_rect(const GBitmap& bitmap, const GIRect& rect, const GPixel& color) {
    const int width = rect.width();
    for (int y = rect.top(); y < rect.bottom(); ++y) {
        src_row(get_addr(bitmap, rect.x(), y), width, color);
    }
}
Esempio n. 8
0
  void fillIRect(const GIRect &rect, const GColor &c, EBlendOp op) {

    const GBitmap &bitmap = GetInternalBitmap();

    uint32_t h = bitmap.fHeight;
    uint32_t w = bitmap.fWidth;

    GIRect bmRect;
    if(!(bmRect.setIntersection(rect, GIRect::MakeWH(w, h))))
      return;

    h = bmRect.height();
    w = bmRect.width();

    // premultiply alpha ...
    GPixel clearValue = ColorToPixel(c);

    // Figure out blendfunc
    BlendFunc blend = GetBlendFunc(op);

    if(bitmap.fRowBytes == w * sizeof(GPixel)) {
      GPixel *p = bitmap.fPixels + bmRect.fTop*bitmap.fWidth + bmRect.fLeft;
      switch(op) {
        case eBlendOp_Src:
          memsetPixel(p, clearValue, w*h);
          break;

        default: {
          GPixel *end = bitmap.fPixels + ((bmRect.fBottom - 1) * w + bmRect.fRight);
          for(; p != end; p++) {
            *p = blend(*p, clearValue);
          }
          break;
        }
      }

    } else {
      
      for(uint32_t j = bmRect.fTop; j < bmRect.fBottom; j++) {
        GPixel *rowPixels = GetRow(bitmap, j) + bmRect.fLeft;

        switch(op) {
          case eBlendOp_Src: {
            memsetPixel(rowPixels, clearValue, w);
            break;
          }

          default: {
            GPixel oldP = rowPixels[0];
            GPixel newP = blend(oldP, clearValue);
            rowPixels[0] = newP;
            
            for(uint32_t i = 1; i < w; i++) {
              if(oldP == rowPixels[i]) {
                rowPixels[i] = newP;
              } else {
                oldP = rowPixels[i];
                newP = rowPixels[i] = blend(rowPixels[i], clearValue);
              }
            }
            break;
          }
        }  // switch
      }  // for
    }  // else
  }
Esempio n. 9
0
  // This code draws a bitmap assuming that we only have translation and scale,
  // which allows us to perform certain optimizations...
  void drawBitmapSimple(const GBitmap &bm, const GPaint &paint) {
    const GBitmap &ctxbm = GetInternalBitmap();
    GRect ctxRect = GRect::MakeXYWH(0, 0, ctxbm.width(), ctxbm.height());
    GRect bmRect = GRect::MakeXYWH(0, 0, bm.width(), bm.height());
    GRect pixelRect = GetTransformedBoundingBox(bmRect);

    GRect rect;
    if(!(rect.setIntersection(ctxRect, pixelRect))) {
      return;
    }

    // We know that since we're only doing scale and translation, that all of the pixel
    // centers contained in rect are going to be drawn, so we only need to know the
    // dimensions of the mapping...
    GVec3f origin(0, 0, 1);
    GVec3f offset(1, 1, 1);

    origin = m_CTM * origin;
    offset = m_CTM * offset;

    float xScale = 1.0f / (offset.X() - origin.X());
    float yScale = 1.0f / (offset.Y() - origin.Y());

    GVec2f start = GVec2f(0, 0);
    if(xScale < 0.0f) {
      start.X() = pixelRect.fRight - 1.0f;
    }
    if(yScale < 0.0f) {
      start.Y() = pixelRect.fBottom - 1.0f;
    }

    GIRect dstRect = rect.round();

    // Construct new bitmap
    int32_t offsetX = ::std::max(0, -dstRect.fLeft);
    int32_t offsetY = ::std::max(0, -dstRect.fTop);
    GBitmap fbm;
    fbm.fWidth = bm.width();
    fbm.fHeight = bm.height();
    fbm.fPixels = GetRow(bm, offsetY) + offsetX;
    fbm.fRowBytes = bm.fRowBytes;

    BlendFunc blend = blend_srcover;

    float alpha = paint.getAlpha();
    if(alpha >= kOpaqueAlpha) {
      for(uint32_t j = 0; j < dstRect.height(); j++) {

        uint32_t srcIdxY = static_cast<uint32_t>(start.Y() + static_cast<float>(j) * yScale);
        GPixel *srcPixels = GetRow(fbm, Clamp<int>(srcIdxY, 0, fbm.height()));
        GPixel *dstPixels = GetRow(ctxbm, dstRect.fTop + j) + dstRect.fLeft;

        for(uint32_t i = 0; i < dstRect.width(); i++) {
          uint32_t srcIdxX = static_cast<uint32_t>(start.X() + static_cast<float>(i) * xScale);
          dstPixels[i] = blend(dstPixels[i], srcPixels[Clamp<int>(srcIdxX, 0, fbm.width())]);
        }
      }
    } else {
      const uint32_t alphaVal = static_cast<uint32_t>((alpha * 255.0f) + 0.5f);
      for(uint32_t j = 0; j < dstRect.height(); j++) {

        uint32_t srcIdxY = static_cast<uint32_t>(start.Y() + static_cast<float>(j) * yScale);
        GPixel *srcPixels = GetRow(fbm, srcIdxY);
        GPixel *dstPixels = GetRow(ctxbm, dstRect.fTop + j) + dstRect.fLeft;

        for(uint32_t i = 0; i < dstRect.width(); i++) {
          uint32_t srcIdxX = static_cast<uint32_t>(start.X() + static_cast<float>(i) * xScale);
          uint32_t srcA = fixed_multiply(GPixel_GetA(srcPixels[srcIdxX]), alphaVal);
          uint32_t srcR = fixed_multiply(GPixel_GetR(srcPixels[srcIdxX]), alphaVal);
          uint32_t srcG = fixed_multiply(GPixel_GetG(srcPixels[srcIdxX]), alphaVal);
          uint32_t srcB = fixed_multiply(GPixel_GetB(srcPixels[srcIdxX]), alphaVal);
          GPixel src = GPixel_PackARGB(srcA, srcR, srcG, srcB);
          dstPixels[i] = blend(dstPixels[i], src);
        }
      }
    }
  }