예제 #1
0
 void AABox::Scale(const Vector3 &s)
 {
    // NB assumes centered on origin
    Vector3 min = m_minimum * s;
    Vector3 max = m_maximum * s;
    SetExtents(min, max);
 }
void  CHuiRasterizedTextMesh::UpdateMeshL(const TDesC8& aBuffer)
    {
    iUsingPreRasterizedMesh = ETrue;
    ResetLines();
    RDesReadStream stream(aBuffer);
    TInt count = stream.ReadInt32L();
    for (TInt i=count-1;i>=0;i--)
        {
        // lines are in reverse order
        SRasterizedLine line;
        line.iTexture = dynamic_cast<CHuiTexture*>((MHuiTexture*)stream.ReadInt32L()); //scary
        line.iGap = stream.ReadInt32L();
        iLines.InsertL(line, 0);
        }
    TSize extents;
    extents.iWidth = stream.ReadInt32L();
    extents.iHeight = stream.ReadInt32L();
    SetExtents(extents);
    stream.Close();
    
    if (RasterizedShadow()) // update shadow
        {
        for (TInt i = iLines.Count()-1; i >=0; i-- )
            {
            if (iLines[i].iTexture)
                {
                const TInt requestedBlurredSize = HUI_ROUND_FLOAT_TO_INT( 2*iVisual->DropShadowHandler()->iRadius.Now() );
                iLines[i].iTexture->CreateShadowTextureL( requestedBlurredSize, EHuiTextureShadowStyleRasterizedText );
                }
            }
        }
    }
avtVectorMetaData::avtVectorMetaData(std::string n, std::string mn,
                                     avtCentering c, int vd,
                                     const double *extents)
    : avtVarMetaData(avtVectorMetaData::TmfsStruct, n, mn, c)
{
    avtVectorMetaData::Init();
    varDim = vd;
    SetExtents(extents);
}
예제 #4
0
 void AABox::Merge(const Vector3 &point)
 {
    if (m_null)
    { 
       // if null, use this point
       SetExtents(point, point);
    } 
    else 
    {
       m_maximum.MakeCeil(point);
       m_minimum.MakeFloor(point);
       UpdateCorners();
    }
 }
예제 #5
0
   void AABox::Merge(const AABox &rhs)
   {
      // Do nothing if rhs null
      if (rhs.m_null)
      {
         return;
      }
      // Otherwise if current null, just take rhs
      else if (m_null)
      {
         SetExtents(rhs.m_minimum, rhs.m_maximum);
      }
      // Otherwise merge
      else
      {
         Vector3 min = m_minimum;
         Vector3 max = m_maximum;
         max.MakeCeil(rhs.m_maximum);
         min.MakeFloor(rhs.m_minimum);

         SetExtents(min, max);
      }
   }
예제 #6
0
void
BoxExtents::SetFromNode(DataNode *parentNode)
{
    if(parentNode == 0)
        return;

    DataNode *searchNode = parentNode->GetNode("BoxExtents");
    if(searchNode == 0)
        return;

    DataNode *node;
    if((node = searchNode->GetNode("extents")) != 0)
        SetExtents(node->AsDoubleArray());
}
예제 #7
0
   void AABox::Transform(const Matrix4 &matrix)
   {
      // Do nothing if current null
      if (m_null)
         return;

      Vector3 min, max, temp;
      bool first = true;
      size_t i;

      for (i = 0; i < 8; ++i)
      {
         // Transform and check extents
         temp = matrix * m_corners[i];
         if (first || temp.x > max.x)
         {
            max.x = temp.x;
         }

         if (first || temp.y > max.y)
         {
            max.y = temp.y;
         }

         if (first || temp.z > max.z)
         {
            max.z = temp.z;
         }

         if (first || temp.x < min.x)
         {
            min.x = temp.x;
         }

         if (first || temp.y < min.y)
         {
            min.y = temp.y;
         }

         if (first || temp.z < min.z)
         {
            min.z = temp.z;
         }

         first = false;
      }

      SetExtents(min,max);
   }
