/***************************************************************************** * * (C) COPYRIGHT MICROSOFT CORPORATION, 2000 * * TITLE: xmltools.cpp * * VERSION: 1.0 * * AUTHOR: LazarI * * DGetATE: 10/18/00 * * DESCRIPTION: Class which encapsulates XML DOM for implementing * wizard templates * *****************************************************************************/ #include "precomp.h" #pragma hdrstop ///////////////////////////////// // CPhotoTemplates impl. // global strings static const TCHAR gszVersionGUID[] = TEXT("{352A15C4-1D19-4e93-AF92-D939C2812491}"); static const TCHAR gszPatternDefs[] = TEXT("template-def"); static const TCHAR gszPatternLocale[] = TEXT("template-definitions[@measurements = \"%s\"]"); static const TCHAR gszPatternLocaleInd[] = TEXT("template-definitions[@measurements = \"locale-independent\"]"); static const TCHAR gszPatternGUID[] = TEXT("template-def[@guid = \"%s\"]"); static const TCHAR gszGUID[] = TEXT("guid"); static const LPCTSTR arrCommonPropNames[CTemplateInfo::PROP_LAST] = { TEXT("guid"), TEXT("group"), TEXT("title"), TEXT("description"), TEXT("repeat-photos"), TEXT("use-thumbnails-for-printing"), TEXT("print-filename"), TEXT("can-rotate"), TEXT("can-crop"), }; ///////////////////////////////////////////////////////////////////////////////////////////////// // utility functions template HRESULT _GetProp(IXMLDOMElement *pElement, LPCTSTR pszName, T &value); // number convertions HRESULT _ConvertTo(LPCTSTR pszValue, LONG &lValue); HRESULT _ConvertTo(LPCTSTR pszValue, double &dValue); HRESULT _ConvertTo(LPCTSTR pszValue, BOOL &bValue); // attributes access HRESULT _GetAttribute(IXMLDOMElement *pElement, LPCTSTR pszAttrName, CComBSTR &bstr); template HRESULT _GetProp(IXMLDOMElement *pElement, LPCTSTR pszName, T &value) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_GetProp: %s"),(pszName ? pszName : TEXT("NULL POINTER!")))); HRESULT hr = E_FAIL; CComBSTR bstr; if( pElement && SUCCEEDED(hr = _GetAttribute(pElement, pszName, bstr)) && SUCCEEDED(hr = _ConvertTo(bstr, value)) ) { hr = S_OK; } WIA_RETURN_HR(hr); } HRESULT _ConvertTo(LPCTSTR pszValue, LONG &lValue) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_ConvertTo(LONG): %s"),(pszValue ? pszValue : TEXT("NULL POINTER!")))); HRESULT hr = E_INVALIDARG; if( pszValue ) { hr = S_OK; TCHAR *endptr = NULL; lValue = _tcstol(pszValue, &endptr, 10); if( ERANGE == errno || *endptr ) { // conversion failed lValue = 0; hr = E_FAIL; } } WIA_RETURN_HR(hr); } HRESULT _ConvertTo(LPCTSTR pszValue, double &dValue) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_ConvertTo(double): %s"),(pszValue ? pszValue : TEXT("NULL POINTER!")))); HRESULT hr = E_INVALIDARG; if( pszValue ) { hr = S_OK; TCHAR *endptr = NULL; dValue = _tcstod(pszValue, &endptr); if( ERANGE == errno || *endptr ) { // conversion failed dValue = 0.0; hr = E_FAIL; } } WIA_RETURN_HR(hr); } HRESULT _ConvertTo(LPCTSTR pszValue, BOOL &bValue) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_ConvertTo(bool): %s"),(pszValue ? pszValue : TEXT("NULL POINTER!")))); HRESULT hr = E_INVALIDARG; if( pszValue ) { hr = S_OK; // check for true first if( 0 == lstrcmp(pszValue, TEXT("yes")) || 0 == lstrcmp(pszValue, TEXT("on")) ) { bValue = true; } else { // check for false next if( 0 == lstrcmp(pszValue, TEXT("no")) || 0 == lstrcmp(pszValue, TEXT("off")) ) { bValue = false; } else { // not a boolean hr = E_FAIL; } } } WIA_RETURN_HR(hr); } HRESULT _GetAttribute(IXMLDOMElement *pElement, LPCTSTR pszAttrName, CComBSTR &bstr) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_GetAttribute(BSTR): %s"),(pszAttrName ? pszAttrName : TEXT("NULL POINTER!")))); HRESULT hr = E_INVALIDARG; CComVariant strAttr; if( pElement && pszAttrName && SUCCEEDED(hr = pElement->getAttribute(CComBSTR(pszAttrName), &strAttr)) ) { if( VT_BSTR == strAttr.vt ) { bstr = strAttr.bstrVal; hr = S_OK; } else { hr = E_FAIL; } } WIA_RETURN_HR(hr); } HRESULT _GetChildElement(IXMLDOMElement *pElement, LPCTSTR pszName, IXMLDOMElement **ppChild) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("_GetChildElement( %s )"),(pszName ? pszName : TEXT("NULL POINTER!")))); HRESULT hr = E_INVALIDARG; if( pElement && pszName && ppChild ) { CComPtr pNode; if( SUCCEEDED(hr = pElement->selectSingleNode(CComBSTR(pszName), &pNode)) && pNode) { // // query for IXMLDOMElement interface // hr = pNode->QueryInterface(IID_IXMLDOMElement, (void **)ppChild); } } WIA_RETURN_HR(hr); } ///////////////////////////////////////////////////////////////////////////////////////////////// // construction/destruction CPhotoTemplates::CPhotoTemplates(): _Measure(MEASURE_UNKNOWN) { } INT MyTemplateDestroyCallback( LPVOID pItem, LPVOID lpData ) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("MyTemplateDestroyCallback( 0x%x, 0x%x )"),pItem,lpData)); if (pItem) { delete (CTemplateInfo *)pItem; } return TRUE; } CPhotoTemplates::~CPhotoTemplates() { CAutoCriticalSection lock(_csList); DPA_DestroyCallback( _hdpaTemplates, MyTemplateDestroyCallback, NULL ); _hdpaTemplates = NULL; } HRESULT CPhotoTemplates::AddTemplates(LPCTSTR pLocale) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::AddTemplates( %s )"),pLocale)); HRESULT hr = E_INVALIDARG; CComPtr pTemplates; CComPtr pLocaleNode; CComBSTR bstrGUID; // // Initialize things as needed // if (!pLocale || !_pRoot) { return hr; } CAutoCriticalSection lock(_csList); // // Select the correct locale node in the XML document // if (_pRoot) { hr = _pRoot->selectSingleNode( CComBSTR(pLocale), &pLocaleNode ); WIA_CHECK_HR(hr,"AddTempaltes: _pRoot->selectSingleNode()"); if (SUCCEEDED(hr) && pLocaleNode) { // // Select the templates sub-node // hr = pLocaleNode->selectNodes(CComBSTR(gszPatternDefs), &pTemplates); WIA_CHECK_HR(hr,"AddTemplates: pLocalNode->selectNodes( )"); if (SUCCEEDED(hr) && pTemplates) { // // update the GUIDs of each template to be uppercase, so we can query later // LONG lCount = 0; hr = pTemplates->get_length(&lCount); WIA_CHECK_HR(hr,"AddTemplates: pTemplates->get_length(&lCount)"); if (SUCCEEDED(hr) && lCount) { // // Loop through all the template and add them to the // the array of templates... // WIA_TRACE((TEXT("AddTemplates: loaded section, adding %d templates.."),lCount)); for( LONG l = 0; SUCCEEDED(hr) && (l < lCount); l++ ) { // // Get the actual XML item for the template... // CComPtr pNode; hr = pTemplates->get_item(l, &pNode); WIA_CHECK_HR(hr,"LoadTemplate: pTemplates->get_item( lRelativeIndex )"); if (SUCCEEDED(hr) && pNode) { // // query IXMLDOMElement interface // CComPtr pTheTemplate; hr = pNode->QueryInterface(IID_IXMLDOMElement, (void **)&pTheTemplate); if (SUCCEEDED(hr) && pTheTemplate) { // // Create template for this item... // CTemplateInfo * pTemplateInfo = (CTemplateInfo *) new CTemplateInfo( pTheTemplate ); if (pTemplateInfo) { INT iRes = -1; if (_hdpaTemplates) { iRes = DPA_AppendPtr( _hdpaTemplates, (LPVOID)pTemplateInfo ); } if (iRes == -1) { // // The item was not added to the DPA, delete it... // delete pTemplateInfo; hr = E_FAIL; } } } } } } pTemplates = NULL; } pLocaleNode = NULL; } } WIA_RETURN_HR(hr); } // public interface HRESULT CPhotoTemplates::Init(IXMLDOMDocument *pDoc) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::Init()"))); HRESULT hr = E_INVALIDARG; CComBSTR bstrGUID; LONG lCountCommon = 0; CAutoCriticalSection lock(_csList); // // If the dpa of item isn't initialized, do it now... // if (!_hdpaTemplates) { _hdpaTemplates = DPA_Create(10); } // // if we're being called twice to initialize, make sure that works... // _pRoot = NULL; // // get the root element & the version guid // if( pDoc && SUCCEEDED(hr = pDoc->get_documentElement(&_pRoot)) && SUCCEEDED(hr = _GetAttribute(_pRoot, TEXT("guid"), bstrGUID)) ) { // check the version if (0==lstrcmp(bstrGUID, gszVersionGUID)) { // // Add the local-independent items first // hr = AddTemplates( gszPatternLocaleInd ); // // Add the local-specific templates second // hr = _GetLocaleMeasurements( &_Measure ); if (SUCCEEDED(hr)) { TCHAR szLocale[MAX_PATH]; *szLocale = 0; hr = _BuildLocaleQueryString(_Measure, szLocale, MAX_PATH); if (SUCCEEDED(hr)) { hr = AddTemplates( szLocale ); } } } } WIA_RETURN_HR(hr); } HRESULT CPhotoTemplates::InitForPrintTo() { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::Init()"))); HRESULT hr = S_OK; // // Our job here is simple -- create 1 template that is the equivalent // of full page. Don't need any icons, etc., just the dimensions // and properties... // _hdpaTemplates = DPA_Create(1); if (_hdpaTemplates) { CTemplateInfo * pTemplateInfo = (CTemplateInfo *) new CTemplateInfo( ); if (pTemplateInfo) { INT iRes = DPA_AppendPtr( _hdpaTemplates, (LPVOID)pTemplateInfo ); if (iRes == -1) { // // The item was not added to the DPA, delete it... // delete pTemplateInfo; hr = E_FAIL; } } } WIA_RETURN_HR(hr); } LONG CPhotoTemplates::Count() { LONG lCount = 0; CAutoCriticalSection lock(_csList); if (_hdpaTemplates) { lCount = (LONG)DPA_GetPtrCount( _hdpaTemplates ); } WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::Count( returning count as %d )"),lCount)); return lCount; } HRESULT CPhotoTemplates::_GetLocaleMeasurements(int *pMeasurements) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::_GetLocalMeasurements()"))); TCHAR szMeasure[5]; if( GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IMEASURE, szMeasure, ARRAYSIZE(szMeasure)) ) { *pMeasurements = (TEXT('0') == szMeasure[0] ? MEASURE_METRIC : MEASURE_US); return S_OK; } WIA_ERROR((TEXT("GetLocaleInfo failed w/GLE = %d"),GetLastError())); return E_FAIL; } HRESULT CPhotoTemplates::_BuildLocaleQueryString(int Measure, LPTSTR pStr, UINT cch) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::_BuildLocaleQueryString()"))); CSimpleString strPatternString; HRESULT hr = E_INVALIDARG; LPCTSTR pszMeasure = MEASURE_METRIC == Measure ? TEXT("cm") : MEASURE_US == Measure ? TEXT("in") : NULL; WIA_TRACE((TEXT("pszMeasure = %s"),pszMeasure)); // build simple XSL pattern query string based on the current locale measurements if (pszMeasure) { strPatternString.Format( gszPatternLocale, pszMeasure ); if (pStr && (cch >= strPatternString.Length())) { hr = StringCchCopy(pStr,cch,strPatternString.String()); } else { hr = E_INVALIDARG; } } else { hr = E_FAIL; } WIA_RETURN_HR(hr); } HRESULT CPhotoTemplates::_BuildGUIDQueryString(const GUID &guid, CComBSTR &bstr) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::_BuildGUIDQueryString()"))); TCHAR szGUID[128]; HRESULT hr = StringFromGUID2(guid, szGUID, ARRAYSIZE(szGUID)); if( SUCCEEDED(hr) ) { TCHAR szPatternString[255]; if( -1 != wnsprintf(szPatternString, ARRAYSIZE(szPatternString), gszPatternGUID, szGUID) ) { bstr = szPatternString; hr = bstr ? S_OK : E_OUTOFMEMORY; } else { hr = E_FAIL; } } WIA_RETURN_HR(hr); } HRESULT CPhotoTemplates::GetTemplate(INT iIndex, CTemplateInfo ** ppTemplateInfo) { WIA_PUSH_FUNCTION_MASK((TRACE_XML,TEXT("CPhotoTemplates::GetTemplate()"))); HRESULT hr = E_INVALIDARG; CAutoCriticalSection lock(_csList); if( ppTemplateInfo ) { if ( _hdpaTemplates ) { if (iIndex < DPA_GetPtrCount( _hdpaTemplates )) { // // Note: it's only okay to hand out pointers here because // we know that wizblob.cpp doesn't delete the CPhotoTemplates // class until all the background threads have exited, etc. // *ppTemplateInfo = (CTemplateInfo *) DPA_FastGetPtr( _hdpaTemplates, iIndex ); hr = S_OK; } } else { hr = E_FAIL; } } WIA_RETURN_HR(hr); } // creates full page template info CTemplateInfo::CTemplateInfo() : _bRepeatPhotos(FALSE), _bUseThumbnailsToPrint(FALSE), _bPrintFilename(FALSE), _bCanRotate(TRUE), _bCanCrop(FALSE), _bPortrait(TRUE), _pStream(NULL) { // // Set imageable area // _rcImageableArea.left = -1; _rcImageableArea.top = -1; _rcImageableArea.right = -1; _rcImageableArea.bottom = -1; // // Set 1 item, takes up all of imageable area // RECT rcItem; rcItem.left = -1; rcItem.top = -1; rcItem.right = -1; rcItem.bottom = -1; _arrLayout.Append( rcItem ); _strTitle.LoadString( IDS_FULL_PAGE_TITLE, g_hInst ); _strDescription.LoadString( IDS_FULL_PAGE_DESC, g_hInst ); } CTemplateInfo::CTemplateInfo( IXMLDOMElement * pTheTemplate ) : _bRepeatPhotos(FALSE), _bUseThumbnailsToPrint(FALSE), _bPrintFilename(FALSE), _bCanRotate(FALSE), _bCanCrop(FALSE), _bPortrait(TRUE), _pStream(NULL) { HRESULT hr; if (pTheTemplate) { // // Make sure backing COM object doesn't go away on us... // pTheTemplate->AddRef(); // // Get all the properties so we can construct an // initialized template for our list... // CComBSTR bstrGroup; CComBSTR bstrTitle; CComBSTR bstrDescription; hr = _GetAttribute( pTheTemplate, arrCommonPropNames[PROP_GROUP], bstrGroup ); WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_GROUP property"); if (SUCCEEDED(hr)) { _strGroup.Assign( CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrGroup)) ); } hr = _GetAttribute( pTheTemplate, arrCommonPropNames[PROP_TITLE], bstrTitle ); WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_TITLE property"); if (SUCCEEDED(hr)) { _strTitle.Assign( CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrTitle)) ); } hr = _GetAttribute( pTheTemplate, arrCommonPropNames[PROP_DESCRIPTION], bstrDescription ); WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_DESCRIPTION property"); if (SUCCEEDED(hr)) { _strDescription.Assign( CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrDescription)) ); } hr = _GetProp( pTheTemplate, arrCommonPropNames[PROP_REPEAT_PHOTOS], _bRepeatPhotos ); WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_REPEAT_PHOTOS property"); hr = _GetProp( pTheTemplate, arrCommonPropNames[PROP_USE_THUMBNAILS_TO_PRINT], _bUseThumbnailsToPrint ); WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_USE_THUMBNAILS_TO_PRINT property"); hr = _GetProp( pTheTemplate, arrCommonPropNames[PROP_PRINT_FILENAME], _bPrintFilename ); WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_USE_THUMBNAILS_TO_PRINT property"); hr = _GetProp( pTheTemplate, arrCommonPropNames[PROP_CAN_ROTATE], _bCanRotate ); WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_CAN_ROTATE property"); hr = _GetProp( pTheTemplate, arrCommonPropNames[PROP_CAN_CROP], _bCanCrop ); WIA_CHECK_HR(hr,"AddTemplate: couldn't get PROP_CAN_CROP property"); // // Get IStream to template preview (icon) // CComPtr pImageInfo; hr = _GetChildElement(pTheTemplate, TEXT("preview-image"), &pImageInfo); WIA_CHECK_HR(hr,"_GetChildElement( preview-image ) failed"); if( SUCCEEDED(hr) && pImageInfo ) { CComBSTR bstrAttr; hr = _GetAttribute(pImageInfo, TEXT("url"), bstrAttr); if(SUCCEEDED(hr)) { // // URL is provided - this overrides everything else // hr = CreateStreamFromURL(bstrAttr, &_pStream); WIA_CHECK_HR(hr,"CreateStreamFromURL failed!"); } else { // // try getting resource info (module + resource name) // hr = _GetAttribute(pImageInfo, TEXT("res-name"), bstrAttr); if(SUCCEEDED(hr)) { CComBSTR bstrModule, bstrType; LPCTSTR pszModule = SUCCEEDED(_GetAttribute(pImageInfo, TEXT("res-module"), bstrModule)) ? bstrModule : NULL; LPCTSTR pszType = SUCCEEDED(_GetAttribute(pImageInfo, TEXT("res-type"), bstrType)) ? bstrType : TEXT("HTML"); // // filter out some of the standard resource types // pszType = (0 == lstrcmp(pszType, TEXT("HTML"))) ? RT_HTML : (0 == lstrcmp(pszType, TEXT("ICON"))) ? RT_ICON : (0 == lstrcmp(pszType, TEXT("BITMAP"))) ? RT_BITMAP : pszType; // // just create a memory stream on the specified resource // hr = CreateStreamFromResource(pszModule, pszType, bstrAttr, &_pStream); WIA_CHECK_HR(hr, "CreateStreamFromResource() failed"); } } } // // Get the layout info for this template... // CComPtr pLayoutInfo; hr = _GetChildElement( pTheTemplate, TEXT("layout"), &pLayoutInfo ); WIA_CHECK_HR(hr,"_GetChildElement( layout ) failed"); if (SUCCEEDED(hr) && pLayoutInfo) { // // Get imageable area for template... // CComPtr pImageableArea; hr = _GetChildElement( pLayoutInfo, TEXT("imageable-area"), &pImageableArea ); WIA_CHECK_HR(hr,"_GetChildElement( imageable-area ) failed"); if (SUCCEEDED(hr) && pImageableArea) { ZeroMemory( &_rcImageableArea, sizeof(_rcImageableArea) ); hr = _GetProp(pImageableArea, TEXT("x"), _rcImageableArea.left); WIA_CHECK_HR(hr,"_GetProp( _rcImageableArea.left ) failed"); hr = _GetProp(pImageableArea, TEXT("y"), _rcImageableArea.top); WIA_CHECK_HR(hr,"_GetProp( _rcImageableArea.top ) failed"); hr = _GetProp(pImageableArea, TEXT("w"), _rcImageableArea.right); WIA_CHECK_HR(hr,"_GetProp( _rcImageableArea.right ) failed"); hr = _GetProp(pImageableArea, TEXT("h"), _rcImageableArea.bottom); WIA_CHECK_HR(hr,"_GetProp( _rcImageableArea.bottom ) failed"); // // Check for special case of all -1's, which // means to scale to full size of printable // area... // WIA_TRACE((TEXT("_rcImageableArea was read as (%d by %d) at (%d,%d)"),_rcImageableArea.right,_rcImageableArea.bottom,_rcImageableArea.left,_rcImageableArea.top)); if ((-1 != _rcImageableArea.left) || (-1 != _rcImageableArea.top) || (-1 != _rcImageableArea.right) || (-1 != _rcImageableArea.bottom)) { // // convert w, h to right & bootom // _rcImageableArea.right += _rcImageableArea.left; _rcImageableArea.bottom += _rcImageableArea.top; } } // // Get individual item rectangles for this template... // CComPtr pListLayout; hr = pLayoutInfo->selectNodes(CComBSTR(TEXT("image-def")), &pListLayout); WIA_CHECK_HR(hr,"pLayoutInfo->selectNodes( image-def ) failed"); if (SUCCEEDED(hr) && pListLayout) { LONG length = 0; hr = pListLayout->get_length(&length); WIA_CHECK_HR(hr,"pListLayout->get_length() failed"); if (SUCCEEDED(hr)) { if (length) { RECT rc; for( long l = 0; l < length; l++ ) { CComPtr pNode; CComPtr pItem; hr = pListLayout->get_item(l, &pNode); WIA_CHECK_HR(hr,"pListLayout->get_item() failed"); if (SUCCEEDED(hr) && pNode) { hr = pNode->QueryInterface(IID_IXMLDOMElement, (void **)&pItem); WIA_CHECK_HR(hr,"pNode->QI( item XMLDOMElement )"); if (SUCCEEDED(hr) && pItem) { ZeroMemory( &rc, sizeof(rc) ); hr = _GetProp(pItem, TEXT("x"), rc.left); WIA_CHECK_HR(hr,"_GetProp( item x ) failed"); hr = _GetProp(pItem, TEXT("y"), rc.top); WIA_CHECK_HR(hr,"_GetProp( item y ) failed"); hr = _GetProp(pItem, TEXT("w"), rc.right); WIA_CHECK_HR(hr,"_GetProp( item w ) failed"); hr = _GetProp(pItem, TEXT("h"), rc.bottom); WIA_CHECK_HR(hr,"_GetProp( item h ) failed"); // // Check for special case of all -1's, which // means to scale to full size of printable // area... // if ((-1 != rc.left) || (-1 != rc.top) || (-1 != rc.right) || (-1 != rc.bottom)) { // convert w, h to right & bootom rc.right += rc.left; rc.bottom += rc.top; } // // insert the image definition // if (-1 == _arrLayout.Append( rc )) { WIA_ERROR((TEXT("Error adding item rectangle to list"))); } } } } } else { WIA_ERROR((TEXT("pListLayout->get_length() returned 0 length!"))); } } } } // // Let go of backing COM object... // pTheTemplate->Release(); } } CTemplateInfo::~CTemplateInfo() { if (_pStream) { _pStream->Release(); _pStream = NULL; } } static void RotateHelper(RECT * pRect, int nNewImageWidth, int nNewImageHeight, BOOL bClockwise) { // // If we don't have a valid pointer, or all the coords are -1, then bail. // The -1 case denotes use all the area, and we don't want to muck with // that... // if (!pRect || ((pRect->left==-1) && (pRect->top==-1) && (pRect->right==-1) && (pRect->bottom==-1))) { return; } WIA_PUSH_FUNCTION_MASK((TRACE_TEMPLATE,TEXT("RotateHelper( pRect(%d,%d,%d,%d) nNewImageWidth=%d nImageHeight=%d bClockwise=%d )"),pRect->left,pRect->top,pRect->right,pRect->bottom,nNewImageWidth,nNewImageHeight,bClockwise)); // // The incoming data is going to be 2 points -- first is the upper left // coord of the original rectangle. The second represents the // the width and the height. The first coord needs to be rotated // 90 degrees, and then put back to the upper left of the rectangle. // // // The width and the height need to be flipped. // int nNewItemWidth = pRect->bottom - pRect->top; int nNewItemHeight = pRect->right - pRect->left; int nNewX, nNewY; if (bClockwise) { nNewX = nNewImageWidth - pRect->bottom; nNewY = pRect->left; } else { nNewX = pRect->top; nNewY = nNewImageHeight - pRect->right; } pRect->left = nNewX; pRect->top = nNewY; pRect->right = nNewX + nNewItemWidth; pRect->bottom = nNewY + nNewItemHeight; WIA_TRACE((TEXT("On Exit: pRect(%d,%d,%d,%d)"),pRect->left,pRect->top,pRect->right,pRect->bottom)); } HRESULT CTemplateInfo::RotateForLandscape() { HRESULT hr = S_OK; WIA_PUSH_FUNCTION_MASK((TRACE_TEMPLATE,TEXT("CTemplateInfo::RotateForLandscape()"))); CAutoCriticalSection lock(_cs); if (_bPortrait) { // // We only want to change this if it's a defined rect // (i.e, not "use all area") // if ((_rcImageableArea.left != -1) && (_rcImageableArea.top != -1) && (_rcImageableArea.right != -1) && (_rcImageableArea.bottom != -1)) { // // The imageable area will just be a flip of width & height. // this relies on the fact the imageable area is always // described in terms of width & height (i.e., top & left // are always 0 in the RECT structure). // LONG oldWidth = _rcImageableArea.right; _rcImageableArea.right = _rcImageableArea.bottom; _rcImageableArea.bottom = oldWidth; } // // Now, map all the points for each item in the layout... // RECT * pRect; for (INT i=0; i < _arrLayout.Count(); i++) { pRect = &_arrLayout[i]; RotateHelper( pRect, _rcImageableArea.right, _rcImageableArea.bottom, FALSE ); } _bPortrait = FALSE; } else { WIA_TRACE((TEXT("Already in landscape mode, doing nothing..."))); } WIA_RETURN_HR(hr); } HRESULT CTemplateInfo::RotateForPortrait() { HRESULT hr = S_OK; WIA_PUSH_FUNCTION_MASK((TRACE_TEMPLATE,TEXT("CTemplateInfo::RotateForPortrait()"))); CAutoCriticalSection lock(_cs); if (!_bPortrait) { // // The imageable area will just be a flip of width & height. // this relies on the fact the imageable area is always // described in terms of width & height (i.e., top & left // are always 0 in the RECT structure). // LONG oldWidth = _rcImageableArea.right; _rcImageableArea.right = _rcImageableArea.bottom; _rcImageableArea.bottom = oldWidth; // // Now, map all the points for each item in the layout... // RECT * pRect; for (INT i=0; i < _arrLayout.Count(); i++) { pRect = &_arrLayout[i]; RotateHelper( pRect, _rcImageableArea.right, _rcImageableArea.bottom, TRUE ); } _bPortrait = TRUE; } else { WIA_TRACE((TEXT("Already in portrait mode, doing nothing..."))); } WIA_RETURN_HR(hr); }