// **************************************************************************** // // Function Name: RGraphicInterfaceImp::Load( ) // // Description: Read in the data into the associated Graphic.from // old Print Shop collection format // // Returns: Nothing // // Exceptions: kMemory, Disk Errors // // **************************************************************************** // void RGraphicInterfaceImp::Load( RStorage& storage, EGraphicType graphicType ) { RPsd3Graphic* pGraphic = RPsd3Graphic::CreateNewGraphic( graphicType ); uBYTE* pGraphicData ; uLONG uGraphicDataSize ; BOOLEAN fMonochrome ; const int kMonochromeOffset = 16 ; storage.SeekRelative( kMonochromeOffset ) ; storage >> fMonochrome ; storage.SeekRelative( 3 ) ; // Gets us to graphic size storage >> uGraphicDataSize ; uLONG uThumbnailSize ; // Skip past the thumbnail storage >> uThumbnailSize ; storage.SeekRelative( uThumbnailSize ) ; pGraphicData = storage.GetStorageStream()->GetBuffer( uGraphicDataSize ) ; pGraphic->Load( pGraphicData, uGraphicDataSize, fMonochrome ) ; m_pGraphicDocument->SetGraphic( dynamic_cast<RGraphic*>( pGraphic ) ); }
// **************************************************************************** // // Function Name: RGraphicInterfaceImp::Load( ) // // Description: Read in the data into the associated Graphic from // a raw data stream. // // Returns: Nothing // // Exceptions: kMemory, Disk Errors // // **************************************************************************** // void RGraphicInterfaceImp::Load( RStorage& storage, uLONG uLength, EGraphicType graphicType ) { RPsd3Graphic* pGraphic = RPsd3Graphic::CreateNewGraphic( graphicType ); uBYTE* pGraphicData = storage.GetStorageStream()->GetBuffer( uLength ); pGraphic->Load( pGraphicData, uLength, FALSE ); m_pGraphicDocument->SetGraphic( dynamic_cast<RGraphic*>( pGraphic ) ); }
// **************************************************************************** // // Function Name: RMergeData::ReadTabDelimitedString( ) // // Description: Read a string that is tab delimited from the storage. // Eat the delimeter character also (eof, cr/lf, tab). // // Returns: Nothing // // Exceptions: Any File Exception, will not send through on kEndOfFile // // **************************************************************************** // RMergeData::EDataDelimiter RMergeData::ReadTabDelimitedString( RStorage& storage, RMBCString& string ) { EDataDelimiter delimiter = kTab; try { uBYTE ubChar( 0 ); RCharacter character; // First, make sure the string is empty string.Empty( ); // Loop until I hit a EOF, TAB, CR, or LF while ( 1 ) { storage >> ubChar; if ( (ubChar == '\t') || (ubChar == '\r') || (ubChar == '\n') ) break; // Check for multi-Byte character = ubChar; if ( character.IsLead( ) ) { UntestedCode( ); uBYTE lead = ubChar; uBYTE trail; storage >> trail; character = RCharacter( lead, trail ); } string += character; } // If I found a CR or a LF, make sure the other is not also present. if ( (ubChar == '\r') || (ubChar == '\n') ) { storage >> ubChar; // If character is NOT a CR or LF, rewind one character if ( !((ubChar == '\r') || (ubChar == '\n')) ) storage.SeekRelative( -1 ); delimiter = kEOL; }
/** * Adds the given object to the transaction. Adding an object to a * transaction means that this transaction modifies or adds the object. * Entities that are added with an invalid layer or block ID are placed * on the current layer / block. * * @param modifiedPropertyTypeId: Property ID that has changed if known * by caller, NULL otherwise. */ bool RTransaction::addObject(QSharedPointer<RObject> object, bool useCurrentAttributes, bool forceNew, const QSet<RPropertyTypeId>& modifiedPropertyTypeIds) { if (object.isNull()) { qWarning() << "RTransaction::addObject: object is NULL"; fail(); return false; } if (storage == NULL) { qWarning() << "RTransaction::addObject: storage is NULL"; fail(); return false; } if (transactionId != -1) { qWarning() << "RTransaction::addObject: " "Trying to add object to an existing transaction. " "Transactions are immutable once committed."; fail(); Q_ASSERT(false); return false; } if (object->getDocument()==NULL) { qWarning() << "RTransaction::addObject: " "Object is not linked to a document."; fail(); Q_ASSERT(false); return false; } RObject::Id oldId = RObject::INVALID_ID; if (forceNew) { oldId=object->getId(); if (object->getId()!=RObject::INVALID_ID) { storage->setObjectId(*object, RObject::INVALID_ID); } if (object->getHandle()!=RObject::INVALID_ID) { storage->setObjectHandle(*object, RObject::INVALID_HANDLE); } } RLinkedStorage* ls = dynamic_cast<RLinkedStorage*>(storage); bool storageIsLinked = (ls!=NULL); RStorage* objectStorage = &object->getDocument()->getStorage(); if (objectStorage==NULL) { qWarning() << "RTransaction::addObject: " "Object storage is NULL."; fail(); Q_ASSERT(false); return false; } if (storageIsLinked && objectStorage!=ls && objectStorage!=ls->getBackStorage()) { qWarning() << "RTransaction::addObject: " "Object is not in linked storage or back storage of transaction."; fail(); Q_ASSERT(false); return false; } if (!storageIsLinked && objectStorage!=storage) { qWarning() << "RTransaction::addObject: " "Object is not in storage of transaction."; fail(); Q_ASSERT(false); return false; } // TODO: add generic way to allow any object not to be cloned here: // i.e. if (object.cloneInsteadOfUpdate()) { ... } // QSharedPointer<RLinetype> lt = object.dynamicCast<RLinetype>(); // if (!lt.isNull() && lt->getId()!=RObject::INVALID_ID) { // qDebug() << "replace linetype"; // QSharedPointer<RLinetype> clone = QSharedPointer<RLinetype>(lt->clone()); // objectStorage->setObjectId(*clone, RObject::INVALID_ID); // deleteObject(lt->getId()); // addObject(clone, useCurrentAttributes, false, modifiedPropertyTypeIds); // return true; // } QSharedPointer<REntity> entity = object.dynamicCast<REntity>(); bool mustClone = false; if (!entity.isNull() && entity->getId()!=REntity::INVALID_ID) { QSharedPointer<REntity> oldEntity = storage->queryEntityDirect(entity->getId()); if (!oldEntity.isNull()) { // object is entity and not new: if (oldEntity->cloneOnChange()) { mustClone = true; } } if (!mustClone) { if (entity->getType()==RS::EntityHatch && modifiedPropertyTypeIds.isEmpty()) { // entity is hatch and not only property has changed: mustClone = true; } } } // if object is an existing hatch and we are not just changing a property: // delete original and add new since hatch geometry cannot be completely // defined through properties which is a requirement for changing objects // through transactions: if (mustClone) { QSharedPointer<REntity> clone = QSharedPointer<REntity>(entity->clone()); objectStorage->setObjectId(*clone, REntity::INVALID_ID); // note that we delete the OLD entity here // (old entity is queried from storage since we pass the ID here): deleteObject(entity->getId()); addObject(clone, useCurrentAttributes, false, modifiedPropertyTypeIds); // draw order was set to top value automatically by // saveObject of RMemoryStorage: clone->setDrawOrder(entity->getDrawOrder()); return true; } // if object is an entity, // place entity on current layer / block, set current pen attributes: if (!entity.isNull()) { if (useCurrentAttributes || entity->getLayerId()==RLayer::INVALID_ID) { entity->setLayerId(object->getDocument()->getCurrentLayerId()); } if (useCurrentAttributes || entity->getBlockId()==RBlock::INVALID_ID) { entity->setBlockId(object->getDocument()->getCurrentBlockId()); } if (useCurrentAttributes || !entity->getColor().isValid()) { entity->setColor(object->getDocument()->getCurrentColor()); } if (useCurrentAttributes || entity->getLineweight()==RLineweight::WeightInvalid) { entity->setLineweight(object->getDocument()->getCurrentLineweight()); } if (useCurrentAttributes || entity->getLinetypeId()==RLinetype::INVALID_ID) { entity->setLinetypeId(object->getDocument()->getCurrentLinetypeId()); } // allowAll to make sure entities on hidden / locked layers can be imported: if (!allowAll && !entity->isEditable(allowInvisible)) { qWarning() << "RTransaction::addObject: entity not editable (locked or hidden layer)"; fail(); return false; } Q_ASSERT_X(!object->getDocument()->queryLayerDirect(entity->getLayerId()).isNull(), "RTransaction::addObject", "layer of entity is NULL"); } // if object is a block definition, // look up existing block based on case insensitive name comparison: bool objectIsBlock = false; QSharedPointer<RBlock> block = object.dynamicCast<RBlock>(); if (!block.isNull()) { objectIsBlock = true; if (!existingBlockDetectionDisabled) { QSharedPointer<RBlock> existingBlock = block->getDocument()->queryBlock(block->getName()); if (!existingBlock.isNull()) { storage->setObjectId(*block, existingBlock->getId()); } } } // if object is a layer, // look up existing layer based on case insensitive name comparison: if (!existingLayerDetectionDisabled && object->getId()==RObject::INVALID_ID) { QSharedPointer<RLayer> layer = object.dynamicCast<RLayer>(); if (!layer.isNull()) { QSharedPointer<RLayer> existingLayer = layer->getDocument()->queryLayer(layer->getName()); if (!existingLayer.isNull()) { storage->setObjectId(*layer, existingLayer->getId()); } } } // if object is a linetype, // look up existing linetype based on case insensitive name comparison: if (!existingLinetypeDetectionDisabled && object->getId()==RObject::INVALID_ID) { QSharedPointer<RLinetype> linetype = object.dynamicCast<RLinetype>(); if (!linetype.isNull()) { QSharedPointer<RLinetype> existingLinetype = linetype->getDocument()->queryLinetype(linetype->getName()); if (!existingLinetype.isNull()) { storage->setObjectId(*linetype, existingLinetype->getId()); } } } bool objectHasChanged = false; QSharedPointer<RObject> oldObject; // object is an existing object that might have changed: if (object->getId() != RObject::INVALID_ID) { // store diff between previous object and this object // as part of this transaction: oldObject = storage->queryObjectDirect(object->getId()); if (oldObject.isNull()) { qWarning() << "RTransaction::addObject: original object not found in storage for " << *object; fail(); return false; } if (typeid(*oldObject) != typeid(*object)) { qWarning("RTransaction::addObject: " "type of original object and " "type of modified object don't match"); fail(); return false; } if (oldObject->getId() != object->getId()) { qWarning("RTransaction::addObject: " "id of original object and " "id of modified object don't match"); fail(); return false; } //qDebug() << "old obj: " << *oldObject; //qDebug() << "new obj: " << *object; // iterate through all properties of the original object // and store the property changes (if any) in this transaction: QSet<RPropertyTypeId> propertyTypeIds; if (modifiedPropertyTypeIds.isEmpty()) { propertyTypeIds = object->getPropertyTypeIds(); } else { propertyTypeIds = modifiedPropertyTypeIds; // if at least one property is a redundant property, we need to // check all properties for changes: bool all = false; QSet<RPropertyTypeId>::iterator it; for (it=propertyTypeIds.begin(); it!=propertyTypeIds.end(); ++it) { RPropertyTypeId pid = *it; QPair<QVariant, RPropertyAttributes> newProperty = object->getProperty(pid); // redundant properties affect other properties: if (newProperty.second.isRedundant()) { all = true; break; } } if (all) { propertyTypeIds = object->getPropertyTypeIds(); } } propertyTypeIds.unite(object->getCustomPropertyTypeIds()); propertyTypeIds.unite(oldObject->getCustomPropertyTypeIds()); QSet<RPropertyTypeId>::iterator it; for (it=propertyTypeIds.begin(); it!=propertyTypeIds.end(); ++it) { RPropertyTypeId pid = *it; QPair<QVariant, RPropertyAttributes> newProperty = object->getProperty(pid); QPair<QVariant, RPropertyAttributes> oldProperty = oldObject->getProperty(pid); // if (pid==RObject::PropertyProtected) { // qDebug() << "pid: " << pid; // qDebug() << "old property: " << oldProperty.first; // qDebug() << "new property: " << newProperty.first; // } // don't record changes in redundant properties (e.g. angle for lines): if (newProperty.second.isRedundant()) { continue; } // property that has changed affects the visibility of // other attributes: if (newProperty.second.affectsOtherProperties()) { onlyChanges = false; } objectHasChanged |= addPropertyChange( object->getId(), RPropertyChange( *it, oldProperty.first, newProperty.first ) ); } if (objectHasChanged) { // remove old entity from storage (only if it has actually changed): storage->removeObject(oldObject); if (object->getDocument()!=NULL) { // only remove from si, if not linked storage / preview if (!storage->isInBackStorage(oldObject->getId())) { QSharedPointer<REntity> oldEntity = oldObject.dynamicCast<REntity>(); if (!spatialIndexDisabled && !oldEntity.isNull()) { QSharedPointer<RBlockReferenceEntity> blockRef = oldEntity.dynamicCast<RBlockReferenceEntity>(); if (blockRef.isNull() || blockRef->getReferencedBlockId()!=RObject::INVALID_ID) { object->getDocument()->removeFromSpatialIndex(oldEntity); } } } } } } bool ret = true; // object is a new object or an existing object that has changed: if (object->getId()==RObject::INVALID_ID || objectHasChanged || // always add block to linked storage to make sure that // block entities are found in linked storage: (objectIsBlock && storageIsLinked)) { // new object: if (object->getId()==RObject::INVALID_ID) { onlyChanges = false; } ret = storage->saveObject(object, !blockRecursionDetectionDisabled, keepHandles); if (!ret) { qCritical() << "RTransaction::addObject: saveObject() failed for object: "; qCritical() << *object; } else { if (oldId!=RObject::INVALID_ID) { cloneIds.insert(oldId, object->getId()); } addAffectedObject(object); if (object->getDocument()!=NULL) { // only add to si, if not linked storage / preview if (!storageIsLinked) { QSharedPointer<REntity> entity = object.dynamicCast<REntity>(); if (!spatialIndexDisabled && !entity.isNull()) { QSharedPointer<RBlockReferenceEntity> blockRef = entity.dynamicCast<RBlockReferenceEntity>(); if (blockRef.isNull() || blockRef->getReferencedBlockId()!=RObject::INVALID_ID) { object->getDocument()->addToSpatialIndex(entity); } // update block references if entity has been changed inside a block // that is not the current block (in block editing): if (entity->getBlockId()!=storage->getCurrentBlockId()) { affectedBlockReferenceIds.unite(storage->queryBlockReferences(entity->getBlockId())); } } } } if (!objectHasChanged) { statusChanges.insert(object->getId()); } } } if (!ret) { fail(); } return ret; }
/** * Stream operator for QDebug */ QDebug operator<<(QDebug dbg, RStorage& s) { dbg.nospace() << "RStorage(" << QString("%1").arg((long int)&s, 0, 16) << ", "; dbg.nospace() << "\n"; //dbg.nospace() << "current block ID: " << s.getCurrentBlockId() << "\n"; dbg.nospace() << "modified: " << s.isModified() << "\n"; QSharedPointer<RBlock> block = s.queryCurrentBlock(); if (block.isNull()) { dbg.nospace() << "current block: INVALID\n"; } else { dbg.nospace() << "current block: " << block->getName() << "\n"; } //dbg.nospace() << "current layer ID: " << s.getCurrentLayerId() << "\n"; QSharedPointer<RLayer> layer = s.queryCurrentLayer(); if (layer.isNull()) { dbg.nospace() << "current layer: INVALID\n"; } else { dbg.nospace() << "current layer: " << layer->getName() << "\n"; } dbg.nospace() << "current view ID: " << s.getCurrentViewId() << "\n"; QSharedPointer<RLinetype> linetype = s.queryCurrentLinetype(); if (linetype.isNull()) { dbg.nospace() << "current linetype: INVALID\n"; } else { dbg.nospace() << "current linetype: " << linetype->getName() << "\n"; } dbg.nospace() << "drawing unit: " << s.getUnit() << "\n"; dbg.nospace() << "dimension font: " << s.getDimensionFont() << "\n"; dbg.nospace() << "bounding box: " << s.getBoundingBox() << "\n"; dbg.nospace() << "document variables: " << *s.queryDocumentVariables() << "\n"; { QSet<RLayer::Id> layers = s.queryAllLayers(true); QSetIterator<RLayer::Id> i(layers); while (i.hasNext()) { RLayer::Id id = i.next(); QSharedPointer<RLayer> l = s.queryObjectDirect(id).dynamicCast<RLayer>(); if (l.isNull()) { dbg.nospace() << "layer not found: " << id; continue; } dbg.nospace() << *l.data() << "\n"; } } { QSet<RView::Id> views = s.queryAllViews(true); QSetIterator<RView::Id> i(views); while (i.hasNext()) { RView::Id id = i.next(); QSharedPointer<RView> v = s.queryObjectDirect(id).dynamicCast<RView>(); if (v.isNull()) { dbg.nospace() << "view not found: " << id; continue; } dbg.nospace() << *v.data() << "\n"; } } { QSet<RBlock::Id> blocks = s.queryAllBlocks(true); QSetIterator<RBlock::Id> i(blocks); while (i.hasNext()) { RBlock::Id id = i.next(); QSharedPointer<RBlock> b = s.queryObjectDirect(id).dynamicCast<RBlock>(); if (b.isNull()) { dbg.nospace() << "block not found: " << id; continue; } dbg.nospace() << *b.data() << "\n"; dbg.nospace() << "block entities: " << s.queryBlockEntities(id) << "\n"; } } { QSet<RLinetype::Id> linetypes = s.queryAllLinetypes(); QSetIterator<RLinetype::Id> i(linetypes); while (i.hasNext()) { RLinetype::Id id = i.next(); QSharedPointer<RLinetype> l = s.queryObjectDirect(id).dynamicCast<RLinetype>(); if (l.isNull()) { dbg.nospace() << "linetype not found: " << id; continue; } dbg.nospace() << *l.data() << "\n"; } } { QSet<REntity::Id> entities = s.querySelectedEntities(); if (entities.size()==0) { entities = s.queryAllEntities(true, true); } QSetIterator<REntity::Id> i(entities); while (i.hasNext()) { REntity::Id id = i.next(); QSharedPointer<REntity> e = s.queryObjectDirect(id).dynamicCast<REntity>(); if (e.isNull()) { dbg.nospace() << "entity not found: " << id; continue; } dbg.nospace() << "Bounding Box: " << e->getBoundingBox() << "\n"; dbg.nospace() << *e.data() << "\n\n"; } } dbg.nospace() << "lastTransactionId: " << s.getLastTransactionId() << "\n"; for (int a = 0; a <= s.getMaxTransactionId(); ++a) { RTransaction t = s.getTransaction(a); dbg.nospace() << t << "\n"; } dbg.nospace() << "variables: \n"; { QStringList vars = s.getVariables(); vars.sort(); QListIterator<QString> i(vars); while (i.hasNext()) { QString key = i.next(); dbg.nospace() << "\t" << key << ": " << s.getVariable(key) << "\n"; } } dbg.nospace() << "Known variables (DXF): \n"; { for (int i=0; i<=RS::MaxKnownVariable; i++) { QVariant v = s.getKnownVariable((RS::KnownVariable)i); if (v.isValid()) { dbg.nospace() << "\t" << RStorage::getKnownVariableName((RS::KnownVariable)i) << ": " << v << "\n"; } } } dbg.nospace() << ")"; return dbg.space(); }
// **************************************************************************** // // Function Name: RGraphicInterfaceImp::LoadFromPretzelCollection( ) // // Description: Read in the data into the associated Graphic.from // Print Shop library-of-one format // // Returns: Nothing // // Exceptions: kMemory, Disk Errors // // **************************************************************************** // void RGraphicInterfaceImp::LoadFromPretzelCollection( RStorage& storage, EGraphicType graphicType ) { // save current compiler struct packing setting, set to 1 (each member on byte boundary) #pragma pack( push, 1 ) struct DS_LIBHEAD { char FileIdentifier[16]; // file verification---NOT NULL TERMINATED! char LibraryName[32]; // Name of library---NOT NULL TERMINATED! short FileID; // unique file identifier short Machine; // machine signature char Type; // type of file---this is often inaccurate so do not use char Subtype; // type of graphics in file (we no longer use) short Count; // number of graphics in file short LayoutClassSize; // size of class info array (layout only) short LayoutCount; // number of layouts in file (layout only) char DriverName[8]; // driver on which bitmaps were made (DOS platform only) char CreatedByBB; // library was created by Broderbund char unused; long magicNumber; // new for version 3.0---confirms library is 3.x char versionLo; // new for version 3.0 char versionHi; // new for version 3.0 long keywordOffset; // new for version 3.0---reads in keywords until end of file char reserved[48]; // remainder of 128 bytes }; struct DS_GRAPHICINFO { char Name[32]; // name of graphic---NOT NULL TERMINATED! long GraphiclD; // unique graphic identifier long GraphicSize; // graphic size long BitmapSize; // bitmap size char GraphicCompress; // compression scheme for graphics char BitmapCompress; // compression scheme for bitmaps char MonoFlag; // True if monochrome graphic char Screening; // default screening value, 0-100 char BackdropType; // backdrop subtypes char reserved; short ProjectCode; // project use code }; // restore compiler struct packing setting #pragma pack( pop ) uLONG uGraphicSize; const int kGraphicSizeOffset = sizeof(DS_LIBHEAD) + 36; storage.SeekRelative( kGraphicSizeOffset ); storage >> uGraphicSize; BOOLEAN fMonochrome; const int kMonochromeOffset = 6; storage.SeekRelative( kMonochromeOffset ); storage >> fMonochrome; const int kSkipRemainder = 5; storage.SeekRelative( kSkipRemainder ); uBYTE* pGraphicData = storage.GetStorageStream()->GetBuffer( uGraphicSize ); RPsd3Graphic* pGraphic = RPsd3Graphic::CreateNewGraphic( graphicType ); pGraphic->Load( pGraphicData, uGraphicSize, fMonochrome ); m_pGraphicDocument->SetGraphic( dynamic_cast<RGraphic*>( pGraphic ) ); }