예제 #8
0
avtMeshMetaData::avtMeshMetaData(std::string s, int nb, int bo, int co, int go,
                                 int sd, int td, avtMeshType mt)
    : AttributeSubject(avtMeshMetaData::TypeMapFormatString)
{
    // Initialize all values.
    *this = avtMeshMetaData();

    // Override some initialization with the passed arguments.
    name                 = s;
    originalName         = name;
    numBlocks            = nb;
    blockOrigin          = bo;
    cellOrigin           = co;
    groupOrigin          = go;
    topologicalDimension = td;
    spatialDimension     = sd;
    meshType             = mt;
    containsExteriorBoundaryGhosts = false;
    SetExtents(0);
}
예제 #9
0
 AABox::AABox(
    float minX, float minY, float minZ,
    float maxX, float maxY, float maxZ)
 {
    SetExtents(minX, minY, minZ, maxX, maxY, maxZ);
 }
예제 #10
0
 AABox::AABox(const Vector3 &min, const Vector3 &max)
 {
    SetExtents(min, max);
 }
void CHuiRasterizedTextMesh::DoBuildL(TInt aRasterizeFlags)
    {
    if(iUsingPreRasterizedMesh)
        {
        return;
        }

    TSize extents(0, 0);
    
    HUI_DEBUG(_L("CHuiRasterizedTextMesh::BuildL() - Updating rasterized text."));

    // This is never NULL during BuildL().
    const TDesC& text = *Text();
    
    // Retrieve the text style used when rasterizing this text mesh.
    THuiTextStyle* textStyle = CHuiStatic::Env().TextStyleManager().TextStyle(iTextStyleId);

    // Retrieve the CFont object used when rasterizing this text mesh.
    CFont* font = textStyle->Font().NearestFontL(iTextMeshScale);

    // Maximum width of a text line in pixels.
    TInt maxWidth = MaxLineWidth();

    TInt startIndex = 0;
    TInt index = 0;
    TInt lineCount = 0;

    CArrayFixFlat<TPtrC>* linePtrs = new (ELeave) CArrayFixFlat<TPtrC>(KLineArrayGranularity);
    CleanupStack::PushL(linePtrs);

    while(startIndex < text.Length())
        {
        /// @todo What is the Symbian way to determine line break chars?
#define HUI_IS_LINE_BREAK(aChar) (aChar == '\n')

        // Find the next logical line.
        while(index < text.Length() && !HUI_IS_LINE_BREAK(text[index]))
            {
            index++;
            }

        TPtrC logicalLine = text.Mid(startIndex, index - startIndex);
        ++index; // Skip the line break.
        startIndex = index;

        switch(LineMode())
            {
            case ELineModeTruncate:
                {
                ++lineCount; // there's always one line created per logical line
                HBufC* buf = logicalLine.AllocLC();
                TPtr ptr = buf->Des();
                // truncate line
                CHuiStatic::ConvertToVisualAndClipL(ptr, *font, maxWidth, maxWidth);
                // create the line entry if not already existing
                
                if (aRasterizeFlags != ERasterizeNone)
                	{
                    if (iLines.Count() < lineCount)
                        {
                        SRasterizedLine line;
                        line.iTexture = NULL;
                        line.iGap = 0;
                        iLines.AppendL(line);
                        
                        if (iPictographInterface)
                            {
                            SRasterizedLine pictographline;
                            pictographline.iTexture = NULL;
                            pictographline.iGap = 0;
                            iPictographLines.AppendL(pictographline);                                
                            }
                        }                	
                        
                	TInt currentLine = lineCount-1;
    	            if (aRasterizeFlags & ERasterizeText)
    	                {
    	                // rasterize a single line (updates texture in iLines[0].iTexture)
        	            RasterizeLineL(ptr, iLines[currentLine]);	                    
    	                }

    	            if (aRasterizeFlags & ERasterizePictographs && iPictographInterface)
    	                {
                        // Rasterize pictographs if needed
        	            RasterizePictographLineL(ptr, font, iPictographLines[currentLine]);
    	                }

    	            // Get extents from the texture we just created
                    CHuiTexture* tex = iLines[currentLine].iTexture;
                    extents.iHeight += iLines[currentLine].iGap;
                    if(tex)
                        {
                        extents.iWidth = Max(extents.iWidth, tex->Size().iWidth);
                        extents.iHeight += tex->Size().iHeight;
                        }	                
                	}
                else
                    {
                    // Don't rasterise or create textures, just get the extents of this text.
                    TSize lineExtents = textStyle->LineExtentsL(ptr);
                    extents.iWidth = Max(extents.iWidth, lineExtents.iWidth);
                    extents.iHeight += lineExtents.iHeight;                    
                    }

                	
        	    CleanupStack::PopAndDestroy(buf);
                break;
                }

            case ELineModeWrap:
                {
                // wrap lines to array
                HBufC* buf = CHuiStatic::ConvertToVisualAndWrapToArrayL(
                    logicalLine, maxWidth, *font, *linePtrs);
                CleanupStack::PushL(buf);

                // one line may create several wrapped lines
                lineCount += linePtrs->Count();

                if (aRasterizeFlags != ERasterizeNone)
                  	{    

                    // create new entries..
                    while (iLines.Count() < lineCount)
                        {
                        SRasterizedLine line;
                        line.iTexture = NULL;
                        line.iGap = 0;
                        iLines.AppendL(line);

                        if (iPictographInterface)
                            {
                            SRasterizedLine pictographline;
                            pictographline.iTexture = NULL;
                            pictographline.iGap = 0;
                            iPictographLines.AppendL(pictographline);                                
                            }
                        }
                    
                   	// Do rasterisation if we want to render to texture.
                    for(TInt i = 0; i < linePtrs->Count(); ++i)
                        {
                        TInt currentLine = (lineCount - linePtrs->Count()) + i;   
          	   	                
    	                if (aRasterizeFlags & ERasterizeText)
    	                    {
                            // rasterize a single line (updates texture in iLines[i].iTexture)
                            RasterizeLineL(linePtrs->At(i), iLines[currentLine]);
    	                    }
    	                    
	                    if (aRasterizeFlags & ERasterizePictographs && iPictographInterface)
	                        {
                            // Rasterize pictographs if needed
                            RasterizePictographLineL(linePtrs->At(i), font, iPictographLines[currentLine]);                                                                 	                            
	                        }
           	                // Get extents from the texture we just created
                            CHuiTexture* tex = iLines[i].iTexture;
                            extents.iHeight += iLines[i].iGap;
                            
                            if(tex)
                                {
                                extents.iWidth = Max(extents.iWidth, tex->Size().iWidth);
                                extents.iHeight += tex->Size().iHeight;
                                }    
                            	                                                         
    	                TBool moreAvailable = (currentLine + 1 < MaxLineCount());
                        if (!moreAvailable)
          	                {
       	                    // Maximum number of lines reached.
       	                    break;
       	                    }
                        }
                  	}
   	            else
   	                {
                    // Don't rasterise or create textures, just get the extents of this text.   	                    
                    for(TInt i = 0; i < linePtrs->Count(); ++i)
                        {  
                        TSize lineExtents = textStyle->LineExtentsL(linePtrs->At(i));
                        extents.iWidth = Max(extents.iWidth, lineExtents.iWidth);
                        extents.iHeight += lineExtents.iHeight;                                                              
                        }
       	            }
                	
                linePtrs->Reset();
                CleanupStack::PopAndDestroy(buf);
                break;
                }

            default:
                break;
            }

        // If we have reached the maximum number of lines, stop building.
        if(IsMaxLineCountReached())
            {
            break;
            }
        }

    HUI_DEBUG(_L("CHuiRasterizedTextMesh::BuildL() - Finished rasterizing text."));

    CleanupStack::PopAndDestroy(linePtrs); linePtrs = 0;

    if (iPictographBitmap)
        {
        iPictographBitmap->Resize(TSize(0, 0));
        }

    HUI_DEBUG(_L("CHuiRasterizedTextMesh::BuildL() - Updating text extents.."));
    // The extents of the mesh depend on how many lines there are.
    SetExtents(extents);

    HUI_DEBUG(_L("CHuiRasterizedTextMesh::BuildL() - Done!"));

    }
