/** * Walk all active monitors. * * @param[in] monitor If NULL, the first monitor is returned and the monitor pool is locked (thread lib is globally locked)<br> * If non-NULL, the next monitor is returned. * @return a pointer to a monitor, or NULL if all monitors walked (and thread lib is globally unlocked). * * @note As this is currently implemented, this must be called to walk ALL monitors. It can't * be used to look for a specific monitor and then quit. * */ hythread_monitor_t VMCALL hythread_monitor_walk (hythread_monitor_t monitor) { hythread_monitor_pool_t pool; hythread_library_t lib = get_default_library (); ASSERT (lib); ASSERT (lib->monitor_pool); ASSERT (lib->monitor_pool->entries); ASSERT (MACRO_SELF () != 0); if (monitor == NULL) { GLOBAL_LOCK (MACRO_SELF (), CALLER_MONITOR_WALK); pool = READP (lib->monitor_pool); monitor = &pool->entries[0]; if (READU (monitor->count) != FREE_TAG) return monitor; } else { pool = pool_for_monitor (lib, monitor); if (pool == NULL) { /* should never happen */ GLOBAL_UNLOCK (MACRO_SELF ()); return NULL; } } do { if (monitor >= &pool->entries[MONITOR_POOL_SIZE - 1]) { if ((pool = READP (pool->next)) == NULL) { /* we've walked all monitors */ GLOBAL_UNLOCK (MACRO_SELF ()); return NULL; } monitor = &pool->entries[0]; } else { monitor++; } } while (READU (monitor->count) == FREE_TAG); return monitor; }
/*---------------------------------------------------------------------------*/ int TTWAIN_SupportsCompressionType(TW_UINT16 comprType) { int rc; TUINT32 size; int found = FALSE; TW_ENUMERATION *container = 0; TW_HANDLE handle = 0; if (!TTWAIN_IsCapCompressionSupported()) return FALSE; rc = TTWAIN_GetCap(ICAP_COMPRESSION, TWON_ENUMERATION, (void *)0, &size); if (!rc || !size) return FALSE; handle = GLOBAL_ALLOC(GMEM_FIXED, size); if (!handle) return FALSE; container = (TW_ENUMERATION *)GLOBAL_LOCK(handle); rc = TTWAIN_GetCap(ICAP_COMPRESSION, TWON_ENUMERATION, (void *)container, 0); if (!rc) goto done; found = TTWAIN_IsItemInList(container->ItemList, &comprType, container->NumItems, DCItemSize[container->ItemType]); found = TRUE; done: if (handle) { GLOBAL_UNLOCK(handle); GLOBAL_FREE(handle); } return found; }
/*---------------------------------------------------------------------------*/ int TTWAIN_SupportsPixelType(TTWAIN_PIXTYPE pix_type) { TW_HANDLE handle; TW_ENUMERATION *container; int rc, found = FALSE; TUINT32 size4data; TW_UINT16 twPix; twPix = PixType[pix_type].type; rc = TTWAIN_GetCap(ICAP_PIXELTYPE, TWON_ENUMERATION, (void *)0, &size4data); if (!rc) return FALSE; if (!size4data) return FALSE; handle = GLOBAL_ALLOC(GMEM_FIXED, size4data); if (!handle) return FALSE; container = (TW_ENUMERATION *)GLOBAL_LOCK(handle); rc = TTWAIN_GetCap(ICAP_PIXELTYPE, TWON_ENUMERATION, (void *)container, 0); if (!rc) goto done; found = TTWAIN_IsItemInList(container->ItemList, &twPix, container->NumItems, DCItemSize[container->ItemType]); done: GLOBAL_UNLOCK(handle); GLOBAL_FREE(handle); return found; }
/*---------------------------------------------------------------------------*/ static int TTWAIN_MemoryXferHandler(void) { TW_IMAGEMEMXFER *imageMemXfer = 0; TW_HANDLE imageMemXferH = 0; TW_HANDLE transferBufferH = 0; TW_SETUPMEMXFER setup; TW_IMAGEINFO info; TW_IMAGELAYOUT imageLayout; TUINT32 nTransferDone; TW_INT16 rc1, rc2, rc3, rc4, twRC2; int ret = FALSE; int stopScanning = 0; UCHAR *transferBuffer = 0; UCHAR *sourceBuffer = 0; UCHAR *targetBuffer = 0; unsigned int rows; double pixSize; int extraX = 0; int extraY = 0; TW_UINT32 rowsToCopy = 0; TW_UINT32 rowsRemaining = 0; TW_UINT32 bytesToCopy = 0; TW_UINT32 bytesToWrap = 0; TW_UINT32 memorySize = 0; int imgInfoOk; /* on Mac often (always) is impossible to get the imageinfo about the transfer... so no I can't prealloc memory and do other checks about size etc... */ /*printf("%s\n", __PRETTY_FUNCTION__);*/ memset(&info, 0, sizeof(TW_IMAGEINFO)); rc1 = TTWAIN_DS(DG_IMAGE, DAT_IMAGEINFO, MSG_GET, (TW_MEMREF)&info); imgInfoOk = (rc1 == TWRC_SUCCESS); /*printf("get image info returns %d\n", imgInfoOk);*/ rc4 = TTWAIN_DS(DG_IMAGE, DAT_IMAGELAYOUT, MSG_GET, &imageLayout); /* determine the transfer buffer size */ rc2 = TTWAIN_DS(DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET, (TW_MEMREF)&setup); transferBufferH = GLOBAL_ALLOC(GMEM_FIXED, setup.Preferred); if (!transferBufferH) return FALSE; transferBuffer = (UCHAR *)GLOBAL_LOCK(transferBufferH); if (imgInfoOk) { pixSize = info.BitsPerPixel / 8.0; memorySize = info.ImageLength * CEIL(info.ImageWidth * pixSize); } else { /* we need to allocate incrementally the memory needs to store the image*/ memorySize = setup.Preferred; /* start using the setupmemxfer.preferred size*/ pixSize = 3; } if (TTwainData.transferInfo.usageMode == TTWAIN_MODE_UNLEASHED) { /* TTwainData.transferInfo = GLOBAL_ALLOC(GMEM_FIXED, memorySize); */ TTwainData.transferInfo.memoryBuffer = (UCHAR *)malloc(memorySize); if (!TTwainData.transferInfo.memoryBuffer) { /*tmsg_error("unable to allocate memory!");*/ return FALSE; } if (imgInfoOk) { TTwainData.transferInfo.memorySize = memorySize; TTwainData.transferInfo.preferredLx = info.ImageWidth; TTwainData.transferInfo.preferredLy = info.ImageLength; } else { TTwainData.transferInfo.memorySize = setup.Preferred; TTwainData.transferInfo.preferredLx = 0; TTwainData.transferInfo.preferredLy = 0; } } extraX = info.ImageWidth - TTwainData.transferInfo.preferredLx; extraY = info.ImageLength - TTwainData.transferInfo.preferredLy; rowsRemaining = MIN(TTwainData.transferInfo.preferredLy, info.ImageLength); targetBuffer = TTwainData.transferInfo.memoryBuffer; /*clean-up the buffer memset(targetBuffer, 0xff, TTwainData.transferInfo.memorySize); */ imageMemXferH = GLOBAL_ALLOC(GMEM_FIXED, sizeof(TW_IMAGEMEMXFER)); if (!imageMemXferH) return FALSE; imageMemXfer = (TW_IMAGEMEMXFER *)GLOBAL_LOCK(imageMemXferH); imageMemXfer->Memory.TheMem = (char *)transferBuffer; imageMemXfer->Memory.Length = setup.Preferred; imageMemXfer->Memory.Flags = TWMF_APPOWNS | TWMF_POINTER; TTwainData.transferInfo.pendingXfers.Count = 0; /* transfer the data -- loop until done or canceled */ nTransferDone = 0; do { rc3 = TTWAIN_DS(DG_IMAGE, DAT_IMAGEMEMXFER, MSG_GET, (TW_MEMREF)imageMemXfer); nTransferDone++; switch (rc3) { case TWRC_SUCCESS: PRINTF("IMAGEMEMXFER, GET, returns SUCCESS\n"); if (imgInfoOk) { TW_UINT32 colsToCopy; rowsToCopy = MIN(imageMemXfer->Rows, rowsRemaining); colsToCopy = MIN(imageMemXfer->Columns, (unsigned long)TTwainData.transferInfo.preferredLx); bytesToCopy = CEIL(colsToCopy * pixSize); bytesToWrap = CEIL(TTwainData.transferInfo.preferredLx * pixSize); } else { TW_UINT32 newMemorySize; rowsToCopy = imageMemXfer->Rows; bytesToCopy = imageMemXfer->BytesPerRow; bytesToWrap = bytesToCopy; newMemorySize = (TTwainData.transferInfo.preferredLy + imageMemXfer->Rows) * imageMemXfer->BytesPerRow; if (TTwainData.transferInfo.memorySize < newMemorySize) { TTwainData.transferInfo.memoryBuffer = (UCHAR *)realloc(TTwainData.transferInfo.memoryBuffer, newMemorySize); TTwainData.transferInfo.memorySize = newMemorySize; targetBuffer = TTwainData.transferInfo.memoryBuffer + (TTwainData.transferInfo.preferredLy * imageMemXfer->BytesPerRow); } TTwainData.transferInfo.preferredLy += rowsToCopy; if ((int)imageMemXfer->Columns > TTwainData.transferInfo.preferredLx) TTwainData.transferInfo.preferredLx = imageMemXfer->Columns; } sourceBuffer = (UCHAR *)imageMemXfer->Memory.TheMem; if (TTwainData.transferInfo.nextImageNeedsToBeInverted) INVERT_BYTE(sourceBuffer, bytesToCopy) for (rows = 0; rows < rowsToCopy; rows++) { memcpy(targetBuffer, sourceBuffer, bytesToCopy); targetBuffer += bytesToWrap; sourceBuffer += imageMemXfer->BytesPerRow; } rowsRemaining -= rowsToCopy; break; case TWRC_XFERDONE: PRINTF("IMAGEMEMXFER, GET, returns XFERDONE\n"); /*copy the last transfer data*/ if (imgInfoOk) { TW_UINT32 colsToCopy; rowsToCopy = MIN(imageMemXfer->Rows, rowsRemaining); colsToCopy = MIN(imageMemXfer->Columns, (unsigned long)TTwainData.transferInfo.preferredLx); bytesToCopy = CEIL(colsToCopy * pixSize); bytesToWrap = CEIL(TTwainData.transferInfo.preferredLx * pixSize); } else { TW_UINT32 newMemorySize; rowsToCopy = imageMemXfer->Rows; bytesToCopy = imageMemXfer->BytesPerRow; bytesToWrap = bytesToCopy; newMemorySize = (TTwainData.transferInfo.preferredLy + imageMemXfer->Rows) * imageMemXfer->BytesPerRow; if (TTwainData.transferInfo.memorySize < newMemorySize) { TTwainData.transferInfo.memoryBuffer = (UCHAR *)realloc(TTwainData.transferInfo.memoryBuffer, newMemorySize); TTwainData.transferInfo.memorySize = newMemorySize; targetBuffer = TTwainData.transferInfo.memoryBuffer + (TTwainData.transferInfo.preferredLy * imageMemXfer->BytesPerRow); } TTwainData.transferInfo.preferredLy += rowsToCopy; if ((int)imageMemXfer->Columns > TTwainData.transferInfo.preferredLx) TTwainData.transferInfo.preferredLx = imageMemXfer->Columns; } sourceBuffer = (UCHAR *)imageMemXfer->Memory.TheMem; if (TTwainData.transferInfo.nextImageNeedsToBeInverted) INVERT_BYTE(sourceBuffer, bytesToCopy) for (rows = 0; rows < rowsToCopy; rows++) { memcpy(targetBuffer, sourceBuffer, bytesToCopy); targetBuffer += bytesToWrap; sourceBuffer += imageMemXfer->BytesPerRow; } rowsRemaining -= rowsToCopy; PRINTF("get pending xfers\n"); twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&TTwainData.transferInfo.pendingXfers); if (twRC2 != TWRC_SUCCESS) { printf("pending xfers != success"); ret = FALSE; goto done; } PRINTF(" pending count = %d\n", TTwainData.transferInfo.pendingXfers.Count); if (TTwainData.transferInfo.pendingXfers.Count == 0) { ret = TRUE; goto done; } if (TTwainData.transferInfo.pendingXfers.Count == 0xffff) { ret = TRUE; goto done; } if (TTwainData.transferInfo.pendingXfers.Count == 0xfffe) { ret = TRUE; goto done; } ret = TRUE; goto done; case TWRC_CANCEL: TTWAIN_RecordError(); twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&TTwainData.transferInfo.pendingXfers); if (twRC2 != TWRC_SUCCESS) { ret = FALSE; goto done; } if (TTwainData.transferInfo.pendingXfers.Count == 0) { ret = FALSE; goto done; } break; case TWRC_FAILURE: PRINTF("IMAGEMEMXFER, GET, returns FAILURE\n"); TTWAIN_RecordError(); twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&TTwainData.transferInfo.pendingXfers); if (twRC2 != TWRC_SUCCESS) { ret = FALSE; goto done; } if (TTwainData.transferInfo.pendingXfers.Count == 0) { ret = FALSE; goto done; } break; default: PRINTF("IMAGEMEMXFER, GET, returns ?!? Default handler called\n"); /* Abort the image */ TTWAIN_RecordError(); twRC2 = TTWAIN_DS(DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&TTwainData.transferInfo.pendingXfers); if (twRC2 != TWRC_SUCCESS) { ret = FALSE; goto done; } if (TTwainData.transferInfo.pendingXfers.Count == 0) { ret = FALSE; goto done; } } } while (rc3 == TWRC_SUCCESS); done: if (ret == TRUE) { if (TTwainData.callback.onDoneCb) { float xdpi, ydpi; TTWAIN_PIXTYPE pixType; xdpi = TTWAIN_Fix32ToFloat(info.XResolution); ydpi = TTWAIN_Fix32ToFloat(info.YResolution); if (imgInfoOk) { xdpi = TTWAIN_Fix32ToFloat(info.XResolution); ydpi = TTWAIN_Fix32ToFloat(info.YResolution); switch (BB(info.PixelType, info.BitsPerPixel)) { case BB(TWPT_BW, 1): pixType = TTWAIN_BW; break; case BB(TWPT_GRAY, 8): pixType = TTWAIN_GRAY8; break; case BB(TWPT_RGB, 24): pixType = TTWAIN_RGB24; break; default: pixType = TTWAIN_RGB24; break; } } else { float lx = TTWAIN_Fix32ToFloat(imageLayout.Frame.Right) - TTWAIN_Fix32ToFloat(imageLayout.Frame.Left); float ly = TTWAIN_Fix32ToFloat(imageLayout.Frame.Bottom) - TTWAIN_Fix32ToFloat(imageLayout.Frame.Top); xdpi = (float)TTwainData.transferInfo.preferredLx / lx; ydpi = (float)TTwainData.transferInfo.preferredLy / ly; switch (imageMemXfer->BytesPerRow / TTwainData.transferInfo.preferredLx) { case 1: pixType = TTWAIN_GRAY8; break; case 3: pixType = TTWAIN_RGB24; break; default: { double b = (imageMemXfer->BytesPerRow / (double)TTwainData.transferInfo.preferredLx); if ((b >= 0.125) && (b < 8)) pixType = TTWAIN_BW; else { printf("unable to det pix type assume RGB24\n"); pixType = TTWAIN_RGB24; } break; } } } stopScanning = !TTwainData.callback.onDoneCb( TTwainData.transferInfo.memoryBuffer, pixType, TTwainData.transferInfo.preferredLx, TTwainData.transferInfo.preferredLy, TTwainData.transferInfo.preferredLx, xdpi, ydpi, TTwainData.callback.onDoneArg); #ifdef MACOSX PRINTF("stopScanning = %d\n", stopScanning); exitTwainSession(); #endif } } else /*ret == FALSE*/ { if (TTwainData.callback.onErrorCb) { TTwainData.callback.onErrorCb(TTwainData.callback.onErrorArg, 0); } } if (imageMemXferH) { GLOBAL_UNLOCK(imageMemXferH); GLOBAL_FREE(imageMemXferH); } if (transferBufferH) { GLOBAL_UNLOCK(transferBuffer); GLOBAL_FREE(transferBufferH); } return ret && !stopScanning; }
/*---------------------------------------------------------------------------*/ int TTWAIN_SetPixelType(TTWAIN_PIXTYPE pixtype) { TUINT32 twPix; int rc, rc2, rc3, rc4, rc5, bdRc; TW_ENUMERATION *container = 0; TW_HANDLE handle = 0; TW_UINT16 twFlavor, twBitDepth; int found; TUINT32 size; twPix = PixType[pixtype].type; twFlavor = PixType[pixtype].flavor; twBitDepth = PixType[pixtype].bitDepth; /*the default in twain specs is chocolate*/ TTwainData.transferInfo.nextImageNeedsToBeInverted = ((twFlavor != TWPF_CHOCOLATE) && (twFlavor != FLAVOR_UNUSED)); rc = TTWAIN_SetCap(ICAP_PIXELTYPE, TWON_ONEVALUE, TWTY_UINT16, (TW_UINT32 *)&twPix); if (TTWAIN_IsCapBitDepthSupported()) bdRc = TTWAIN_SetBitDepth(twBitDepth); if (rc) { if (twFlavor != FLAVOR_UNUSED) { rc2 = TTWAIN_GetCap(ICAP_PIXELFLAVOR, TWON_ENUMERATION, (void *)0, &size); if (rc2 && size) { handle = GLOBAL_ALLOC(GMEM_FIXED, size); if (!handle) return TRUE; /*non sono semplicamente riuscito a prendere info riguardo il pixelFlavor, ma setPixelType e' andato a buon fine */ #ifdef _WIN32 container = (TW_ENUMERATION *)handle; #else container = (TW_ENUMERATION *)GLOBAL_LOCK(handle); #endif rc3 = TTWAIN_GetCap(ICAP_PIXELFLAVOR, TWON_ENUMERATION, (void *)container, 0); if (rc3) { found = TTWAIN_IsItemInList(container->ItemList, &twFlavor, container->NumItems, DCItemSize[container->ItemType]); /*let's try to set....*/ if (found) { rc4 = TTWAIN_SetCap(ICAP_PIXELFLAVOR, TWON_ONEVALUE, TWTY_UINT16, (TW_UINT32 *)&twFlavor); if (rc4) { TW_UINT16 current, *itemList; /*check if it's properly set...*/ rc5 = TTWAIN_GetCap(ICAP_PIXELFLAVOR, TWON_ENUMERATION, (void *)container, 0); if (rc5) { itemList = (TW_UINT16 *)container->ItemList; current = itemList[container->CurrentIndex]; if (current == twFlavor) { TTwainData.transferInfo.nextImageNeedsToBeInverted = FALSE; } } } } } } } } if (handle) { GLOBAL_UNLOCK(handle); GLOBAL_FREE(handle); } return rc; }