예제 #1
0
bool pt_PieceTable::_realInsertStrux(PT_DocPosition dpos,
									 PTStruxType pts,
									 const gchar ** attributes,
									 const gchar ** properties,
									 pf_Frag_Strux ** ppfs_ret)
{
	// insert a new structure fragment at the given document position.
	// this function can only be called while editing the document.
	// Also can specify an indexAP to be used for the frag rather
	// than that obtained by default. Very useful for insertting
	// Cells where you can immediately specify the cell position in
	// a table.  this function can only be called while editing the
	// document.

	UT_return_val_if_fail (m_pts==PTS_Editing, false);

	// get the fragment at the doc postion containing the given
	// document position.

	pf_Frag * pf = NULL;
	PT_BlockOffset fragOffset = 0;
	bool bFoundFrag = getFragFromPosition(dpos,&pf,&fragOffset);
	UT_return_val_if_fail (bFoundFrag, false);

	// get the strux containing the given position.

	pf_Frag_Strux * pfsContainer = NULL;
	bool bFoundContainer = _getStruxFromPosition(dpos,&pfsContainer);
	UT_return_val_if_fail (bFoundContainer,false);
	//
	// Can only insert an endTOC into a TOC
	//
	if((pfsContainer->getStruxType() == PTX_SectionTOC) && (pts != PTX_EndTOC))
	{
		bFoundContainer = _getStruxFromPosition(pfsContainer->getPos(),&pfsContainer);
		dpos--;
	}
	if(isEndFootnote(pfsContainer))
	{
		bFoundContainer = _getStruxFromFragSkip(pfsContainer,&pfsContainer);
	}
	// if we are inserting something similar to the previous strux,
	// we will clone the attributes/properties; we assume that the
	// new strux should have the same AP as the one which preceeds us.
	// This is generally true for inserting a paragraph -- it should
	// inherit the style of the one we just broke.

	PT_AttrPropIndex indexAP = 0;
	if (pfsContainer->getStruxType() == pts)
	{
		// TODO paul, add code here to see if this strux has a "followed-by"
		// TODO paul, property (or property in the style) and get the a/p
		// TODO paul, from there rather than just taking the attr/prop
		// TODO paul, of the previous strux.
		indexAP = pfsContainer->getIndexAP();
	}

//
// Look to see if we're in the middle of a hyperlink span now.
//
	pf_Frag * pHype = _findPrevHyperlink(pf);
	if(pHype != NULL && (pts != PTX_SectionFrame) // allow annotations in
	                                              // hyperlinks
	   && (pts != PTX_SectionAnnotation)
	   && (pts != PTX_EndAnnotation)) // frames are always placed
		                                           // at the end of blocks
                                                   // so we don't need this 
	{
//
// We have an open hyperlink! FIXME later we should allow this by terminating
// the hyperlink span just before this strux, then doing the insert strux.
// Instead for now we'll just disallow this insertStrux.
//
// This assert is to remind use to write the code to terminate
// the hyperlink.
//
		pf_Frag * pEndHype = _findNextHyperlink(pf);
		PT_DocPosition posEnd = 0;
		if(pEndHype)
		{
			posEnd = pEndHype->getPos();
		}
		//
		// OK now insert a new end of hyperlink at pf
		//
		insertObject(dpos, PTO_Hyperlink,NULL,NULL);
		dpos++;
		if(posEnd > 0)
		{
			//
			// Now delete the old endhyperlink.
			//
			pf_Frag * pfEnd = NULL;
			UT_uint32 newOff = 0;
			posEnd++; // from the insert
			UT_uint32 offset = 0;
			_deleteObjectWithNotify(posEnd,
									static_cast<pf_Frag_Object*>(pEndHype),
									offset,1,pfsContainer,&pfEnd,&newOff,true);
		}
		bFoundFrag = getFragFromPosition(dpos,&pf,&fragOffset);
		UT_return_val_if_fail (bFoundFrag, false);
	}	

//
// If desired, merge in the specified attributes/properties. This
// enables cells to inherit the properties of the block from which
// they were inserted.
//
	if (attributes || properties)
	{
		PT_AttrPropIndex pAPIold = indexAP;
		bool bMerged = m_varset.mergeAP(PTC_AddFmt,pAPIold,attributes,properties,&indexAP,getDocument());
        UT_UNUSED(bMerged);
		UT_ASSERT_HARMLESS(bMerged);
	}

	pf_Frag_Strux * pfsNew = NULL;
	if (!_createStrux(pts,indexAP,&pfsNew))
		return false;

	pfsNew->setXID(getXID());
	
	// when inserting paragraphs, we try to remember the current
	// span formatting active at the insertion point and add a
	// FmtMark immediately after the block.  this way, if the
	// user keeps typing text, the FmtMark will control it's
	// attr/prop -- if the user warps away and/or edits elsewhere
	// and then comes back to this point (the FmtMark may or may
	// not still be here) new text will either use the FmtMark or
	// look to the right.

	bool bNeedGlob = false;
	PT_AttrPropIndex apFmtMark = 0;
	if (pfsNew->getStruxType() == PTX_Block)
	{
		bNeedGlob = _computeFmtMarkForNewBlock(pfsNew,pf,fragOffset,&apFmtMark);
		if (bNeedGlob)
			beginMultiStepGlob();

		// if we are leaving an empty block (are stealing all it's content) we should
		// put a FmtMark in it to remember the active span fmt at the time.
		// this lets things like hitting two consecutive CR's and then comming
		// back to the first empty paragraph behave as expected.

		// fixme sevior here

		if ((pf->getType()==pf_Frag::PFT_Text) && (fragOffset == 0) &&
			(pf->getPrev()!=NULL) && (pf->getPrev()->getType()==pf_Frag::PFT_Strux))
		{
			pf_Frag_Strux *pfsStrux = static_cast<pf_Frag_Strux *>(pf->getPrev());
			if(pfsStrux->getStruxType() == PTX_Block)
			{
				_insertFmtMarkAfterBlockWithNotify(pfsContainer,dpos,apFmtMark);
			}
		}
	}
	//
	// Look if we're placing an endcell in an empty block. If so, 
	// insert a format mark
	//
	if (pfsNew->getStruxType() == PTX_EndCell)
	{
		if((pf->getPrev()!=NULL) && (pf->getPrev()->getType()==pf_Frag::PFT_Strux))
		{
			pf_Frag_Strux *pfsStrux = static_cast<pf_Frag_Strux *>(pf->getPrev());
			if(pfsStrux->getStruxType() == PTX_Block)
			{
				_insertFmtMarkAfterBlockWithNotify(pfsContainer,dpos,apFmtMark);
			}
		}
	}

	// insert this frag into the fragment list. Update the container strux as needed
	_insertStrux(pf,fragOffset,pfsNew);
	if (ppfs_ret)
		*ppfs_ret = pfsNew;

	// create a change record to describe the change, add
	// it to the history, and let our listeners know about it.
	if(pfsNew->getStruxType() == PTX_SectionFrame)
	{
		// Inserting a sectionFrame screws up dos. It goes just before the next
		// block strux found.
		dpos = pfsNew->getPrev()->getPos() + pfsNew->getPrev()->getLength();
	}
	PX_ChangeRecord_Strux * pcrs
		= new PX_ChangeRecord_Strux(PX_ChangeRecord::PXT_InsertStrux,
									dpos,indexAP,pfsNew->getXID(), pts);
	UT_return_val_if_fail (pcrs,false);

	// add record to history.  we do not attempt to coalesce these.
	m_history.addChangeRecord(pcrs);
	m_pDocument->notifyListeners(pfsContainer,pfsNew,pcrs);

	if (bNeedGlob)
	{
		// dpos might have shifted if a frame was moved in between the two blocks
		dpos = pfsNew->getPos();
		UT_return_val_if_fail (!pfsNew->getNext() || pfsNew->getNext()->getType()!=pf_Frag::PFT_FmtMark, false);
		_insertFmtMarkAfterBlockWithNotify(pfsNew,dpos+pfsNew->getLength(),apFmtMark);
		endMultiStepGlob();
	}

	return true;
}
예제 #2
0
파일: SkPDFFont.cpp 프로젝트: molikto/Skia
void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) {
    const SkAdvancedTypefaceMetrics* metricsPtr =
        SkPDFFont::GetMetrics(this->typeface(), canon);
    SkASSERT(metricsPtr);
    if (!metricsPtr) { return; }
    const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
    SkASSERT(can_embed(metrics));
    SkAdvancedTypefaceMetrics::FontType type = this->getType();
    SkTypeface* face = this->typeface();
    SkASSERT(face);

    auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
    uint16_t emSize = SkToU16(this->typeface()->getUnitsPerEm());
    add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0);

    int ttcIndex;
    std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex));
    size_t fontSize = fontAsset ? fontAsset->getLength() : 0;
    if (0 == fontSize) {
        SkDebugf("Error: (SkTypeface)(%p)::openStream() returned "
                 "empty stream (%p) when identified as kType1CID_Font "
                 "or kTrueType_Font.\n", face, fontAsset.get());
    } else {
        switch (type) {
            case SkAdvancedTypefaceMetrics::kTrueType_Font: {
                #ifdef SK_PDF_USE_SFNTLY
                if (!SkToBool(metrics.fFlags &
                              SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) {
                    sk_sp<SkPDFStream> subsetStream = get_subset_font_stream(
                            std::move(fontAsset), this->glyphUsage(),
                            metrics.fFontName.c_str(), ttcIndex);
                    if (subsetStream) {
                        descriptor->insertObjRef("FontFile2", std::move(subsetStream));
                        break;
                    }
                    // If subsetting fails, fall back to original font data.
                    fontAsset.reset(face->openStream(&ttcIndex));
                    SkASSERT(fontAsset);
                    SkASSERT(fontAsset->getLength() == fontSize);
                    if (!fontAsset || fontAsset->getLength() == 0) { break; }
                }
                #endif  // SK_PDF_USE_SFNTLY
                auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
                fontStream->dict()->insertInt("Length1", fontSize);
                descriptor->insertObjRef("FontFile2", std::move(fontStream));
                break;
            }
            case SkAdvancedTypefaceMetrics::kType1CID_Font: {
                auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
                fontStream->dict()->insertName("Subtype", "CIDFontType0C");
                descriptor->insertObjRef("FontFile3", std::move(fontStream));
                break;
            }
            default:
                SkASSERT(false);
        }
    }

    auto newCIDFont = sk_make_sp<SkPDFDict>("Font");
    newCIDFont->insertObjRef("FontDescriptor", std::move(descriptor));
    newCIDFont->insertName("BaseFont", metrics.fPostScriptName);

    switch (type) {
        case SkAdvancedTypefaceMetrics::kType1CID_Font:
            newCIDFont->insertName("Subtype", "CIDFontType0");
            break;
        case SkAdvancedTypefaceMetrics::kTrueType_Font:
            newCIDFont->insertName("Subtype", "CIDFontType2");
            newCIDFont->insertName("CIDToGIDMap", "Identity");
            break;
        default:
            SkASSERT(false);
    }
    auto sysInfo = sk_make_sp<SkPDFDict>();
    sysInfo->insertString("Registry", "Adobe");
    sysInfo->insertString("Ordering", "Identity");
    sysInfo->insertInt("Supplement", 0);
    newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo));

    int16_t defaultWidth = 0;
    {
        int emSize;
        auto glyphCache = SkPDFFont::MakeVectorCache(face, &emSize);
        sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
                glyphCache.get(), &this->glyphUsage(), SkToS16(emSize), &defaultWidth);
        if (widths && widths->size() > 0) {
            newCIDFont->insertObject("W", std::move(widths));
        }
        newCIDFont->insertScalar(
                "DW", scaleFromFontUnits(defaultWidth, SkToS16(emSize)));
    }

    ////////////////////////////////////////////////////////////////////////////

    this->insertName("Subtype", "Type0");
    this->insertName("BaseFont", metrics.fPostScriptName);
    this->insertName("Encoding", "Identity-H");
    auto descendantFonts = sk_make_sp<SkPDFArray>();
    descendantFonts->appendObjRef(std::move(newCIDFont));
    this->insertObject("DescendantFonts", std::move(descendantFonts));

    if (metrics.fGlyphToUnicode.count() > 0) {
        this->insertObjRef("ToUnicode",
                           SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode,
                                                  &this->glyphUsage(),
                                                  multiByteGlyphs(),
                                                  firstGlyphID(),
                                                  lastGlyphID()));
    }
    SkDEBUGCODE(fPopulated = true);
    return;
}
예제 #3
0
파일: SkPDFFont.cpp 프로젝트: molikto/Skia
static void add_type3_font_info(SkPDFCanon* canon,
                                SkPDFDict* font,
                                SkTypeface* typeface,
                                const SkBitSet& subset,
                                SkGlyphID firstGlyphID,
                                SkGlyphID lastGlyphID) {
    const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon);
    SkASSERT(lastGlyphID >= firstGlyphID);
    // Remove unused glyphs at the end of the range.
    // Keep the lastGlyphID >= firstGlyphID invariant true.
    while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) {
        --lastGlyphID;
    }
    int unitsPerEm;
    auto cache = SkPDFFont::MakeVectorCache(typeface, &unitsPerEm);
    SkASSERT(cache);
    SkScalar emSize = (SkScalar)unitsPerEm;
    font->insertName("Subtype", "Type3");
    // Flip about the x-axis and scale by 1/emSize.
    SkMatrix fontMatrix;
    fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
    font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));

    auto charProcs = sk_make_sp<SkPDFDict>();
    auto encoding = sk_make_sp<SkPDFDict>("Encoding");

    auto encDiffs = sk_make_sp<SkPDFArray>();
    // length(firstGlyphID .. lastGlyphID) ==  lastGlyphID - firstGlyphID + 1
    // plus 1 for glyph 0;
    SkASSERT(firstGlyphID > 0);
    SkASSERT(lastGlyphID >= firstGlyphID);
    int glyphCount = lastGlyphID - firstGlyphID + 2;
    // one other entry for the index of first glyph.
    encDiffs->reserve(glyphCount + 1);
    encDiffs->appendInt(0);  // index of first glyph

    auto widthArray = sk_make_sp<SkPDFArray>();
    widthArray->reserve(glyphCount);

    SkIRect bbox = SkIRect::MakeEmpty();

    sk_sp<SkPDFStream> emptyStream;
    for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
        bool skipGlyph = gID != 0 && !subset.has(gID);
        SkString characterName;
        SkScalar advance = 0.0f;
        SkIRect glyphBBox;
        if (skipGlyph) {
            characterName.set("g0");
        } else {
            characterName.printf("g%X", gID);
            const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
            advance = SkFloatToScalar(glyph.fAdvanceX);
            glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
                                          glyph.fWidth, glyph.fHeight);
            bbox.join(glyphBBox);
            const SkPath* path = cache->findPath(glyph);
            if (path && !path->isEmpty()) {
                SkDynamicMemoryWStream content;
                setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox,
                                            &content);
                SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content);
                SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(),
                                      &content);
                charProcs->insertObjRef(
                    characterName, sk_make_sp<SkPDFStream>(
                            std::unique_ptr<SkStreamAsset>(content.detachAsStream())));
            } else {
                if (!emptyStream) {
                    emptyStream = sk_make_sp<SkPDFStream>(
                            std::unique_ptr<SkStreamAsset>(
                                    new SkMemoryStream((size_t)0)));
                }
                charProcs->insertObjRef(characterName, emptyStream);
            }
        }
        encDiffs->appendName(characterName.c_str());
        widthArray->appendScalar(advance);
    }

    encoding->insertObject("Differences", std::move(encDiffs));
    font->insertInt("FirstChar", 0);
    font->insertInt("LastChar", lastGlyphID - firstGlyphID + 1);
    /* FontBBox: "A rectangle expressed in the glyph coordinate
      system, specifying the font bounding box. This is the smallest
      rectangle enclosing the shape that would result if all of the
      glyphs of the font were placed with their origins coincident and
      then filled." */
    auto fontBBox = sk_make_sp<SkPDFArray>();
    fontBBox->reserve(4);
    fontBBox->appendInt(bbox.left());
    fontBBox->appendInt(bbox.bottom());
    fontBBox->appendInt(bbox.right());
    fontBBox->appendInt(bbox.top());
    font->insertObject("FontBBox", std::move(fontBBox));
    font->insertName("CIDToGIDMap", "Identity");
    if (metrics && metrics->fGlyphToUnicode.count() > 0) {
        font->insertObjRef("ToUnicode",
                           SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode,
                                                  &subset,
                                                  false,
                                                  firstGlyphID,
                                                  lastGlyphID));
    }
    auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
    int32_t fontDescriptorFlags = kPdfSymbolic;
    if (metrics) {
        // Type3 FontDescriptor does not require all the same fields.
        descriptor->insertName("FontName", metrics->fPostScriptName);
        descriptor->insertInt("ItalicAngle", metrics->fItalicAngle);
        fontDescriptorFlags |= (int32_t)metrics->fStyle;
        // Adobe requests CapHeight, XHeight, and StemV be added
        // to "greatly help our workflow downstream".
        if (metrics->fCapHeight != 0) { descriptor->insertInt("CapHeight", metrics->fCapHeight); }
        if (metrics->fStemV     != 0) { descriptor->insertInt("StemV",     metrics->fStemV);     }
        SkScalar xHeight = cache->getFontMetrics().fXHeight;
        if (xHeight != 0) {
            descriptor->insertScalar("XHeight", xHeight);
        }
    }
    descriptor->insertInt("Flags", fontDescriptorFlags);
    font->insertObjRef("FontDescriptor", std::move(descriptor));
    font->insertObject("Widths", std::move(widthArray));
    font->insertObject("Encoding", std::move(encoding));
    font->insertObject("CharProcs", std::move(charProcs));
}
예제 #4
0
void HierarchyList::insertObject( QObject *o, QListViewItem *parent )
{
    bool fakeMainWindow = false;
    if ( o && o->inherits( "QMainWindow" ) ) {
  QObject *cw = ( (QMainWindow*)o )->centralWidget();
  if ( cw ) {
      o = cw;
      fakeMainWindow = true;
  }
    }
    QListViewItem *item = 0;
    QString className = WidgetFactory::classNameOf( o );
    if ( o->inherits( "QLayoutWidget" ) ) {
  switch ( WidgetFactory::layoutType( (QWidget*)o ) ) {
  case WidgetFactory::HBox:
      className = "HBox";
      break;
  case WidgetFactory::VBox:
      className = "VBox";
      break;
  case WidgetFactory::Grid:
      className = "Grid";
      break;
  default:
      break;
  }
    }

    QString dbInfo;
#ifndef QT_NO_SQL
    dbInfo = MetaDataBase::fakeProperty( o, "database" ).toStringList().join(".");
#endif

    QString name = o->name();
    if ( o->parent() && o->parent()->inherits( "QWidgetStack" ) &&
   o->parent()->parent() ) {
  if ( o->parent()->parent()->inherits( "QTabWidget" ) )
      name = ( (QTabWidget*)o->parent()->parent() )->tabLabel( (QWidget*)o );
  else if ( o->parent()->parent()->inherits( "QWizard" ) )
      name = ( (QWizard*)o->parent()->parent() )->title( (QWidget*)o );
    }

    QToolBox *tb;
    if ( o->parent() && o->parent()->parent() &&
     (tb = ::qt_cast<QToolBox*>(o->parent()->parent()->parent())) )
    name = tb->itemLabel( tb->indexOf((QWidget*)o) );


    if ( fakeMainWindow ) {
  name = o->parent()->name();
  className = "QMainWindow";
    }

    if ( !parent )
  item = new HierarchyItem( HierarchyItem::Widget, this, name, className, dbInfo );
    else
  item = new HierarchyItem( HierarchyItem::Widget, parent, name, className, dbInfo );
    if ( !parent )
  item->setPixmap( 0, PixmapChooser::loadPixmap( "form.xpm", PixmapChooser::Mini ) );
    else if ( o->inherits( "QLayoutWidget") )
  item->setPixmap( 0, PixmapChooser::loadPixmap( "layout.xpm", PixmapChooser::Small ) );
    else
  item->setPixmap( 0, WidgetDatabase::iconSet( WidgetDatabase::idFromClassName( WidgetFactory::classNameOf( o ) ) ).
       pixmap( QIconSet::Small, QIconSet::Normal ) );
    ( (HierarchyItem*)item )->setWidget( (QWidget*)o );

    const QObjectList *l = o->children();
    if ( !l )
  return;
    QObjectListIt it( *l );
    it.toLast();
    for ( ; it.current(); --it ) {
  if ( !it.current()->isWidgetType() || ( (QWidget*)it.current() )->isHidden() )
      continue;
  if (  !formWindow->widgets()->find( (QWidget*)it.current() ) ) {
      if ( it.current()->parent() &&
     ( it.current()->parent()->inherits( "QTabWidget" ) ||
       it.current()->parent()->inherits( "QWizard" ) ) &&
     it.current()->inherits( "QWidgetStack" ) ) {
    QObject *obj = it.current();
    QObjectList *l2 = obj->queryList( "QWidget", 0, true, false );
    QDesignerTabWidget *tw = 0;
    QDesignerWizard *dw = 0;
    if ( it.current()->parent()->inherits( "QTabWidget" ) )
        tw = (QDesignerTabWidget*)it.current()->parent();
    if ( it.current()->parent()->inherits( "QWizard" ) )
      dw = (QDesignerWizard*)it.current()->parent();
    QWidgetStack *stack = (QWidgetStack*)obj;
    for ( obj = l2->last(); obj; obj = l2->prev() ) {
        if ( qstrcmp( obj->className(), "QWidgetStackPrivate::Invisible" ) == 0 ||
       ( tw && !tw->tabBar()->tab( stack->id( (QWidget*)obj ) ) ) ||
       ( dw && dw->isPageRemoved( (QWidget*)obj ) ) )
      continue;
        insertObject( obj, item );
    }
    delete l2;
      } else if ( ::qt_cast<QToolBox*>(it.current()->parent()) ) {
            if ( !::qt_cast<QScrollView*>(it.current()) )
            continue;
            QToolBox *tb = (QToolBox*)it.current()->parent();
            for ( int i = tb->count() - 1; i >= 0; --i )
            insertObject( tb->item( i ), item );
        }
      continue;
  }
  insertObject( it.current(), item );
    }

    if ( item->firstChild() )
  item->setOpen( true );
}
/*!
 * Read all Psion paragraphs and add them to the document.
 */