예제 #12
0
int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )

{
/* -------------------------------------------------------------------- */
/*      Do some rudimentary checking that this is a well formed         */
/*      node.                                                           */
/* -------------------------------------------------------------------- */
    if( psRoot == NULL 
        || psRoot->eType != CXT_Element 
        || !EQUAL(psRoot->pszValue,"GMLFeatureClass") )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "GMLFeatureClass::InitializeFromXML() called on %s node!",
                  psRoot->pszValue );
        return FALSE;
    }

    if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "GMLFeatureClass has no <Name> element." );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Collect base info.                                              */
/* -------------------------------------------------------------------- */
    CPLFree( m_pszName );
    m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) );
    
    SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) );

    const char *pszGPath = CPLGetXMLValue( psRoot, "GeometryElementPath", "" );
    
    if( strlen( pszGPath ) > 0 )
        SetGeometryElement( pszGPath );

    if( CPLGetXMLValue( psRoot, "GeometryType", NULL ) != NULL )
    {
        SetGeometryType( atoi(CPLGetXMLValue( psRoot, "GeometryType", NULL )) );
    }

/* -------------------------------------------------------------------- */
/*      Collect dataset specific info.                                  */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psDSI = CPLGetXMLNode( psRoot, "DatasetSpecificInfo" );
    if( psDSI != NULL )
    {
        const char *pszValue;

        pszValue = CPLGetXMLValue( psDSI, "FeatureCount", NULL );
        if( pszValue != NULL )
            SetFeatureCount( atoi(pszValue) );

        // Eventually we should support XML subtrees.
        pszValue = CPLGetXMLValue( psDSI, "ExtraInfo", NULL );
        if( pszValue != NULL )
            SetExtraInfo( pszValue );

        if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL 
            && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL
            && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL
            && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL )
        {
            SetExtents( atof(CPLGetXMLValue( psDSI, "ExtentXMin", "0.0" )),
                        atof(CPLGetXMLValue( psDSI, "ExtentXMax", "0.0" )),
                        atof(CPLGetXMLValue( psDSI, "ExtentYMin", "0.0" )),
                        atof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) );
        }
    }
    
