Example #1
0
static sk_sp<SkPDFArray> make_indexed_color_space(const SkColorTable* table) {
    auto result = sk_make_sp<SkPDFArray>();
    result->reserve(4);
    result->appendName("Indexed");
    result->appendName("DeviceRGB");
    SkASSERT(table);
    if (table->count() < 1) {
        result->appendInt(0);
        char shortTableArray[3] = {0, 0, 0};
        SkString tableString(shortTableArray, SK_ARRAY_COUNT(shortTableArray));
        result->appendString(tableString);
        return result;
    }
    result->appendInt(table->count() - 1);  // maximum color index.

    // Potentially, this could be represented in fewer bytes with a stream.
    // Max size as a string is 1.5k.
    char tableArray[256 * 3];
    SkASSERT(3u * table->count() <= SK_ARRAY_COUNT(tableArray));
    uint8_t* tablePtr = reinterpret_cast<uint8_t*>(tableArray);
    const SkPMColor* colors = table->readColors();
    for (int i = 0; i < table->count(); i++) {
        pmcolor_to_rgb24(colors[i], tablePtr, kN32_SkColorType);
        tablePtr += 3;
    }
    SkString tableString(tableArray, 3 * table->count());
    result->appendString(tableString);
    return result;
}
Example #2
0
sk_sp<SkPDFDict> SkPDFResourceDict::Make(
        const SkTDArray<SkPDFObject*>* gStateResources,
        const SkTDArray<SkPDFObject*>* patternResources,
        const SkTDArray<SkPDFObject*>* xObjectResources,
        const SkTDArray<SkPDFObject*>* fontResources) {
    auto dict = sk_make_sp<SkPDFDict>();
    static const char kProcs[][7] = {
        "PDF", "Text", "ImageB", "ImageC", "ImageI"};
    auto procSets = sk_make_sp<SkPDFArray>();

    procSets->reserve(SK_ARRAY_COUNT(kProcs));
    for (size_t i = 0; i < SK_ARRAY_COUNT(kProcs); i++) {
        procSets->appendName(kProcs[i]);
    }
    dict->insertObject("ProcSets", std::move(procSets));

    if (gStateResources) {
        add_subdict(*gStateResources, kExtGState_ResourceType, dict.get());
    }
    if (patternResources) {
        add_subdict(*patternResources, kPattern_ResourceType, dict.get());
    }
    if (xObjectResources) {
        add_subdict(*xObjectResources, kXObject_ResourceType, dict.get());
    }
    if (fontResources) {
        add_subdict(*fontResources, kFont_ResourceType, dict.get());
    }
    return dict;
}
Example #3
0
    // Append the transcript names for the given record.
    void _appendTranscriptNames(seqan::String<unsigned> & tIDs,  // transcript ids to write out
                                seqan::StringSet<seqan::CharString> & contigNames,
                                seqan::NameStoreCache<seqan::StringSet<seqan::CharString> > & cache,
                                MyGffRecord const & record)
    {
        clear(tIDs);

        seqan::CharString groupNames;
        for (unsigned i = 0; i < length(record.tagNames); ++i)
            if (record.tagNames[i] == options.gffGroupBy)
                groupNames = record.tagValues[i];
        if (empty(groupNames))
            return;  // Record has no group names.

        // Write out the ids of the transcripts that the record belongs to as indices in contigNames.
        unsigned idx = 0;
        seqan::StringSet<seqan::CharString> ss;
        strSplit(ss, groupNames, seqan::EqualsChar<','>());
        for (unsigned i = 0; i < length(ss); ++i)
        {
            if (empty(ss[i]))
                continue;
            if (!getIdByName(contigNames, ss[i], idx, cache))
            {
                appendValue(tIDs, length(contigNames));
                appendName(contigNames, ss[i], cache);
            }
            else
            {
                appendValue(tIDs, idx);
            }
        }
    }
