public function visitTextFrame(IdmlTextFrame $element, $outer_depth = 0) { // For the outermost TextFrame whose parent is IdmlPage, do not do the special anchor processing $parentElement = $element->parentIdmlObject(); if ($element->parentIdmlObject() == null) { $this->addPageElement("<!-- OUTERTEXTFRAME {$element->story->UID} -->", $outer_depth, ''); return; // yes visit children } else { $stack = $this->getAncestors($element, 'IdmlPage'); // close all open tags back to the root $this->rewind($stack, $outer_depth); $inner_depth = get_class($element->parentIdmlObject()) == 'IdmlCharacterRange' ? $outer_depth - 3 : $outer_depth; $this->addPageElement("<!-- ANCHORED TEXTFRAME {$element->story->UID} -->", $inner_depth, ''); $this->addPageElement("<div data-idml='IdmlTextFrame {$element->UID}'>", $inner_depth); $this->addPageElement("<!-- ANCHOR {$element->story->UID} -->", $inner_depth + 1, ''); // Create a new producer for recursion . . . $thisClass = get_class($this); assert($thisClass == 'IdmlProduceFixedLayout' || $thisClass == 'IdmlProduceReflowable' || $thisClass == 'IdmlProduceHtmlDiagnostic'); $currentRecursivePageNumber = $this->pageNumber; $htmlProducer = new $thisClass($currentRecursivePageNumber); // . . . then walk the tree starting from the current text frame's story . . . if ($element->story && $element->visible) { $element->story->accept($htmlProducer, $inner_depth + 1); } // . . . and finally stuff the content that _it_ produces back into this object. . . $innerContent = $htmlProducer->getBodyContent(); $diagnosticContent = $htmlProducer->getDiagnosticContent(); $this->addPageElement($innerContent, 0, $diagnosticContent); // . . . and copy the page number of the inner object to the outer object. $this->pageNumber = $htmlProducer->pageNumber; $this->addPageElement("<!-- /ANCHOR {$element->story->UID} -->", $inner_depth + 1, ''); $this->addPageElement("</div><!-- IdmlTextFrame {$element->UID}-->", $inner_depth); $this->addPageElement("<!-- /ANCHORED TEXTFRAME {$element->story->UID} -->", $inner_depth, ''); // reopen all tags from the root down to where we were before we were interrupted $this->fastForward($stack, $outer_depth); // Important: Instruct IdmlTextFrame not to continue any deeper return 'do not visit children'; } }
/** * Parse DOM. * * @param DOMDocument $doc */ private function parse(DOMDocument $doc) { $xpath = new DOMXPath($doc); $q = "//idPkg:{$this->xmlRootName}/{$this->xmlRootName}"; $nodes = $xpath->query($q); $pageNode = $nodes->item(0); $attributes = $pageNode->attributes; $this->UID = $attributes->getNamedItem('Self')->value; $itemTransform = $attributes->getNamedItem('ItemTransform')->value; $this->transformation = new IdmlTransformation($itemTransform); $this->pageCount = (int) $attributes->getNamedItem('PageCount')->value; if ($pageNode->hasAttribute('BindingLocation')) { $bindingLocation = (int) $pageNode->getAttribute('BindingLocation'); } else { // this happens with MasterSpreads which do not have a binding location. $bindingLocation = -1; } // First construct the pages (typically one or two pages per spread) // although more than two are technically allowed. // We need to have pages loaded first. $q = "//idPkg:{$this->xmlRootName}/{$this->xmlRootName}//Page"; $nodes = $xpath->query($q); foreach ($nodes as $pageNode) { $newPage = new IdmlPage($this); $newPage->parse($pageNode); $this->pages[] = $newPage; } // Process children text frames and rectangles. $spreadNodes = $doc->getElementsByTagName($this->xmlRootName); $spreadNode = $spreadNodes->item(1); // Child nodes. foreach ($spreadNode->childNodes as $element) { $nodeSelf = ''; if ($element->nodeType == XML_ELEMENT_NODE) { /*@var $element DomNode*/ //get the element's id if possible and make sure it is not to be hidden before we parse it $selfIdNode = $element->attributes->getNamedItem('Self'); if ($selfIdNode) { $nodeSelf = $selfIdNode->nodeValue; } } if ($nodeSelf && array_key_exists($nodeSelf, $this->idmlPackage->chaucerHidden)) { error_log('Processing Spread Page, hiding ' . $element->nodeName . ' ' . $nodeSelf . ' ' . __FILE__ . ' Line ' . __LINE__); } elseif ($element->nodeType == XML_ELEMENT_NODE) { switch ($element->nodeName) { case 'Rectangle': // @TODO - determine whether spans should be used for rectangles parallel to the axes, and code accordingly // $rectangle = new IdmlRectangle(); $rectangle = new IdmlPolygon(); $rectangle->parse($element); $this->dropElementIntoPage($rectangle); break; case 'TextFrame': $newTextFrame = new IdmlTextFrame(); $newTextFrame->parse($element); $this->dropElementIntoPage($newTextFrame); $pageUID = $newTextFrame->page != null ? $newTextFrame->page->UID : '000'; // And now for some hyperlink management: $hyperlinkMgr = IdmlHyperlinkManager::getInstance(); // Update the destination page names for links to anchors. // Refs to the anchors are stored during processing of children, but we don't have the UIDs until the text frame is fully parsed. $hyperlinkMgr->updateDestinationPages($newTextFrame->UID, $pageUID); // Also, map the page UID to the text frame UID so the destination page name can be determined for fixed layout. $hyperlinkMgr->saveTextFrameUID($newTextFrame->UID, $pageUID); break; case 'Group': $group = new IdmlGroup(); $group->parse($element); $this->dropElementIntoPage($group); break; case 'Polygon': $polygon = new IdmlPolygon(); $polygon->parse($element); $this->dropElementIntoPage($polygon); break; case 'Oval': $oval = new IdmlOval(); $oval->parse($element); $this->dropElementIntoPage($oval); break; case 'GraphicLine': $line = new IdmlGraphicLine(); $line->parse($element); $this->dropElementIntoPage($line); break; default: // Placeholder: no default action at this time break; } } } }
/** * Create an HTML aside from the IDML TextFrame. * @param IdmlTextFrame $element * @param int $outer_depth */ protected function createAside(IdmlTextFrame $element, $outer_depth = 0) { $inner_depth = get_class($element->parentIdmlObject()) == 'IdmlCharacterRange' ? $outer_depth - 3 : $outer_depth; $this->addPageElement("<!-- ANCHOR {$element->story->UID} -->", $inner_depth + 1, ''); $this->writeAsideBegin($element, $inner_depth + 1); // Create a new producer for recursion . . . // NOTE: Logic using a 2nd producer has been eliminated. We think it is no longer effective // Code is left in place in case things go horribly awry. // $thisClass = get_class($this); // $currentRecursivePageNumber = $this->pageNumber; // $htmlProducer = new $thisClass($currentRecursivePageNumber); // . . . then walk the tree starting from the current text frame's story . . . if ($element->story && $element->visible) { $element->story->accept($this, $outer_depth + 1); // $element->story->accept($htmlProducer, $inner_depth+1); } // . . . and finally stuff the content that _it_ produces back into this object // Copy the page elements to a new array first to prevent side effects // $innerContent = $htmlProducer->getPageElements(); // $pageElements = $this->pageElements; // $this->pageElements = array_merge($pageElements, $innerContent); // $diagnosticContent = $htmlProducer->getDiagnosticPageElements(); // $diagnosticPageElements = $this->diagnosticPageElements; // $this->diagnosticPageElements = array_merge($diagnosticPageElements, $diagnosticContent); $this->writeAsideEnd($outer_depth + 1); $this->addPageElement("<!-- /ANCHOR {$element->story->UID} -->", $inner_depth + 1, ''); if (!is_null($element->rotationOffset)) { $this->addPageElement('<div style="height:' . $element->rotationOffset . 'px;">', 0); $this->addPageElement('</div>', 0); $element->rotationOffset = null; } }
public function visitTextFrame(IdmlTextFrame $element, $depth = 0) { /* find the parent and if it is a character range, drop that from the parent list */ $parentElement = $element->parentIdmlObject(); if (is_a($parentElement, "IdmlCharacterRange") && count($this->parentStack) > 3) { $element->attributes["_pxe_stashed_parent"] = array_pop($this->parentStack); } }