Beispiel #1
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);
        }
      }
    }
  }
Beispiel #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);
        }
      }
    }
  }
void GContext4::drawBitmap(const GBitmap& lclBmp, float x, float y, const GPaint& paint){
    
    float alpha = paint.getAlpha();
    alpha = (alpha>1)?1:((alpha<0)?0:alpha);//bound alpha by 0 and 1
    uint8_t intAlpha = alpha*255 + .5;
    if(intAlpha != 0){
        
        float gTop = y, gLeft = x, gBottom = y+lclBmp.fHeight, gRight = x+lclBmp.fWidth;
        mapMtx.vectorMult(&gLeft, &gTop);
        mapMtx.vectorMult(&gRight, &gBottom);
        ConversionMatrix invMtx;
        mapMtx.getInverse(invMtx);
        
        helper.findIntersection(&gLeft, &gRight, &gTop, &gBottom, Btmp.fHeight, Btmp.fWidth);
        if((gLeft != gRight) && (gTop != gBottom)){ //if intersection surface area is zero, do nothing

            float topPixValue = helper.roundToInt(gTop), bottomPixValue = helper.roundToInt(gBottom);
            float gLeftStartValue = helper.roundToInt(gLeft), gRightPixValue = helper.roundToInt(gRight);
            
            uint32_t DstColor;
            uint32_t lclColor;
            
            for (float j = topPixValue; j< bottomPixValue; j++) {
                float lclYVal = j + .5;
                size_t gRowsDown = j*Btmp.fRowBytes;
                for (float i = gLeftStartValue; i <gRightPixValue; i++) {
                    float lclXVal = i + .5;
                    
                    char* gAddress = (char*) Btmp.fPixels + gRowsDown + (int) i;
                    DstColor = *((GPixel*) gAddress);
                    
                    invMtx.vectorMult(&lclXVal, &lclYVal);
                    lclColor = *(GPixel*) (char*) lclBmp.fPixels + floorf(lclYVal)*lclBmp.fRowBytes + floorf(lclXVal);
                    
                    
                    if (lclColor != 0) { //if there is something to blend
                        if(intAlpha == 1){
                            *((GPixel*) gAddress) = helper.blendColor(DstColor, lclColor);
                        }
                        else if( DstColor == 0 ) { //if destination alpha == 0
                            
                            *((GPixel*) gAddress) = helper.packARGB(lclColor, intAlpha);
                        }
                        else{
                            *((GPixel*) gAddress) = helper.blendColorWithAlpha(DstColor, lclColor, intAlpha);
                        }
                    }
                }
            }
        }
    }
}
void GContext4::drawRect(const GRect& rect, const GPaint& bucket){
    if((int)(bucket.getAlpha()*255 + .5) > 0){ //only do something if the alpha is greater than zero
        const GColor& color = bucket.getColor();
        if(helper.isLegalColor(color)){
            if(!rect.isEmpty()){
                float rTop=rect.fTop,rBottom=rect.fBottom,rLeft=rect.fLeft,rRight=rect.fRight;
                mapping.vectorMult(&rLeft, &rTop);
                mapping.vectorMult(&rRight, &rBottom);
                if(rLeft>rRight){
                    rLeft += rRight;
                    rRight = rLeft - rRight;
                    rLeft = rLeft - rRight;
                }
                if (rTop > rBottom){
                    rTop += rBottom;
                    rBottom = rTop - rBottom;
                    rTop = rTop - rBottom;
                }
                int left = helper.roundToInt(rLeft);
                int right = helper.roundToInt(rRight);
                int top = helper.roundToInt(rTop);
                int bottom = helper.roundToInt(rBottom);
                helper.findIntersection(&left, &right, &top, &bottom, Btmp.fHeight, Btmp.fWidth);
                uint32_t storedResult = 0x01;
                uint32_t storedDestination = 0x01;
                uint32_t DstColor;
                uint32_t rectColor = helper.packARGB(color);
                char* row = ((char*) Btmp.fPixels) + top*Btmp.fRowBytes;
                for(int j = top; j<bottom; j++){
                    for(int i=left ; i<right; i++){
                        DstColor = *((GPixel*) row + i);
                        if(storedDestination == DstColor){ //if we have the value already, don't do the math
                            *((GPixel*) row + i) = storedResult;
                        }
                        else{
                            storedDestination = DstColor;
                            storedResult = helper.blendColor(DstColor, rectColor);
                            *((GPixel*) row + i) = storedResult; //blends the two colors
                        }
                    }
                    row += Btmp.fRowBytes;
                }
            }
        }
    }
}
Beispiel #5
0
  void drawBitmap(const GBitmap &bm, float x, float y, const GPaint &paint) {

    float alpha = paint.getAlpha();
    if(alpha < kTransparentAlpha) {
      return;
    }

    save();
    translate(x, y);

    if(CheckSkew(m_CTM)) {
      drawBitmapXForm(bm, paint);
    } else {
      drawBitmapSimple(bm, paint);
    }

    restore();
  }