/* -------------------------------------------------------------------- */
/*      Collect property definitions.                                   */
/* -------------------------------------------------------------------- */
    for( CPLXMLNode *psThis = psRoot->psChild;
         psThis != NULL; psThis = psThis->psNext )
    {
        if( EQUAL(psThis->pszValue, "PropertyDefn") )
        {
            const char *pszName = CPLGetXMLValue( psThis, "Name", NULL );
            const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" );
            GMLPropertyDefn *poPDefn;

            if( pszName == NULL )
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "GMLFeatureClass %s has a PropertyDefn without a <Name>..",
                          m_pszName );
                return FALSE;
            }

            poPDefn = new GMLPropertyDefn( 
                pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) );
            
            if( EQUAL(pszType,"Untyped") )
                poPDefn->SetType( GMLPT_Untyped );
            else if( EQUAL(pszType,"String") ) 
            {
                poPDefn->SetType( GMLPT_String );
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
            }
            else if( EQUAL(pszType,"Integer") )
            {
                poPDefn->SetType( GMLPT_Integer );
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
            }
            else if( EQUAL(pszType,"Real") )
            {
                poPDefn->SetType( GMLPT_Real );
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
                poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) );
            }
            else if( EQUAL(pszType,"StringList") ) 
                poPDefn->SetType( GMLPT_StringList );
            else if( EQUAL(pszType,"IntegerList") )
                poPDefn->SetType( GMLPT_IntegerList );
            else if( EQUAL(pszType,"RealList") )
                poPDefn->SetType( GMLPT_RealList );
            else if( EQUAL(pszType,"Complex") )
                poPDefn->SetType( GMLPT_Complex );
            else
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "Unrecognised property type %s.", 
                          pszType );
                return FALSE;
            }

            AddProperty( poPDefn );
        }
    }

    return TRUE;
}
예제 #13
0
 AARect::AARect(
    float minX, float minY,
    float maxX, float maxY)
 {
    SetExtents(minX, minY, maxX, maxY);
 }
예제 #14
0
 AARect::AARect(const Vector2 &min, const Vector2 &max)
 {
    SetExtents(min, max);
 }
예제 #15
0
 void AARect::Translate(const Vector2 &translation)
 {
    SetExtents(GetMinimum() + translation, GetMaximum() + translation);
 }
예제 #16
0
int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )

{
/* -------------------------------------------------------------------- */
/*      Do some rudimentary checking that this is a well formed         */
/*      node.                                                           */
/* -------------------------------------------------------------------- */
    if( psRoot == NULL 
        || psRoot->eType != CXT_Element 
        || !EQUAL(psRoot->pszValue,"GMLFeatureClass") )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "GMLFeatureClass::InitializeFromXML() called on %s node!",
                  psRoot->pszValue );
        return FALSE;
    }

    if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "GMLFeatureClass has no <Name> element." );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Collect base info.                                              */
/* -------------------------------------------------------------------- */
    CPLFree( m_pszName );
    m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) );
    n_nNameLen = strlen(m_pszName);

    SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) );