UT_Error IE_Imp_Psion::readParagraphs(const psiconv_text_and_layout psiontext,
                                      const psiconv_word_styles_section style_sec)
//                                      psiconv_list embobjlst)
{
	unsigned int i,inline_nr;
	int loc;
	psiconv_paragraph paragraph;
	psiconv_in_line_layout in_line;
	UT_UCS4String text;
	psiconv_word_style style;
	const gchar *stylename;
	UT_Error res;

	// Iterate through all paragraphs
	for (i=0; i < psiconv_list_length(psiontext); i++) {

		UT_DEBUGMSG(("PSION: Importing paragraph %d\n",i));
		if (!(paragraph = (psiconv_paragraph) psiconv_list_get(psiontext,i))) {
			// Something is really wrong...
			UT_ASSERT(paragraph != NULL);
			return UT_IE_IMPORTERROR;
		}
	
		// Determine the style name; set it to Normal if it is not available
		if (!style_sec ||
		    !(style = psiconv_get_style(style_sec,paragraph->base_style)) ||
			(!style->name) || 
		  	!(stylename = prepare_style_name(style->name)))
			stylename = (const gchar *) strdup("Normal");
		if (!stylename)
			return UT_IE_NOMEMORY;
		UT_DEBUGMSG(("PSION: paragraph %d: style %s\n",i,stylename));
		
		// Add all paragraph attributes to the document
		if ((res = applyParagraphAttributes(paragraph->base_paragraph,stylename)))
			return res;
		
		// Iterate through all Psion inlines. These contain the character
		// layout information, together with the number of characters they
		// apply to.
		loc = 0;
		for(inline_nr=0; inline_nr < psiconv_list_length(paragraph->in_lines);
		    inline_nr++) {
			UT_DEBUGMSG(("Psion: paragraph %d inline %d\n",i,inline_nr));
			if (!(in_line = (psiconv_in_line_layout) psiconv_list_get(paragraph->in_lines,inline_nr))) {
				// Something is really wrong...
				UT_ASSERT(in_line != NULL);
				return UT_IE_IMPORTERROR;
			}
			// This may be an object, which needs special handling.
		 	// Objects have layout associated with them, but we will ignore
			// it. I am not sure how it would apply anyway. We will also ignore
			// all text. It should just be a single character \016, which is the
			// object marker.
			if (in_line->object) { 
				if ((res = insertObject(in_line)))
					return res;
			} else {		
				// Put all characters belonging to the current inline into text
				text.clear();
				if ((res = prepareCharacters(paragraph->text + loc,in_line->length,
					  text)))
					return res;
				// Yes, text may be empty!
				if (text.length()) {
					// Add the character layout and the text itself to the document
					if ((res = applyCharacterAttributes(in_line->layout)))
						return res;
					if (!(appendSpan((text.ucs4_str()),text.length())))
						return UT_IE_IMPORTERROR;
				}
			}
			loc += in_line->length;
		}

		// There may be text left after iterating through all inlines.
		// This remaining text gets the paragraph base_character layout.
		if (loc < psiconv_unicode_strlen(paragraph->text)) {
			// Get the remaining characters into text
			text.clear();
			if ((res = prepareCharacters(paragraph->text+loc,
			                       psiconv_unicode_strlen(paragraph->text - loc),text)))
				return res;

			// Yes, text may be empty!
			if (text.length()) {
				// Add the character layout and the text itself to the document.

				if ((res = applyCharacterAttributes(paragraph->base_character)))
					return res;

				if (!appendSpan(text.ucs4_str(),text.length()))
					return UT_IE_IMPORTERROR;
			}
		}
	}
	return UT_OK;
}
예제 #6
0
파일: cloner.cpp 프로젝트: binque/mongo
        void operator()(DBClientCursorBatchIterator &i) {
            const string to_dbname = nsToDatabase(to_collection);
            while (i.moreInCurrentBatch()) {
                if (n % 128 == 127) {
                    time_t now = time(0);
                    if (now - lastLog >= 60) { 
                        // report progress
                        if (lastLog) {
                            log() << "clone " << to_collection << ' ' << n << endl;
                        }
                        lastLog = now;
                    }
                    mayInterrupt(_mayBeInterrupted);
                }

                BSONObj js = i.nextSafe();
                ++n;

                if (isindex) {
                    verify(nsToCollectionSubstring(from_collection) == "system.indexes");
                    storedForLater->push_back(fixindex(js, to_dbname).getOwned());
                }
                else {
                    try {
                        LOCK_REASON(lockReason, "cloner: copying documents into local collection");
                        Client::ReadContext ctx(to_collection, lockReason);
                        if (_isCapped) {
                            Collection *cl = getCollection(to_collection);
                            verify(cl->isCapped());
                            BSONObj pk = js["$_"].Obj();
                            BSONObjBuilder rowBuilder;                        
                            BSONObjIterator it(js);
                            while (it.moreWithEOO()) {
                                BSONElement e = it.next();
                                if (e.eoo()) {
                                    break;
                                }
                                if (!mongoutils::str::equals(e.fieldName(), "$_")) {
                                    rowBuilder.append(e);
                                }
                            }
                            BSONObj row = rowBuilder.obj();
                            CappedCollection *cappedCl = cl->as<CappedCollection>();
                            bool indexBitChanged = false;
                            cappedCl->insertObjectWithPK(pk, row, Collection::NO_LOCKTREE, &indexBitChanged);
                            // Hack copied from Collection::insertObject. TODO: find a better way to do this                        
                            if (indexBitChanged) {
                                cl->noteMultiKeyChanged();
                            }
                        }
                        else {
                            insertObject(to_collection, js, 0, logForRepl);
                        }
                    }
                    catch (UserException& e) {
                        error() << "error: exception cloning object in " << from_collection << ' ' << e.what() << " obj:" << js.toString() << '\n';
                        throw;
                    }

                    RARELY if ( time( 0 ) - saveLast > 60 ) {
                        log() << n << " objects cloned so far from collection " << from_collection << endl;
                        saveLast = time( 0 );
                    }
                }
            }
        }