void GContext4::drawBitmap(const GBitmap& lclBmp, float x, float y, const GPaint& paint){
    
    float alpha = paint.getAlpha();
    alpha = (alpha>1)?1:((alpha<0)?0:alpha);//bound alpha by 0 and 1
    uint8_t intAlpha = alpha*255 + .5;
    if(intAlpha != 0){
        // first find the intersection
        float gTop = y, gLeft = x, gBottom = y+lclBmp.fHeight, gRight = x+lclBmp.fWidth;
        float inverseScaleX = 1;
        float inverseScaleY = 1;
            mapping.vectorMult(&gLeft, &gTop);
            mapping.vectorMult(&gRight, &gBottom);
            if(mapping.a1 != 1){
                inverseScaleX = abs(1/mapping.a1); //hide divides as much as possible
            }
            if(mapping.b2 != 1){
                inverseScaleY = abs(1/mapping.b2);
            }
        float lclTop = (gTop<0)?-gTop*inverseScaleY:(gTop>Btmp.fHeight)?(gTop-Btmp.fHeight*inverseScaleY):0;
        float lclLeft = (gLeft<0)?-gLeft*inverseScaleX:(gLeft>Btmp.fWidth)?(gLeft-Btmp.fWidth*inverseScaleX):0;
        helper.findIntersection(&gLeft, &gRight, &gTop, &gBottom, Btmp.fHeight, Btmp.fWidth); //even if directions are switched we will still move from gLeft to gRight and gTop to gBottom
        if((gLeft != gRight) && (gTop != gBottom)){ //if not visible, do nothing
            int topPixValue = helper.roundToInt(gTop), bottomPixValue = helper.roundToInt(gBottom);
            int gLeftStartValue = helper.roundToInt(gLeft), gRightPixValue = helper.roundToInt(gRight);
            int gIntervalPixelWidth = gRightPixValue - gLeftStartValue;
            int gIntervalPixelHeight = bottomPixValue - topPixValue;
            int lclLeftStartValue = helper.roundToInt(lclLeft);
            
            uint32_t DstColor;
            uint32_t lclColor;
            
            
            char* gRow = ((char*) Btmp.fPixels + topPixValue*Btmp.fRowBytes);
            char* lclRow = ((char*) lclBmp.fPixels + helper.roundToInt(lclTop)*lclBmp.fRowBytes);
            char* lclStartRow = lclRow;
            
            
            float lclXIncrementer = 0;
            float lclYIncrementer = 0;
            
            if (mapping.b2 > 0) { //if scale up & positive for Y
                for (int j = 0; j<gIntervalPixelHeight; j++) {
                    if (mapping.a1 > 0) {
                        for (int i = 0; i < gIntervalPixelWidth; i++) {
                            DstColor = *((GPixel*) gRow + gLeftStartValue + i);
                            lclColor = *((GPixel*) lclRow + lclLeftStartValue + helper.roundToInt(lclXIncrementer));
                            lclXIncrementer += inverseScaleX;
                            if (lclColor != 0) { //if source alpha is not zero
                                if(intAlpha == 1){
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.blendColor(DstColor, lclColor);
                                }
                                else if( DstColor == 0 ) { //if destination alpha == 0
                                    
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.packARGB(lclColor, intAlpha);
                                }
                                else{
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.blendColorWithAlpha(DstColor, lclColor, intAlpha);
                                }
                            }
                        }
                        lclXIncrementer = 0;
                    }
                    else{
                        for (int i = 0; i > gIntervalPixelWidth; i--) {
                            DstColor = *((GPixel*) gRow + gLeftStartValue + i);
                            lclColor = *((GPixel*) lclRow + lclLeftStartValue + helper.roundToInt(lclXIncrementer));
                            lclXIncrementer += inverseScaleX;
                            if (lclColor != 0) { //if source alpha is not zero
                                if(intAlpha == 1){
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.blendColor(DstColor, lclColor);
                                }
                                else if( DstColor == 0 ) { //if destination alpha == 0
                                    
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.packARGB(lclColor, intAlpha);
                                }
                                else{
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.blendColorWithAlpha(DstColor, lclColor, intAlpha);
                                }
                            }
                        }
                        lclXIncrementer = 0;
                    }
                    lclYIncrementer += inverseScaleY;
                    gRow += Btmp.fRowBytes;
                    lclRow = lclStartRow + helper.roundToInt(lclYIncrementer)*lclBmp.fRowBytes;
                }
            }
            else{
                for (int j = 0; j>gIntervalPixelHeight; j--) {
                    if (mapping.a1 > 0) {
                        for (int i = 0; i < gIntervalPixelWidth; i++) {
                            DstColor = *((GPixel*) gRow + gLeftStartValue + i);
                            lclColor = *((GPixel*) lclRow + lclLeftStartValue + helper.roundToInt(lclXIncrementer));
                            lclXIncrementer += inverseScaleX;
                            if (lclColor != 0) {
                                if(intAlpha == 1){
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.blendColor(DstColor, lclColor);
                                }
                                else if( DstColor == 0 ) {
                                    
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.packARGB(lclColor, intAlpha);
                                }
                                else{
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.blendColorWithAlpha(DstColor, lclColor, intAlpha);
                                }
                            }
                        }
                        lclXIncrementer = 0;
                    }
                    else{
                        for (int i = 0; i > gIntervalPixelWidth; i--) {
                            DstColor = *((GPixel*) gRow + gLeftStartValue + i);
                            lclColor = *((GPixel*) lclRow + lclLeftStartValue + helper.roundToInt(lclXIncrementer));
                            lclXIncrementer += inverseScaleX;
                            if (lclColor != 0) { //if source alpha is not zero
                                if(intAlpha == 1){
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.blendColor(DstColor, lclColor);
                                }
                                else if( DstColor == 0 ) { //if destination alpha == 0
                                    
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.packARGB(lclColor, intAlpha);
                                }
                                else{
                                    *((GPixel*) gRow + gLeftStartValue + i) = helper.blendColorWithAlpha(DstColor, lclColor, intAlpha);
                                }
                            }
                        }
                        lclXIncrementer = 0;
                    }
                    lclYIncrementer += inverseScaleY;
                    gRow += Btmp.fRowBytes; //steps a row of bytes in Btmp
                    lclRow = lclStartRow + helper.roundToInt(lclYIncrementer)*lclBmp.fRowBytes; //steps a row of bytes in lclBmp
                }
            }
        }
    }
}
Beispiel #7
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);
        }
      }
    }
  }