/* -------------------------------------------------------------------- */
/*      Collect geometry properties.                                    */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psThis;

    int bHasValidGeometryName = FALSE;
    int bHasValidGeometryElementPath = FALSE;
    int bHasFoundGeomType = FALSE;
    int bHasFoundGeomElements = FALSE;
    const char* pszGName = "";
    const char* pszGPath = "";
    int nGeomType = wkbUnknown;

    for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
    {
        if( psThis->eType == CXT_Element &&
            EQUAL(psThis->pszValue, "GeomPropertyDefn") )
        {
            const char *pszName = CPLGetXMLValue( psThis, "Name", "" );
            const char *pszElementPath = CPLGetXMLValue( psThis, "ElementPath", "" );
            const char *pszType = CPLGetXMLValue( psThis, "Type", NULL );
            int bNullable = CSLTestBoolean(CPLGetXMLValue( psThis, "Nullable", "true") );
            nGeomType = wkbUnknown;
            if( pszType != NULL && !EQUAL(pszType, "0") )
            {
                nGeomType = atoi(pszType);
                OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType);
                if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) )
                {
                    nGeomType = wkbUnknown;
                    CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
                            pszType);
                }
                else if( nGeomType == 0 )
                    nGeomType = OGRFromOGCGeomType(pszType);
            }
            bHasFoundGeomElements = TRUE;
            AddGeometryProperty( new GMLGeometryPropertyDefn( pszName, pszElementPath, nGeomType, -1, bNullable ) );
            bHasValidGeometryName = FALSE;
            bHasValidGeometryElementPath = FALSE;
            bHasFoundGeomType = FALSE;
        }
        else if( psThis->eType == CXT_Element &&
            strcmp(psThis->pszValue, "GeometryName") == 0 )
        {
            bHasFoundGeomElements = TRUE;

            if( bHasValidGeometryName )
            {
                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
                bHasValidGeometryName = FALSE;
                bHasValidGeometryElementPath = FALSE;
                bHasFoundGeomType = FALSE;
                pszGPath = "";
                nGeomType = wkbUnknown;
            }
            pszGName = CPLGetXMLValue( psThis, NULL, "" );
            bHasValidGeometryName = TRUE;
        }
        else if( psThis->eType == CXT_Element &&
            strcmp(psThis->pszValue, "GeometryElementPath") == 0 )
        {
            bHasFoundGeomElements = TRUE;

            if( bHasValidGeometryElementPath )
            {
                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
                bHasValidGeometryName = FALSE;
                bHasValidGeometryElementPath = FALSE;
                bHasFoundGeomType = FALSE;
                pszGName = "";
                nGeomType = wkbUnknown;
            }
            pszGPath = CPLGetXMLValue( psThis, NULL, "" );
            bHasValidGeometryElementPath = TRUE;
        }
        else if( psThis->eType == CXT_Element &&
                 strcmp(psThis->pszValue, "GeometryType") == 0 )
        {
            bHasFoundGeomElements = TRUE;

            if( bHasFoundGeomType )
            {
                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
                bHasValidGeometryName = FALSE;
                bHasValidGeometryElementPath = FALSE;
                bHasFoundGeomType = FALSE;
                pszGName = "";
                pszGPath = "";
                nGeomType = wkbUnknown;
            }
            const char* pszGeometryType = CPLGetXMLValue( psThis, NULL, NULL );
            nGeomType = wkbUnknown;
            if( pszGeometryType != NULL && !EQUAL(pszGeometryType, "0") )
            {
                nGeomType = atoi(pszGeometryType);
                OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType);
                if( nGeomType == 100 || EQUAL(pszGeometryType, "NONE") )
                {
                    bHasValidGeometryElementPath = FALSE;
                    bHasFoundGeomType = FALSE;
                    break;
                }
                else if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) )
                {
                    nGeomType = wkbUnknown;
                    CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
                            pszGeometryType);
                }
                else if( nGeomType == 0 )
                    nGeomType = OGRFromOGCGeomType(pszGeometryType);
            }
            bHasFoundGeomType = TRUE;
        }
    }

    /* If there was a dangling <GeometryElementPath> or <GeometryType> or */
    /* that no explicit geometry information has been found, then add */
    /* a geometry field */
    if( bHasValidGeometryElementPath || bHasFoundGeomType || !bHasFoundGeomElements )
    {
        AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
    }

    SetSRSName( CPLGetXMLValue( psRoot, "SRSName", NULL ) );

