inline void setDestinationOutStream(){ TokenId ti; ti.setOutputStream(); tOutput[dOutput] = OutputToken(NULL, ti); destinationsMap.emplace((Computable*) NULL, dOutput); ++dOutput; assert(dOutput <= MAX_INSTRUCTION_INPUTS); }
inline void setDestination(uint id, Computable* c = NULL){ TokenId ti(graphId, id); tOutput[dOutput] = OutputToken(NULL, ti); if(c){ destinationsMap.emplace(c, dOutput); }else{ throw std::runtime_error("Impossible to set NULL destination."); } ++dOutput; assert(dOutput <= MAX_INSTRUCTION_INPUTS); }
BOOL PSPrintDC::StartOSOutput() { if ((SafeToUseGDI == 0) && !GDIContextIsCurrent) { // We need to restore the GDI context - this involves removing our dictionary // from the dictionary stack, and calling restore. if (!OutputToken(_T("end restore")) || !OutputNewLine()) // Error return FALSE; // Flush our buffer so Camelot PS syncs correctly with GDI PS. if (!FlushPSBuffer()) // Error return FALSE; GDIContextIsCurrent = TRUE; } // Increment GDI count SafeToUseGDI++; // Ok to use GDI now return TRUE; }
BOOL PSPrintDC::OutputToken(TCHAR *Str) { #ifndef STANDALONE // Should we re-instate the Camelot context? if (!SafeToUseGDI && GDIContextIsCurrent) { // Yes - just save the context (so we can restore GDI's context) and put our // dictionary on the dict stack. // Must do this first or else we get an infinite loop! GDIContextIsCurrent = FALSE; // Code by Mike // We need to work out where we are in order to render the correct bits of postscript header. BOOL AtStartOfPaper = FALSE; BOOL AtStartOfPatch = StartOfPage; StartOfPage=FALSE; // Work out whether this is the first call to output token for this page if (AtStartOfPatch) { PrintView* pView = (PrintView*)(pPSRegion->GetRenderView()); ERROR2IF(pView==NULL,FALSE,"No printview in this PS render region"); ERROR3IF(!pView->IsKindOf(CC_RUNTIME_CLASS(PrintView)), "Not a PrintView in PSPrintDC output token"); AtStartOfPaper = ((pView->PatchInfo.PatchNumber)==1); } OutputNewLine(); // ok now check our flag. This may be the first time we've // been called from this PSPrintDC construction. If so we // need to output page header stuff. if (AtStartOfPaper) { // We need to get the name of the output plate here // this might be a bit tricky! Na easy... if (!pPSRegion->WritePlateName(this)) return FALSE; } // save the graphics state OutputToken(_T("save")); OutputNewLine(); // wxWidgets and Windows both use (0,0) to mean the top left hand origin of the // paper in logical coordinates. However, they do something rather different in // terms of physical coordinates. What windows printer drivers do (and thus what // Camelot expects) is use a postcript page transformation matrix to invert the // page, and for the postscript to be written in native DPI coordinates with the // origin at the TOP left of the page. What wxWidgets does is write its postscript // in the more natural way with the origin at the BOTTOM of the page, and handle // the coordinate inversion wihin wxWidgets. // // Note that this means while our internally generated PS expects a transformation // matrix that flips the Y coordinate (as the windows drivers produce). We // can't change the transformation matrix in the prologue because this would // affect wxWidgets output (and also it's technically difficult to do). We can't // change our own rendering matrix (so we produce the right coordinates) because // lots of things seem to explode with a matrix which flips the Y access (negative // scale factors etc.). We can't just change the coordinates we write because // other things (e.g. bitmaps) use the native render matrix. So what we do is // temporarily invert the PS transformation matrix during the period of our output. // This seems arcane but reasonably extensive research suggests it is the best // way forward. It's restored before we do any OS output. TCHAR flipbuf[256]; INT32 translate = GetDC()->GetSize().GetHeight(); camSprintf(flipbuf, _T("0 %d translate 1 -1 scale"), translate); OutputToken(flipbuf); OutputNewLine(); // Now start plate writing etc. if (!pPSRegion->WritePhotoNegative(this)) return FALSE; if (AtStartOfPaper) { // We need to fill the page with black if the plate says we // need to negate everything. if (!pPSRegion->WriteRenderPaper(this)) return FALSE; } // Write out our procset. if (!pPSRegion->WriteProlog(this)) // Error return FALSE; OutputNewLine(); OutputToken(_T("XaraStudio1Dict begin")); OutputNewLine(); // Now output the setscreen function for this plate if (!pPSRegion->WritePlateScreen(this)) return FALSE; // try to write out the sep tables if we need them if (!pPSRegion->WriteSepTables(this)) return FALSE; // export any clip region we might need. if (!OutputPSClipping()) return FALSE; } // Special tokens // static TCHAR Space = _T(' '); // static TCHAR NewLine[] = _T("\n"); if (LineWidth > 70) { // Line is getting INT32 - wrap around OutputNewLine(); } // Pad with a space (unless at the beginning of the line) if (LineWidth > 0) { // Make sure we have enough room in the buffer if (!MakeRoomInBuffer(1)) // Error occured in buffer handling. return FALSE; // Add space to buffer camStrcat(Buffer.Data, _T(" ")); Buffer.nCount++; // Update line width record. LineWidth++; } // Write the token out to the file INT32 Len = camStrlen(Str); // Make sure we have enough room in the buffer if (!MakeRoomInBuffer(Len)) // Error occured in buffer handling. return FALSE; // Add space to buffer camStrcat(Buffer.Data, Str); Buffer.nCount += Len; // Update line width record. LineWidth += Len; // Success return TRUE; #else return FALSE; #endif }