예제 #7
0
static SkPDFIndirectReference make_function_shader(SkPDFDocument* doc,
                                                   const SkPDFGradientShader::Key& state) {
    SkPoint transformPoints[2];
    const SkShader::GradientInfo& info = state.fInfo;
    SkMatrix finalMatrix = state.fCanvasTransform;
    finalMatrix.preConcat(state.fShaderTransform);

    bool doStitchFunctions = (state.fType == SkShader::kLinear_GradientType ||
                              state.fType == SkShader::kRadial_GradientType ||
                              state.fType == SkShader::kConical_GradientType) &&
                              (SkTileMode)info.fTileMode == SkTileMode::kClamp &&
                              !finalMatrix.hasPerspective();

    int32_t shadingType = 1;
    auto pdfShader = SkPDFMakeDict();
    // The two point radial gradient further references
    // state.fInfo
    // in translating from x, y coordinates to the t parameter. So, we have
    // to transform the points and radii according to the calculated matrix.
    if (doStitchFunctions) {
        pdfShader->insertObject("Function", gradientStitchCode(info));
        shadingType = (state.fType == SkShader::kLinear_GradientType) ? 2 : 3;

        auto extend = SkPDFMakeArray();
        extend->reserve(2);
        extend->appendBool(true);
        extend->appendBool(true);
        pdfShader->insertObject("Extend", std::move(extend));

        std::unique_ptr<SkPDFArray> coords;
        if (state.fType == SkShader::kConical_GradientType) {
            SkScalar r1 = info.fRadius[0];
            SkScalar r2 = info.fRadius[1];
            SkPoint pt1 = info.fPoint[0];
            SkPoint pt2 = info.fPoint[1];
            FixUpRadius(pt1, r1, pt2, r2);

            coords = SkPDFMakeArray(pt1.x(),
                                    pt1.y(),
                                    r1,
                                    pt2.x(),
                                    pt2.y(),
                                    r2);
        } else if (state.fType == SkShader::kRadial_GradientType) {
            const SkPoint& pt1 = info.fPoint[0];
            coords = SkPDFMakeArray(pt1.x(),
                                    pt1.y(),
                                    0,
                                    pt1.x(),
                                    pt1.y(),
                                    info.fRadius[0]);
        } else {
            const SkPoint& pt1 = info.fPoint[0];
            const SkPoint& pt2 = info.fPoint[1];
            coords = SkPDFMakeArray(pt1.x(),
                                    pt1.y(),
                                    pt2.x(),
                                    pt2.y());
        }

        pdfShader->insertObject("Coords", std::move(coords));
    } else {
        // Depending on the type of the gradient, we want to transform the
        // coordinate space in different ways.
        transformPoints[0] = info.fPoint[0];
        transformPoints[1] = info.fPoint[1];
        switch (state.fType) {
            case SkShader::kLinear_GradientType:
                break;
            case SkShader::kRadial_GradientType:
                transformPoints[1] = transformPoints[0];
                transformPoints[1].fX += info.fRadius[0];
                break;
            case SkShader::kConical_GradientType: {
                transformPoints[1] = transformPoints[0];
                transformPoints[1].fX += SK_Scalar1;
                break;
            }
            case SkShader::kSweep_GradientType:
                transformPoints[1] = transformPoints[0];
                transformPoints[1].fX += SK_Scalar1;
                break;
            case SkShader::kColor_GradientType:
            case SkShader::kNone_GradientType:
            default:
                return SkPDFIndirectReference();
        }

        // Move any scaling (assuming a unit gradient) or translation
        // (and rotation for linear gradient), of the final gradient from
        // info.fPoints to the matrix (updating bbox appropriately).  Now
        // the gradient can be drawn on on the unit segment.
        SkMatrix mapperMatrix;
        unit_to_points_matrix(transformPoints, &mapperMatrix);

        finalMatrix.preConcat(mapperMatrix);

        // Preserves as much as possible in the final matrix, and only removes
        // the perspective. The inverse of the perspective is stored in
        // perspectiveInverseOnly matrix and has 3 useful numbers
        // (p0, p1, p2), while everything else is either 0 or 1.
        // In this way the shader will handle it eficiently, with minimal code.
        SkMatrix perspectiveInverseOnly = SkMatrix::I();
        if (finalMatrix.hasPerspective()) {
            if (!split_perspective(finalMatrix,
                                   &finalMatrix, &perspectiveInverseOnly)) {
                return SkPDFIndirectReference();
            }
        }

        SkRect bbox;
        bbox.set(state.fBBox);
        if (!SkPDFUtils::InverseTransformBBox(finalMatrix, &bbox)) {
            return SkPDFIndirectReference();
        }
        SkDynamicMemoryWStream functionCode;

        SkShader::GradientInfo infoCopy = info;

        if (state.fType == SkShader::kConical_GradientType) {
            SkMatrix inverseMapperMatrix;
            if (!mapperMatrix.invert(&inverseMapperMatrix)) {
                return SkPDFIndirectReference();
            }
            inverseMapperMatrix.mapPoints(infoCopy.fPoint, 2);
            infoCopy.fRadius[0] = inverseMapperMatrix.mapRadius(info.fRadius[0]);
            infoCopy.fRadius[1] = inverseMapperMatrix.mapRadius(info.fRadius[1]);
        }
        switch (state.fType) {
            case SkShader::kLinear_GradientType:
                linearCode(infoCopy, perspectiveInverseOnly, &functionCode);
                break;
            case SkShader::kRadial_GradientType:
                radialCode(infoCopy, perspectiveInverseOnly, &functionCode);
                break;
            case SkShader::kConical_GradientType:
                twoPointConicalCode(infoCopy, perspectiveInverseOnly, &functionCode);
                break;
            case SkShader::kSweep_GradientType:
                sweepCode(infoCopy, perspectiveInverseOnly, &functionCode);
                break;
            default:
                SkASSERT(false);
        }
        pdfShader->insertObject(
                "Domain", SkPDFMakeArray(bbox.left(), bbox.right(), bbox.top(), bbox.bottom()));

        auto domain = SkPDFMakeArray(bbox.left(), bbox.right(), bbox.top(), bbox.bottom());
        std::unique_ptr<SkPDFArray> rangeObject = SkPDFMakeArray(0, 1, 0, 1, 0, 1);
        pdfShader->insertRef("Function",
                             make_ps_function(functionCode.detachAsStream(), std::move(domain),
                                              std::move(rangeObject), doc));
    }

    pdfShader->insertInt("ShadingType", shadingType);
    pdfShader->insertName("ColorSpace", "DeviceRGB");

    SkPDFDict pdfFunctionShader("Pattern");
    pdfFunctionShader.insertInt("PatternType", 2);
    pdfFunctionShader.insertObject("Matrix", SkPDFUtils::MatrixToArray(finalMatrix));
    pdfFunctionShader.insertObject("Shading", std::move(pdfShader));
    return doc->emit(pdfFunctionShader);
}
예제 #8
0
static std::unique_ptr<SkPDFDict> gradientStitchCode(const SkShader::GradientInfo& info) {
    auto retval = SkPDFMakeDict();

    // normalize color stops
    int colorCount = info.fColorCount;
    std::vector<SkColor>  colors(info.fColors, info.fColors + colorCount);
    std::vector<SkScalar> colorOffsets(info.fColorOffsets, info.fColorOffsets + colorCount);

    int i = 1;
    while (i < colorCount - 1) {
        // ensure stops are in order
        if (colorOffsets[i - 1] > colorOffsets[i]) {
            colorOffsets[i] = colorOffsets[i - 1];
        }

        // remove points that are between 2 coincident points
        if ((colorOffsets[i - 1] == colorOffsets[i]) && (colorOffsets[i] == colorOffsets[i + 1])) {
            colorCount -= 1;
            colors.erase(colors.begin() + i);
            colorOffsets.erase(colorOffsets.begin() + i);
        } else {
            i++;
        }
    }
    // find coincident points and slightly move them over
    for (i = 1; i < colorCount - 1; i++) {
        if (colorOffsets[i - 1] == colorOffsets[i]) {
            colorOffsets[i] += 0.00001f;
        }
    }
    // check if last 2 stops coincide
    if (colorOffsets[i - 1] == colorOffsets[i]) {
        colorOffsets[i - 1] -= 0.00001f;
    }

    SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(colorCount);
    ColorTuple *colorData = colorDataAlloc.get();
    for (int i = 0; i < colorCount; i++) {
        colorData[i][0] = SkColorGetR(colors[i]);
        colorData[i][1] = SkColorGetG(colors[i]);
        colorData[i][2] = SkColorGetB(colors[i]);
    }

    // no need for a stitch function if there are only 2 stops.
    if (colorCount == 2)
        return createInterpolationFunction(colorData[0], colorData[1]);

    auto encode = SkPDFMakeArray();
    auto bounds = SkPDFMakeArray();
    auto functions = SkPDFMakeArray();

    retval->insertObject("Domain", SkPDFMakeArray(0, 1));
    retval->insertInt("FunctionType", 3);

    for (int i = 1; i < colorCount; i++) {
        if (i > 1) {
            bounds->appendScalar(colorOffsets[i-1]);
        }

        encode->appendScalar(0);
        encode->appendScalar(1.0f);

        functions->appendObject(createInterpolationFunction(colorData[i-1], colorData[i]));
    }

    retval->insertObject("Encode", std::move(encode));
    retval->insertObject("Bounds", std::move(bounds));
    retval->insertObject("Functions", std::move(functions));

    return retval;
}