/* -------------------------------------------------------------------- */
/*      Collect dataset specific info.                                  */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psDSI = CPLGetXMLNode( psRoot, "DatasetSpecificInfo" );
    if( psDSI != NULL )
    {
        const char *pszValue;

        pszValue = CPLGetXMLValue( psDSI, "FeatureCount", NULL );
        if( pszValue != NULL )
            SetFeatureCount( CPLAtoGIntBig(pszValue) );

        // Eventually we should support XML subtrees.
        pszValue = CPLGetXMLValue( psDSI, "ExtraInfo", NULL );
        if( pszValue != NULL )
            SetExtraInfo( pszValue );

        if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL 
            && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL
            && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL
            && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL )
        {
            SetExtents( CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMin", "0.0" )),
                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMax", "0.0" )),
                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMin", "0.0" )),
                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) );
        }
    }
    
/* -------------------------------------------------------------------- */
/*      Collect property definitions.                                   */
/* -------------------------------------------------------------------- */
    for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
    {
        if( psThis->eType == CXT_Element &&
            EQUAL(psThis->pszValue, "PropertyDefn") )
        {
            const char *pszName = CPLGetXMLValue( psThis, "Name", NULL );
            const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" );
            const char *pszSubType = CPLGetXMLValue( psThis, "Subtype", "" );
            const char *pszCondition = CPLGetXMLValue( psThis, "Condition", NULL );
            int bNullable = CSLTestBoolean(CPLGetXMLValue( psThis, "Nullable", "true") );
            GMLPropertyDefn *poPDefn;

            if( pszName == NULL )
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "GMLFeatureClass %s has a PropertyDefn without a <Name>..",
                          m_pszName );
                return FALSE;
            }

            poPDefn = new GMLPropertyDefn( 
                pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) );
            
            poPDefn->SetNullable(bNullable);
            if( EQUAL(pszType,"Untyped") )
                poPDefn->SetType( GMLPT_Untyped );
            else if( EQUAL(pszType,"String") ) 
            {
                if( EQUAL(pszSubType, "Boolean") )
                {
                    poPDefn->SetType( GMLPT_Boolean );
                    poPDefn->SetWidth( 1 );
                }
                else
                {
                    poPDefn->SetType( GMLPT_String );
                    poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
                }
            }
            else if( EQUAL(pszType,"Integer") )
            {
                if( EQUAL(pszSubType, "Short") )
                {
                    poPDefn->SetType( GMLPT_Short );
                }
                else if( EQUAL(pszSubType, "Integer64") )
                {
                    poPDefn->SetType( GMLPT_Integer64 );
                }
                else
                {
                    poPDefn->SetType( GMLPT_Integer );
                }
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
            }
            else if( EQUAL(pszType,"Real") )
            {
                if( EQUAL(pszSubType, "Float") )
                {
                    poPDefn->SetType( GMLPT_Float );
                }
                else
                {
                    poPDefn->SetType( GMLPT_Real );
                }
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
                poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) );
            }
            else if( EQUAL(pszType,"StringList") ) 
            {
                if( EQUAL(pszSubType, "Boolean") )
                    poPDefn->SetType( GMLPT_BooleanList );
                else
                    poPDefn->SetType( GMLPT_StringList );
            }
            else if( EQUAL(pszType,"IntegerList") )
            {
                if( EQUAL(pszSubType, "Integer64") )
                    poPDefn->SetType( GMLPT_Integer64List );
                else
                    poPDefn->SetType( GMLPT_IntegerList );
            }
            else if( EQUAL(pszType,"RealList") )
                poPDefn->SetType( GMLPT_RealList );
            else if( EQUAL(pszType,"Complex") )
                poPDefn->SetType( GMLPT_Complex );
            else if( EQUAL(pszType,"FeatureProperty") )
                poPDefn->SetType( GMLPT_FeatureProperty );
            else if( EQUAL(pszType,"FeaturePropertyList") )
                poPDefn->SetType( GMLPT_FeaturePropertyList );
            else
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "Unrecognised property type %s.", 
                          pszType );
                delete poPDefn;
                return FALSE;
            }
            if( pszCondition != NULL )
                poPDefn->SetCondition(pszCondition);

            AddProperty( poPDefn );
        }
    }

    return TRUE;
}