about summary refs log tree commit diff
path: root/docs/tool/Modules/NaturalDocs/ImageReferenceTable.pm
diff options
context:
space:
mode:
Diffstat (limited to 'docs/tool/Modules/NaturalDocs/ImageReferenceTable.pm')
-rw-r--r--docs/tool/Modules/NaturalDocs/ImageReferenceTable.pm383
1 files changed, 383 insertions, 0 deletions
diff --git a/docs/tool/Modules/NaturalDocs/ImageReferenceTable.pm b/docs/tool/Modules/NaturalDocs/ImageReferenceTable.pm
new file mode 100644
index 00000000..8f13ce5f
--- /dev/null
+++ b/docs/tool/Modules/NaturalDocs/ImageReferenceTable.pm
@@ -0,0 +1,383 @@
+###############################################################################
+#
+#   Package: NaturalDocs::ImageReferenceTable
+#
+###############################################################################
+#
+#   A <NaturalDocs::SourceDB>-based package that manages all the image references appearing in source files.
+#
+###############################################################################
+
+# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
+# Natural Docs is licensed under the GPL
+
+use strict;
+use integer;
+
+use NaturalDocs::ImageReferenceTable::String;
+use NaturalDocs::ImageReferenceTable::Reference;
+
+
+package NaturalDocs::ImageReferenceTable;
+
+use base 'NaturalDocs::SourceDB::Extension';
+
+
+###############################################################################
+# Group: Information
+
+#
+#   Topic: Usage
+#
+#       - <NaturalDocs::Project> and <NaturalDocs::SourceDB> must be initialized before this package can be used.
+#
+#       - Call <Register()> before using.
+#
+#
+#   Topic: Programming Notes
+#
+#       When working on this code, remember that there are three things it has to juggle.
+#
+#       - The information in <NaturalDocs::SourceDB>.
+#       - Image file references in <NaturalDocs::Project>.
+#       - Source file rebuilding on changes.
+#
+#       Managing the actual image files will be handled between <NaturalDocs::Project> and the <NaturalDocs::Builder>
+#       sub-packages.
+#
+#
+#   Topic: Implementation
+#
+#       Managing image references is simpler than managing the references in <NaturalDocs::SymbolTable>.  In SymbolTable,
+#       you have to worry about reference targets popping into and out of existence.  A link may go to a file that hasn't been
+#       reparsed yet and the target may no longer exist.  We have to deal with that when we know it, which may be after the
+#       reference's file was parsed.  Also, a new definition may appear that serves as a better interpretation of a link than its
+#       current target, and again we may only know that after the reference's file has been parsed already.  So we have to deal
+#       with scores and potential symbols and each symbol knowing exactly what links to it and so forth.
+#
+#       Not so with image references.  All possible targets (all possible image files) are known by <NaturalDocs::Project> early
+#       on and will remain consistent throughout execution.  So because of that, we can get away with only storing reference
+#       counts with each image and determining exactly where a reference points to as we find them.
+#
+#       Reference counts are stored with the image file information in <NaturalDocs::Project>.  However, it is not loaded and
+#       saved to disk by it.  Rather, it is regenerated by this package when it loads <ImageReferenceTable.nd>.
+#       NaturalDocs::Project only stores the last modification time (so it can add files to the build list if they've changed) and
+#       whether it had any references at all on the last run (so it knows whether it should care if they've changed.)
+#       ImageReferenceTable.nd stores each reference's target, width, and height.  Whether their interpretations have changed is
+#       dealt with in the <Load()> function, again since the list of targets (image files) is constant.
+#
+#       The package is based on <NaturalDocs::SourceDB>, so read it's documentation for more information on how it works.
+#
+
+
+###############################################################################
+# Group: Variables
+
+
+#
+#   var: extensionID
+#   The <ExtensionID> granted by <NaturalDocs::SourceDB>.
+#
+my $extensionID;
+
+
+
+###############################################################################
+# Group: Files
+
+
+#
+#   File: ImageReferenceTable.nd
+#
+#   The data file which stores all the image references from the last run of Natural Docs.
+#
+#   Format:
+#
+#       > [Standard Binary Header]
+#
+#       It starts with the standard binary header from <NaturalDocs::BinaryFile>.
+#
+#       > [Image Reference String or undef]
+#       > [AString16: target file]
+#       > [UInt16: target width or 0]
+#       > [UInt16: target height or 0]
+#
+#       For each <ImageReferenceString>, it's target, width, and height are stored.  The target is needed so we can tell if it
+#       changed from the last run, and the dimensions are needed because if the target hasn't changed but the file's dimensions
+#       have, the source files need to be rebuilt.
+#
+#       <ImageReferenceStrings> are encoded by <NaturalDocs::ImageReferenceTable::String>.
+#
+#       > [AString16: definition file or undef] ...
+#
+#       Then comes a series of AString16s for all the files that define the reference until it hits an undef.
+#
+#       This whole series is repeated for each <ImageReferenceString> until it hits an undef.
+#
+#	Revisions:
+#
+#		1.4:
+#
+#			- The file was added to Natural Docs.
+#
+
+
+
+###############################################################################
+# Group: Functions
+
+
+#
+#   Function: Register
+#   Registers the package with <NaturalDocs::SourceDB>.
+#
+sub Register
+    {
+    my $self = shift;
+    $extensionID = NaturalDocs::SourceDB->RegisterExtension($self, 0);
+    };
+
+
+#
+#   Function: Load
+#
+#   Loads the data from <ImageReferenceTable.nd>.  Returns whether it was successful.
+#
+sub Load # => bool
+    {
+    my $self = shift;
+
+    if (NaturalDocs::Settings->RebuildData())
+        {  return 0;  };
+
+    # The file format hasn't changed since it was introduced.
+    if (!NaturalDocs::BinaryFile->OpenForReading( NaturalDocs::Project->DataFile('ImageReferenceTable.nd') ))
+        {  return 0;  };
+
+
+    # [Image Reference String or undef]
+    while (my $referenceString = NaturalDocs::ImageReferenceTable::String->FromBinaryFile())
+        {
+        NaturalDocs::SourceDB->AddItem($extensionID, $referenceString,
+                                                           NaturalDocs::ImageReferenceTable::Reference->New());
+
+        # [AString16: target file]
+        # [UInt16: target width or 0]
+        # [UInt16: target height or 0]
+
+        my $targetFile = NaturalDocs::BinaryFile->GetAString16();
+        my $width = NaturalDocs::BinaryFile->GetUInt16();
+        my $height = NaturalDocs::BinaryFile->GetUInt16();
+
+        my $newTargetFile = $self->SetReferenceTarget($referenceString);
+        my $newWidth;
+        my $newHeight;
+
+        if ($newTargetFile)
+            {
+            NaturalDocs::Project->AddImageFileReference($newTargetFile);
+            ($newWidth, $newHeight) = NaturalDocs::Project->ImageFileDimensions($newTargetFile);
+            };
+
+        my $rebuildDefinitions = ($newTargetFile ne $targetFile || $newWidth != $width || $newHeight != $height);
+
+
+        # [AString16: definition file or undef] ...
+        while (my $definitionFile = NaturalDocs::BinaryFile->GetAString16())
+            {
+            NaturalDocs::SourceDB->AddDefinition($extensionID, $referenceString, $definitionFile);
+
+            if ($rebuildDefinitions)
+                {  NaturalDocs::Project->RebuildFile($definitionFile);  };
+            };
+        };
+
+
+    NaturalDocs::BinaryFile->Close();
+    return 1;
+    };
+
+
+#
+#   Function: Save
+#
+#   Saves the data to <ImageReferenceTable.nd>.
+#
+sub Save
+    {
+    my $self = shift;
+
+    my $references = NaturalDocs::SourceDB->GetAllItemsHashRef($extensionID);
+
+    NaturalDocs::BinaryFile->OpenForWriting( NaturalDocs::Project->DataFile('ImageReferenceTable.nd') );
+
+    while (my ($referenceString, $referenceObject) = each %$references)
+        {
+        # [Image Reference String or undef]
+        # [AString16: target file]
+        # [UInt16: target width or 0]
+        # [UInt16: target height or 0]
+
+        NaturalDocs::ImageReferenceTable::String->ToBinaryFile($referenceString);
+
+        my $target = $referenceObject->Target();
+        my ($width, $height);
+
+        if ($target)
+            {  ($width, $height) = NaturalDocs::Project->ImageFileDimensions($target);  };
+
+        NaturalDocs::BinaryFile->WriteAString16( $referenceObject->Target() );
+        NaturalDocs::BinaryFile->WriteUInt16( ($width || 0) );
+        NaturalDocs::BinaryFile->WriteUInt16( ($height || 0) );
+
+        # [AString16: definition file or undef] ...
+
+        my $definitions = $referenceObject->GetAllDefinitionsHashRef();
+
+        foreach my $definition (keys %$definitions)
+            {  NaturalDocs::BinaryFile->WriteAString16($definition);  };
+
+        NaturalDocs::BinaryFile->WriteAString16(undef);
+        };
+
+    NaturalDocs::ImageReferenceTable::String->ToBinaryFile(undef);
+
+    NaturalDocs::BinaryFile->Close();
+    };
+
+
+#
+#   Function: AddReference
+#
+#   Adds a new image reference.
+#
+sub AddReference #(FileName file, string referenceText)
+    {
+    my ($self, $file, $referenceText) = @_;
+
+    my $referenceString = NaturalDocs::ImageReferenceTable::String->Make($file, $referenceText);
+
+    if (!NaturalDocs::SourceDB->HasItem($extensionID, $referenceString))
+        {
+        my $referenceObject = NaturalDocs::ImageReferenceTable::Reference->New();
+        NaturalDocs::SourceDB->AddItem($extensionID, $referenceString, $referenceObject);
+
+        my $target = $self->SetReferenceTarget($referenceString);
+        if ($target)
+            {  NaturalDocs::Project->AddImageFileReference($target);  };
+        };
+
+    NaturalDocs::SourceDB->AddDefinition($extensionID, $referenceString, $file);
+    };
+
+
+#
+#   Function: OnDeletedDefinition
+#
+#   Called for each definition deleted by <NaturalDocs::SourceDB>.  This is called *after* the definition has been deleted from
+#   the database, so don't expect to be able to read it.
+#
+sub OnDeletedDefinition #(ImageReferenceString referenceString, FileName file, bool wasLastDefinition)
+    {
+    my ($self, $referenceString, $file, $wasLastDefinition) = @_;
+
+    if ($wasLastDefinition)
+        {
+        my $referenceObject = NaturalDocs::SourceDB->GetItem($extensionID, $referenceString);
+        my $target = $referenceObject->Target();
+
+        if ($target)
+            {  NaturalDocs::Project->DeleteImageFileReference($target);  };
+
+        NaturalDocs::SourceDB->DeleteItem($extensionID, $referenceString);
+        };
+    };
+
+
+#
+#   Function: GetReferenceTarget
+#
+#   Returns the image file the reference resolves to, or undef if none.
+#
+#   Parameters:
+#
+#       sourceFile - The source <FileName> the reference appears in.
+#       text - The reference text.
+#
+sub GetReferenceTarget #(FileName sourceFile, string text) => FileName
+    {
+    my ($self, $sourceFile, $text) = @_;
+
+    my $referenceString = NaturalDocs::ImageReferenceTable::String->Make($sourceFile, $text);
+    my $reference = NaturalDocs::SourceDB->GetItem($extensionID, $referenceString);
+
+    if (!defined $reference)
+        {  return undef;  }
+    else
+        {  return $reference->Target();  };
+    };
+
+
+#
+#   Function: SetReferenceTarget
+#
+#   Determines the best target for the passed <ImageReferenceString> and sets it on the
+#   <NaturalDocs::ImageReferenceTable::Reference> object.  Returns the new target <FileName>.  Does *not* add any source
+#   files to the bulid list.
+#
+sub SetReferenceTarget #(ImageReferenceString referenceString) => FileName
+    {
+    my ($self, $referenceString) = @_;
+
+    my $referenceObject = NaturalDocs::SourceDB->GetItem($extensionID, $referenceString);
+    my ($sourcePath, $text) = NaturalDocs::ImageReferenceTable::String->InformationOf($referenceString);
+
+
+    # Try the path relative to the source file first.
+
+    my $target;
+
+    my $imageFile = NaturalDocs::File->JoinPaths($sourcePath, $text);
+    my $exists = NaturalDocs::Project->ImageFileExists($imageFile);
+
+
+    # Then try relative image directories.
+
+    if (!$exists)
+        {
+        my $relativeImageDirectories = NaturalDocs::Settings->RelativeImageDirectories();
+
+        for (my $i = 0; $i < scalar @$relativeImageDirectories && !$exists; $i++)
+            {
+            $imageFile = NaturalDocs::File->JoinPaths($sourcePath, $relativeImageDirectories->[$i], 1);
+            $imageFile = NaturalDocs::File->JoinPaths($imageFile, $text);
+
+            $exists = NaturalDocs::Project->ImageFileExists($imageFile);
+            };
+        };
+
+
+    # Then try absolute image directories.
+
+    if (!$exists)
+        {
+        my $imageDirectories = NaturalDocs::Settings->ImageDirectories();
+
+        for (my $i = 0; $i < scalar @$imageDirectories && !$exists; $i++)
+            {
+            $imageFile = NaturalDocs::File->JoinPaths($imageDirectories->[$i], $text);
+            $exists = NaturalDocs::Project->ImageFileExists($imageFile);
+            };
+        };
+
+
+    if ($exists)
+        {  $target = NaturalDocs::Project->ImageFileCapitalization($imageFile);  };
+    #else leave it as undef.
+
+    $referenceObject->SetTarget($target);
+    return $target;
+    };
+
+
+1;