static bool in_resize_corner(const GRect& r, float x, float y, GPoint* anchor) { if (hit_test(r.left(), r.top(), x, y)) { anchor->set(r.right(), r.bottom()); return true; } else if (hit_test(r.right(), r.top(), x, y)) { anchor->set(r.left(), r.bottom()); return true; } else if (hit_test(r.right(), r.bottom(), x, y)) { anchor->set(r.left(), r.top()); return true; } else if (hit_test(r.left(), r.bottom(), x, y)) { anchor->set(r.right(), r.top()); return true; } return false; }
void concat(GCanvas* canvas) { const GRect r = this->getRect(); const float cx = (r.left() + r.right()) / 2; const float cy = (r.top() + r.bottom()) / 2; canvas->translate(cx, cy); canvas->rotate(fAngle * M_PI / 180); canvas->translate(-cx, -cy); }
/** * Fill the rectangle with color, using SRC_OVER porter-duff mode. * * The affected pixels are those whose centers are "contained" inside the rectangle: * e.g. contained == center > min_edge && center <= max_edge * * Any area in the rectangle that is outside of the bounds of the canvas is ignored. */ void fillRect(const GRect& rect, const GColor& color) { // Get dimensions of rectangle int le = GRoundToInt(rect.left()); int to = GRoundToInt(rect.top()); int ri = GRoundToInt(rect.right()); int bo = GRoundToInt(rect.bottom()); // Fix rectangle boundaries if (le < 0) {le = 0;} if (to < 0) {to = 0;} if (ri > draw.width()) {ri = draw.width();} if (bo > draw.height()) {bo = draw.height();} // Don't draw if rectangle is of zero size if ((le < 0 && ri < 0) || (le > draw.width() && ri > draw.width())) { return; } if ((to < 0 && bo < 0) || (to > draw.height() && bo > draw.height())) { return; } if ((to == bo) || (le == ri)) { return; } // If alpha value is 0, end method if (color.fA <= 0) { return; } // Prepare color to place into bitmap GColor c = color.pinToUnit(); unsigned a = (int)(c.fA * 255.99999); unsigned r = (int)(c.fR * c.fA * 255.99999); unsigned g = (int)(c.fG * c.fA * 255.99999); unsigned b = (int)(c.fB * c.fA * 255.99999); // Fill desired pixels GPixel* dst = draw.fPixels; dst = (GPixel*)((char*)dst + (int)to * draw.rowBytes()); for (int y = to; y < bo; ++y) { for (int x = le; x < ri; ++x) { if (GPixel_GetA(*draw.getAddr(x, y)) > 0) { // blend float sA = c.fA + ((GPixel_GetA(*draw.getAddr(x, y)) / 255.99999) * (1.0f - c.fA)); float sR = (c.fR * c.fA) + ((GPixel_GetR(*draw.getAddr(x, y)) / 255.99999) * (1.0f - c.fA)); float sG = (c.fG * c.fA) + ((GPixel_GetG(*draw.getAddr(x, y)) / 255.99999) * (1.0f - c.fA)); float sB = (c.fB * c.fA) + ((GPixel_GetB(*draw.getAddr(x, y)) / 255.99999) * (1.0f - c.fA)); unsigned nA = (int)(sA * 255.99999); unsigned nR = (int)(sR * 255.99999); unsigned nG = (int)(sG * 255.99999); unsigned nB = (int)(sB * 255.99999); dst[x] = GPixel_PackARGB(nA, nR, nG, nB); } else { // Fill color unblended dst[x] = GPixel_PackARGB(a, r, g, b); } } dst = (GPixel*)((char*)dst + draw.rowBytes()); } }
/** * Scale and translate the bitmap such that is fills the specific rectangle. * * Any area in the rectangle that is outside of the bounds of the canvas is ignored. * * If a given pixel in the bitmap is not opaque (e.g. GPixel_GetA() < 255) then blend it * using SRCOVER blend mode. */ void fillBitmapRect(const GBitmap& src, const GRect& dst) { // Store dimensions of dst rectangle int left = dst.left(); int top = dst.top(); int right = dst.right(); int bottom = dst.bottom(); int rW = dst.width(); int rH = dst.height(); // Store dimensions of src bitmap int bW = src.width(); int bH = src.height(); // Find necessary scale factor for both width and height float sx = (float)bW/(float)rW; float sy = (float)bH/(float)rH; float tx = 0 - left; float ty = 0 - top; // Create matrix for scaling float scale[6] = {sx, 0, 0, 0, sy, 0}; // Create matrix for translating float translate[6] = {1, 0, tx, 0, 1, ty}; // Combine the matrices float both[6] = {sx, 0, sx*tx, 0, sy, sy*ty}; // For loop that takes each point in dst and find corresponding point in src GPixel* d = draw.fPixels; d = (GPixel*)((char*)d + (int)top * draw.rowBytes()); for (int y = top; y < bottom; ++y) { for (int x = left; x < right; ++x) { // Only map pixels that are in the bitmap if ((x >= 0 && x < draw.width()) && (y >= 0 && y < draw.height())) { // Find corresponding point in src bitmap int xP; int yP; xP = both[0] * x + both[1] * y + both[2]; yP = both[3] * x + both[4] * y + both[5]; // Apply CTM to x and y int nX = (CTM[0] * x) + (CTM[1] * y) + (CTM[2]); int nY = (CTM[3] * x) + (CTM[4] * y) + (CTM[5]); // Prepare color to fill unsigned a = GPixel_GetA(*src.getAddr(xP, yP)); unsigned r = GPixel_GetR(*src.getAddr(xP, yP)); unsigned g = GPixel_GetG(*src.getAddr(xP, yP)); unsigned b = GPixel_GetB(*src.getAddr(xP, yP)); unsigned nA = a; unsigned nR = r; unsigned nG = g; unsigned nB = b; if (GPixel_GetA(*draw.getAddr(x, y)) > 0) { // blend float lA = GPixel_GetA(*src.getAddr(xP, yP)) / 255.99999; float lR = GPixel_GetR(*src.getAddr(xP, yP)) / 255.99999; float lG = GPixel_GetG(*src.getAddr(xP, yP)) / 255.99999; float lB = GPixel_GetB(*src.getAddr(xP, yP)) / 255.99999; float sA = lA + ((GPixel_GetA(*draw.getAddr(x, y)) / 255.99999) * (1.0f - lA)); float sR = lR + ((GPixel_GetR(*draw.getAddr(x, y)) / 255.99999) * (1.0f - lA)); float sG = lG + ((GPixel_GetG(*draw.getAddr(x, y)) / 255.99999) * (1.0f - lA)); float sB = lB + ((GPixel_GetB(*draw.getAddr(x, y)) / 255.99999) * (1.0f - lA)); /* float sA = lA + ((GPixel_GetA(*draw.getAddr(nX, nY)) / 255.99999) * (1.0f - lA)); float sR = lR + ((GPixel_GetR(*draw.getAddr(nX, nY)) / 255.99999) * (1.0f - lA)); float sG = lG + ((GPixel_GetG(*draw.getAddr(nX, nY)) / 255.99999) * (1.0f - lA)); float sB = lB + ((GPixel_GetB(*draw.getAddr(nX, nY)) / 255.99999) * (1.0f - lA)); */ nA = (int)(sA * 255.99999); nR = (int)(sR * 255.99999); nG = (int)(sG * 255.99999); nB = (int)(sB * 255.99999); d[x] = GPixel_PackARGB(nA, nR, nG, nB); //d = (GPixel*)((char*)d + (int)nY * draw.rowBytes()); //d[nX] = GPixel_PackARGB(nA, nR, nG, nB); //d = (GPixel*)((char*)d - (int)nY * draw.rowBytes()); } else { d[x] = GPixel_PackARGB(a, r, g, b); //d = (GPixel*)((char*)d + (int)nY * draw.rowBytes()); //d[nX] = GPixel_PackARGB(a, r, g, b); //d = (GPixel*)((char*)d - (int)nY * draw.rowBytes()); } } } d = (GPixel*)((char*)d + draw.rowBytes()); } }
static GRect offset(const GRect& rect, float dx, float dy) { return GRect::MakeLTRB(rect.left() + dx, rect.top() + dy, rect.right() + dx, rect.bottom() + dy); }
static bool contains(const GRect& rect, float x, float y) { return rect.left() < x && x < rect.right() && rect.top() < y && y < rect.bottom(); }