Example #4
0
static void populate_type_1_font(SkPDFDict* font,
                                 const SkAdvancedTypefaceMetrics& info,
                                 const std::vector<SkString>& glyphNames,
                                 SkTypeface* typeface,
                                 SkGlyphID firstGlyphID,
                                 SkGlyphID lastGlyphID) {
    font->insertName("Subtype", "Type1");
    font->insertName("BaseFont", info.fPostScriptName);

    // glyphCount not including glyph 0
    unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
    SkASSERT(glyphCount > 0 && glyphCount <= 255);
    font->insertInt("FirstChar", (size_t)0);
    font->insertInt("LastChar", (size_t)glyphCount);
    {
        int emSize;
        auto glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
        auto widths = sk_make_sp<SkPDFArray>();
        SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
        widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
        for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
            advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
            widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
        }
        font->insertObject("Widths", std::move(widths));
    }
    auto encDiffs = sk_make_sp<SkPDFArray>();
    encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
    encDiffs->appendInt(0);

    SkASSERT(glyphNames.size() > lastGlyphID);
    const SkString unknown("UNKNOWN");
    encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]);
    for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
        encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]);
    }

    auto encoding = sk_make_sp<SkPDFDict>("Encoding");
    encoding->insertObject("Differences", std::move(encDiffs));
    font->insertObject("Encoding", std::move(encoding));
}
Example #5
0
void ProjectSplicedRoi::_updateRanges(seqan::GffRecord const & record,
                                      seqan::Segment<seqan::CharString, seqan::InfixSegment> const & name)
{
    if (verbosity >= 3)
        std::cerr << "Updating " << name << "\t" << record.beginPos << "\t" << record.endPos << "\n";

    unsigned idx = 0;
    if (getIdByName(groupNames, name, idx, groupNamesCache))
    {
        ranges[idx].i1 = std::min(ranges[idx].i1, (int)record.beginPos);
        ranges[idx].i2 = std::max(ranges[idx].i2, (int)record.endPos);
    }
    else
    {
        idx = length(groupNames);
        appendName(groupNames, name, groupNamesCache);
        appendValue(ranges, TIntPair(record.beginPos, record.endPos));
    }
}
Example #6
0
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));
}
// feed the parser with a char
// return value:
// 1	if needs more chars
// 0	if finished
// -1	if error
uint8_t JSONStreamingParser::feed(char c)
{
	switch(state)
	{
		// on error, just drop chars and return state
		case PARSER_ERROR:
		case PARSER_FINISHED:
			return state;
			
		// on idle, espect { opening character, skipping blanks
		case PARSER_IDLE:
			if(isspace(c))
				return state;
			if(c != '{')
			{
				state = PARSER_ERROR;
				return state;
			}
			state = PARSER_WAIT_NAME;
			flags = 0;
			return state;
			
		case PARSER_WAIT_NAME:
			// skip spaces
			if(isspace(c))
				return state;
			
			// we can have quotes or double quotes here
			if(c != '"' && c != '\'')
			{
				state = PARSER_ERROR;
				return state;
			}
			if(c == '"')
				flags = IN_DQUOTES;
			else
				flags = IN_QUOTES;
			
			// switch to reading name
			clearName();
			state = PARSER_NAME;
			return state;
			
		case PARSER_NAME:
		
			// first, look at special state after a backslash
			if(flags & IN_BACKSLASH)
			{
				appendName(c);
				flags &= ~IN_BACKSLASH;
				return state;
			}
			else if(c == '\\')
			{
				flags |= IN_BACKSLASH;
				return state;
			}
				
			switch(c)
			{
				case '"':
					if((flags & IN_QUOTES))
					{
						appendName(c);
						return state;
					}
					// switch to semicolon state
					state = PARSER_WAIT_SEMICOLON;
					flags = 0;
					return state;
					
				case '\'':
					if((flags & IN_DQUOTES))
					{
						appendName(c);
						return state;
					}
					// switch to semicolon state
					state = PARSER_WAIT_SEMICOLON;
					flags = 0;
					return state;
					
				case ':':
					if( (flags & IN_QUOTES) || (flags & IN_DQUOTES))
					{
						appendName(c);
						return state;
					}
					state = PARSER_WAIT_VALUE;
					flags = 0;
					return state;
					
				case 0:
					state = PARSER_ERROR;
					return state;
					
				default:
					appendName(c);
					return state;
			} // switch(c)
			
		case PARSER_WAIT_SEMICOLON:
			if(isspace(c))
				return state;
			if(c != ':')
			{
				state = PARSER_ERROR;
				return state;
			}
			state = PARSER_WAIT_VALUE;
			flags = 0;
			return state;
			
		case PARSER_WAIT_VALUE:
			if(isspace(c))
				return state;
			
			// value can be a simple type, a list or an array
			// check latter 2 before
			if(c == '{')
			{
				doCallback("<LIST>");
				level++;
				
				// mark current level as list
				levels = levels << 1;
				
				clearName();
				state = PARSER_WAIT_NAME;
				flags = 0;
				return state;
			}
			else if(c == '[')
			{
				doCallback("<ARRAY>");
				level++;

				// mark current level as array
				levels = (levels << 1) | 0x01;
				
				clearName();
				state = PARSER_WAIT_VALUE;
				flags = 0;
				return state;
			}
			else if(c == '"')
			{
				flags = IN_DQUOTES;
				clearValue();
				appendValue(c);
				state = PARSER_VALUE;
				return state;
			}
			else if(c == '\'')
			{
				flags = IN_QUOTES;
				clearValue();
				appendValue(c);
				state = PARSER_VALUE;
				return state;
			}
			else if(c == '}' || c == ']')
			{
				if(level <= 0)
				{
					if(c == '}')
						state = PARSER_FINISHED;
					else
						state = PARSER_ERROR;
					return state;
				}
				level--;
				levels >>= 1;
				state = PARSER_WAIT_SEPARATOR;
				return state;
			}
			else
			{
				flags = 0;
				clearValue();
				appendValue(c);
				state = PARSER_VALUE;
				return state;
			}
			
		case PARSER_VALUE:
			
			if(flags & IN_BACKSLASH)
			{
				flags &= ~IN_BACKSLASH;
				appendValue(c);
				return state;
			}
			else if(c == '\\')
			{
				flags |= IN_BACKSLASH;
				return state;
			}
			else if( ((c == '"') && (flags & IN_DQUOTES)) || ((c == '\'') && (flags & IN_QUOTES)))
			{
				flags = 0;
				appendValue(c);
				doCallback();
				state = PARSER_WAIT_SEPARATOR;
				return state;
			}
			else if( (flags & IN_QUOTES) || (flags & IN_DQUOTES))
			{
				appendValue(c);
				return state;
			}
			else if(isalnum(c) || c == '_' || c == '.' || c == '-')
			{
				appendValue(c);
				return state;
			}
			else if(c == ',')
			{
				flags = 0;
				doCallback();
				if(levels &0x01)
					state = PARSER_WAIT_VALUE;
				else
					state = PARSER_WAIT_NAME;
				return state;
			}
			else if(isspace(c))
			{
				flags = 0;
				doCallback();
				state = PARSER_WAIT_SEPARATOR;
				return state;
			}
			else if(c == '}' || c == ']')
			{
				if(level <= 0)
				{
					if(c == '}')
						state = PARSER_FINISHED;
					else
						state = PARSER_ERROR;
					return state;
				}
				doCallback();
				level--;
				levels = levels >> 1;
				state = PARSER_WAIT_SEPARATOR;
				return state;
			}
			else
			{
Example #8
0
File: main.cpp Project: CCJY/coliru
 BadResultCode(ResultCode result_code) : Exception(static_cast<uint32_t>(result_code))
 {
     appendName("BadResultCode");
 }
Example #9
0
File: main.cpp Project: CCJY/coliru
 ConnectionError(const std::string& host, int port) :
     Exception(host + ":" + std::to_string(port))
 {
     appendName("ConnectionError");
 }