ZQ<ZRectPOD> Insert(const ZDCPixmap& iPixmap) { const ZPointPOD theSourceSize = iPixmap.Size(); const ZPointPOD thePaddedSize = theSourceSize + sPointPOD(2*fPaddingX,2*fPaddingY); for (;;) { int theX, theY; if (spInsert(fRoot, fCapX, fCapY, X(thePaddedSize), Y(thePaddedSize), 0, 0, theX, theY)) { const ZPointPOD destLocation = sPointPOD(theX+fPaddingX, theY+fPaddingY); fPixmap.CopyFrom(destLocation, iPixmap, sRect(theSourceSize)); const ZRectPOD result = sRect(theSourceSize) + destLocation; fUsedX = sMax(fUsedX, R(result) + fPaddingX); fUsedY = sMax(fUsedY, B(result) + fPaddingY); return result; } else { const int newCapX = fCapX + X(thePaddedSize); const int newCapY = fCapY + Y(thePaddedSize); fGrowHorizontal = not fGrowHorizontal; if (fGrowHorizontal && newCapX <= X(fPixmap.Size())) { ZRef<Node> newRoot = new Node; newRoot->fVertical = true; newRoot->fPos = fCapX; newRoot->f0 = fRoot; newRoot->f1 = new Node; fRoot = newRoot; fCapX = newCapX; } else if (newCapY <= Y(fPixmap.Size())) { ZRef<Node> newRoot = new Node; newRoot->fVertical = false; newRoot->fPos = fCapY; newRoot->f0 = fRoot; newRoot->f1 = new Node; fRoot = newRoot; fCapY = newCapY; } else { return null; } } } }
ZDCPixmap::ZDCPixmap(const ZDCPixmap& iSource1, const ZDCPixmap& iSource2, const ZDCPixmap& iMask) { // An undersized or missing image is considered to be all black, so a // missing mask means we're an exact copy of iSource1. if (not iMask) { fRep = iSource1.GetRep(); return; } ZPointPOD source1Size = iSource1.Size(); ZPointPOD source2Size = iSource2.Size(); ZPointPOD maskSize = iMask.Size(); ZPointPOD resultSize; resultSize.h = max(source1Size.h, max(source2Size.h, maskSize.h)); resultSize.v = max(source1Size.v, max(source2Size.v, maskSize.v)); EFormatStandard theStandardFormat = sMapEfficientToStandard(eFormatEfficient_Color_32); RasterDesc theRasterDesc(resultSize, theStandardFormat); PixelDesc thePixelDesc(theStandardFormat); fRep = ZDCPixmapRep::sCreate(theRasterDesc, sRect(resultSize), thePixelDesc); // Do a simple version for now for (ZCoord y = 0; y < resultSize.v; ++y) { for (ZCoord x = 0; x < resultSize.h; ++x) { ZRGBA source1Pixel = iSource1.GetPixel(x, y); ZRGBA source2Pixel = iSource2.GetPixel(x, y); ZRGBA maskPixel = iMask.GetPixel(x, y); this->SetPixel(x, y, source1Pixel * (ZRGBA::sWhite - maskPixel) + source2Pixel * maskPixel); } } }
void ZDCCanvas_X::DrawPixmap(ZDCState& ioState, const ZPoint& inLocation, const ZDCPixmap& inSourcePixmap, const ZDCPixmap* inMaskPixmap) { if (!fDrawable) return; if (!inSourcePixmap) return; ZRect realSourceBounds = inSourcePixmap.Size(); ZPoint realLocation = inLocation + ioState.fOrigin; if (inMaskPixmap) { if (!*inMaskPixmap) return; SetupLock theSetupLock(this); ZDCRgn sourceBoundsRgn = ZRect(realSourceBounds.Size()); ZDCRgn realClip = (this->Internal_CalcClipRgn(ioState) - realLocation) & sourceBoundsRgn; if (realClip.IsEmpty()) return; // Take a one bit copy of the mask Pixmap monoPixmap = fXServer->CreateBitmapFromDCPixmap(fDrawable, *inMaskPixmap, realSourceBounds, false); ZAssert(monoPixmap != None); // Paint with zeroes the area of the mask that's not part of the clip, if any if (ZDCRgn inverseClip = sourceBoundsRgn - realClip) { XGCValues values; values.graphics_exposures = 0; GC monoGC = fXServer->CreateGC(monoPixmap, GCGraphicsExposures, &values); fXServer->SetRegion(monoGC, inverseClip.GetRegion()); fXServer->SetForeground(monoGC, 0); fXServer->FillRectangle(monoPixmap, monoGC, 0, 0, realSourceBounds.Width(), realSourceBounds.Height()); fXServer->FreeGC(monoGC); } fXServer->SetFunction(fGC, GXcopy); ++fChangeCount_Mode; fXServer->SetClipMask(fGC, monoPixmap); fXServer->SetClipOrigin(fGC, realLocation.h, realLocation.v); ++fChangeCount_Clip; fXServer->DrawDCPixmap(fDrawable, fGC, realLocation, inSourcePixmap, realSourceBounds); fXServer->SetClipMask(fGC, None); fXServer->SetClipOrigin(fGC, 0, 0); fXServer->FreePixmap(monoPixmap); } else { SetupLock theSetupLock(this); SetupClip theSetupClip(this, ioState); if (theSetupClip.IsEmpty()) return; fXServer->SetFunction(fGC, GXcopy); ++fChangeCount_Mode; fXServer->DrawDCPixmap(fDrawable, fGC, realLocation, inSourcePixmap, realSourceBounds); } }