Exemple #1
0
/* Save real number arg in DICT. If not fractional save as integer. */
void cfwDictSaveReal(DICT *dict, float r) {
    char buf[50];
    int value;          /* Current nibble value */
    int last = 0;       /* Last nibble value */
    int odd = 0;        /* Flags odd nibble */
    long i = (long)r;

    if (i == r) {
        /* Value was integer */
        cfwDictSaveInt(dict, i);
        return;
    }

    /* Convert to string; 8 digits of precision is enough to accurately
       represent the matrix of a typical TrueType font using a 2048 unit em */
    ctuDtostr(buf, r, 0, 8);

    *dnaNEXT(*dict) = cff_BCD;
    for (i = buf[0] == '0';; i++) {
        switch (buf[i]) {
        case '\0':
            /* Terminate number */
            *dnaNEXT(*dict) = odd ? last << 4 | 0xf : 0xff;
            return;

        case '+':
            continue;

        case '-':
            value = 0xe;
            break;

        case '.':
            value = 0xa;
            break;

        case 'E':
        case 'e':
            value = (buf[++i] == '-') ? 0xc : 0xb;
            break;

        default:
            value = buf[i] - '0';
            break;
        }

        if (odd) {
            *dnaNEXT(*dict) = last << 4 | value;
        }
        else {
            last = value;
        }
        odd = !odd;
    }
}
Exemple #2
0
/* Save real number arg in DICT. If not fractional save as integer. */
void cfwDictSaveReal(DICT *dict, float r) {
	char buf[50];
	int value;          /* Current nibble value */
	int last = 0;       /* Last nibble value */
	int odd = 0;        /* Flags odd nibble */
	long i = (long)r;

	if (i == r) {
		/* Value was integer */
		cfwDictSaveInt(dict, i);
		return;
	}

	ctuDtostr(buf, r, 0, 8); /* 8 places is as good as it gets when converting ASCII real numbers->float-> ASCII real numbers, as happens to all the  PrivateDict values.*/

	*dnaNEXT(*dict) = cff_BCD;
	for (i = buf[0] == '0';; i++) {
		switch (buf[i]) {
			case '\0':
				/* Terminate number */
				*dnaNEXT(*dict) = odd ? last << 4 | 0xf : 0xff;
				return;

			case '+':
				continue;

			case '-':
				value = 0xe;
				break;

			case '.':
				value = 0xa;
				break;

			case 'E':
			case 'e':
				value = (buf[++i] == '-') ? 0xc : 0xb;
				break;

			default:
				value = buf[i] - '0';
				break;
		}

		if (odd) {
			*dnaNEXT(*dict) = last << 4 | value;
		}
		else {
			last = value;
		}
		odd = !odd;
	}
}
Exemple #3
0
unsigned short addGlyphMarkClassGDEF(hotCtx g, GNode *markClassNode)
	{
	int i;
	unsigned char classIndex = 0;
	GNode *markNode;
	GDEFCtx h = g->ctx.GDEF;
	
	for (i = 0; i < h->markAttachClasses.cnt; i++)
		{
		markNode = *((GNode**) dnaINDEX( h->markAttachClasses, i));
		if (markClassNode == markNode)
			{
			classIndex = i+1; /* GDEF MarkAttachment class index starts at 1, not 0. */
			break;
			}
		}
	
	if (classIndex == 0)
		{
		GNode **nextMarkClass;
		if ( h->markAttachClasses.cnt > kMaxMarkAttachClasses)
			return kMaxMarkAttachClasses + 1; /* trigger error msg in caller of this function */
			
		nextMarkClass = dnaNEXT(h->markAttachClasses);
		*nextMarkClass = markClassNode;
		classIndex = (unsigned char) h->markAttachClasses.cnt;
		}
		
	return classIndex;
	}
Exemple #4
0
static LOffset  createMarkSetClassDef(GDEFCtx h, hotCtx g)
	{
	int i;
	Offset size = (Offset)MARK_SET_TABLE_SIZE(h->markSetClasses.cnt);
	h->markSetClassTable.MarkSetTableFormat = 1;
	h->markSetClassTable.MarkSetCount = (unsigned short)h->markSetClasses.cnt;
	dnaINIT(g->dnaCtx, h->markSetClassTable.markSetEntries, h->markSetClasses.cnt, 10);
	for (i = 0; i < h->markSetClasses.cnt; i++)
		{
		GNode * p;
		otlTbl otl;
		MarkSetEntry* markSetEntry;
		GNode* srcNode = h->markSetClasses.array[i];
		GNode* headNode;
		markSetEntry = dnaNEXT(h->markSetClassTable.markSetEntries);
		otl = otlTableNew(g);
		markSetEntry->otl = otl;
		
		featGlyphClassCopy(g, &headNode, srcNode);
		featGlyphClassSort(g, &headNode, 1, 1);
		otlCoverageBegin(g, otl);

		for (p = headNode; p != NULL; p = p->nextCl)
			otlCoverageAddGlyph(g, otl,  p->gid);
		otlCoverageEnd(g, otl);	
		
		markSetEntry->MarkSetCoverage = size;
		size  += (Offset)otlGetCoverageSize(otl);
		featRecycleNodes(g, headNode); /* Don't need this class any more*/
		h->markSetClasses.array[i] = NULL;
		}
		
	return size;
	}
Exemple #5
0
/* Add curve to path. */
static void glyphCurve(abfGlyphCallbacks *cb,
                       float x1, float y1,
                       float x2, float y2,
                       float x3, float y3) {
    OpRec *opRec;
    ufwCtx h = cb->direct_ctx;
    h->path.x = x3;
    h->path.y = y3;

    if (h->err.code != 0)
        return; /* Pending error */
    else if (h->path.state != 3) {
        /* Call sequence error */
        h->err.code = ufwErrBadCall;
        return;
    }

    opRec = dnaNEXT(h->path.opList);
    opRec->opType = curvetoType;
    opRec->coords[0] = x1;
    opRec->coords[1] = y1;
    opRec->coords[2] = x2;
    opRec->coords[3] = y2;
    opRec->coords[4] = x3;
    opRec->coords[5] = y3;
}
Exemple #6
0
unsigned short addMarkSetClassGDEF(hotCtx g, GNode *markClassNode)
	{
	int i;
	unsigned char classIndex = 0;
	GNode *markNode;
	GDEFCtx h = g->ctx.GDEF;
	
	for (i = 0; i < h->markSetClasses.cnt; i++)
		{
		markNode = *((GNode**) dnaINDEX( h->markSetClasses, i));
		if (markClassNode == markNode)
			{
			classIndex = i+1; /* so that 0 means no value was assigned. */
			break;
			}
		}
	
	if (classIndex == 0)
		{
		GNode **nextMarkClass = dnaNEXT(h->markSetClasses);
		*nextMarkClass = markClassNode;
		classIndex = (unsigned char)h->markSetClasses.cnt;
		}
	return classIndex - 1;
	}
Exemple #7
0
/* Add move to path. */
static void glyphMove(abfGlyphCallbacks *cb, float x0, float y0) {
    OpRec *opRec;
    ufwCtx h = cb->direct_ctx;
    h->path.x = x0;
    h->path.y = y0;

    if (h->err.code != 0)
        return; /* Pending error */
    else if (h->path.state < 2) {
        /* Call sequence error */
        h->err.code = ufwErrBadCall;
        return;
    }

    if (h->path.state == 3) {
        /* Write previous path. */
        writeContour(h);
    } else if (h->path.state < 3) {
        /* First path data seen in glyph */
        writeLine(h, "\t<outline>");
    } else if (h->path.state > 3) {
        /* Call sequence error */
        h->err.code = ufwErrBadCall;
        return;
    }
    opRec = dnaNEXT(h->path.opList);
    opRec->opType = movetoType;
    opRec->coords[0] = x0;
    opRec->coords[1] = y0;

    h->path.state = 3;
}
Exemple #8
0
int addLigCaretEntryGDEF(hotCtx g, GNode* glyphNode, unsigned short caretValue, unsigned short format)
	{
	int i;
	LigGlyphEntry *lge = NULL;
	GID gid = glyphNode->gid;
	GDEFCtx h = g->ctx.GDEF;
	int seenCaretValue = 0;
	/* See if we can find matching GID entry in the attach point list.*/
	i = 0;
	while (i <  h->ligCaretEntries.cnt)
		{
		if  (h->ligCaretEntries.array[i].gid == gid)
			{
			unsigned short j;
			CaretTable *ct;
			lge = &h->ligCaretEntries.array[i];
			/* make sure the contour isn't already in the list. */
			for (j = 0; j < lge->caretTables.cnt; j++)
				if (lge->caretTables.array[j].CaretValue == caretValue)
					{
					seenCaretValue = 1;
					break;
					}
			if (!seenCaretValue)
				{
				ct = dnaNEXT(lge->caretTables);
				ct->format = format;
				ct->CaretValue = caretValue;
				}
			break;
			}
		i++;
		}
	if (lge == NULL)
		{
		CaretTable *ct;
		lge = dnaNEXT(h->ligCaretEntries);
		lge->gid = gid;
		dnaINIT(g->dnaCtx, lge->caretTables, 10, 10);
		ct = dnaNEXT(lge->caretTables);
		ct->format = format;
		ct->CaretValue = caretValue;
		}
	return seenCaretValue;
	}
Exemple #9
0
int addAttachEntryGDEF(hotCtx g, GNode* glyphNode, unsigned short contour)
	{
	int i;
	AttachEntry *attachEntry = NULL;
	GID gid = glyphNode->gid;
	GDEFCtx h = g->ctx.GDEF;
	int seenContour = 0;
	/* See if we can find matching GID entry in the attach point list.*/
	i = 0;
	while (i <  h->attachEntries.cnt)
		{
		if  (h->attachEntries.array[i].gid == gid)
			{
			unsigned short j, *indexEntry;
			attachEntry = &h->attachEntries.array[i];
			/* make sure the contour isn't already in the list. */
			for (j = 0; j < attachEntry->contourIndices.cnt; j++)
				if (attachEntry->contourIndices.array[j] == contour)
					{
					seenContour = 1;
					break;
					}
			if (!seenContour)
				{
				indexEntry = dnaNEXT(attachEntry->contourIndices);
				*indexEntry = contour;
				}
			break;
			}
		i++;
		}
	if (attachEntry == NULL)
		{
		unsigned short *indexEntry;
		attachEntry = dnaNEXT(h->attachEntries);
		attachEntry->gid = gid;
		dnaINIT(g->dnaCtx, attachEntry->contourIndices, 10, 10);
		indexEntry = dnaNEXT(attachEntry->contourIndices);
		*indexEntry = contour;
		}
	return seenContour;
	}
Exemple #10
0
/* Add font to set */
void tcAddFont(tcCtx g, long flags) {
    tcprivCtx h = g->ctx.tcpriv;
    Font *font = dnaNEXT(h->set);

    if (flags & TC_SMALLMEMORY && g->cb.tmpOpen == NULL) {
        tcFatal(g, "callbacks not supplied for SMALLMEMORY mode");
    }

    g->flags = flags;
    font->filename = (g->cb.psId == NULL) ? "?" : g->cb.psId(g->cb.ctx);
    parseFont(g, font);
}
Exemple #11
0
/* Add line to path. */
static void glyphLine(abfGlyphCallbacks *cb, float x1, float y1) {
    OpRec *opRec;
    ufwCtx h = cb->direct_ctx;
    float dx1 = x1 - h->path.x;
    float dy1 = y1 - h->path.y;
    h->path.x = x1;
    h->path.y = y1;

    if (h->err.code != 0)
        return; /* Pending error */
    else if (h->path.state != 3) {
        /* Call sequence error */
        h->err.code = ufwErrBadCall;
        return;
    }

    opRec = dnaNEXT(h->path.opList);
    opRec->opType = linetoType;
    opRec->coords[0] = x1;
    opRec->coords[1] = y1;
}
Exemple #12
0
/* Add encoding to accumulator if unique and return index */
int encodingAdd(tcCtx g, int nCodes, unsigned char *code,
				int nSups, CodeMap *supplement)
	{
	encodingCtx h = g->ctx.encoding;
	int i;
	Encoding *encoding;

	for (i = 0; i < h->encodings.cnt; i++)
		{
		encoding = &h->encodings.array[i];
		if (nCodes == encoding->nCodes && nSups == encoding->nSups)
			{
			int j;
			for (j = 0; j < nCodes; j++)
				if (code[j] != encoding->code[j])
					goto mismatch;
			for (j = 0; j < nSups; j++)
				if (supplement[j].code != encoding->supplement[j].code ||
					supplement[j].sid != encoding->supplement[j].sid)
					goto mismatch;
			return PREDEF_CNT + i;	/* Found match */
		mismatch:
			;
			}
		}
	/* No match found; add encoding */
	encoding = dnaNEXT(h->encodings);
	encoding->nCodes = nCodes;
	encoding->code = MEM_NEW(g, nCodes);
	COPY(encoding->code, code, nCodes);
	encoding->nSups = nSups;
	if (nSups > 0)
		{
		encoding->supplement = MEM_NEW(g, nSups * sizeof(CodeMap));
		COPY(encoding->supplement, supplement, nSups);
		}

	return PREDEF_CNT + h->encodings.cnt - 1;
	}
/* Add supplementary code point to encoding. */
void cfwEncodingAddSupCode(cfwCtx g, unsigned char code, SID sid) {
    encodingCtx h = g->ctx.encoding;
    SupCode *sup = dnaNEXT(h->_new->supcodes);
    sup->code = code;
    sup->sid = sid;
}
/* Add code point to encoding. */
void cfwEncodingAddCode(cfwCtx g, unsigned char code) {
    encodingCtx h = g->ctx.encoding;
    *dnaNEXT(h->_new->codes) = code;
}
/* Begin new encoding. */
void cfwEncodingBeg(cfwCtx g) {
    encodingCtx h = g->ctx.encoding;
    h->_new = dnaNEXT(h->encodings);
    h->_new->codes.cnt = 0;
    h->_new->supcodes.cnt = 0;
}
Exemple #16
0
/* Save dict operator. */
void cfwDictSaveOp(DICT *dict, int op) {
	if (op & 0xff00) {
		*dnaNEXT(*dict) = cff_escape;
	}
	*dnaNEXT(*dict) = (unsigned char)op;
}
Exemple #17
0
/* Begin new glyph definition. */
static int glyphBeg(abfGlyphCallbacks *cb, abfGlyphInfo *info) {
    ufwCtx h = cb->direct_ctx;
    char buf[9];
    char glyphName[MAX_UFO_GLYPH_NAME];
    char glifName[MAX_UFO_GLYPH_NAME];
    char glifRelPath[FILENAME_MAX];
    Glyph *glyphRec;

    cb->info = info;

    if (h->err.code != 0)
        return ABF_FAIL_RET; /* Pending error */
    else if (h->path.state != 0) {
        /* Call sequence error */
        h->err.code = ufwErrBadCall;
        return ABF_FAIL_RET;
    } else if (info->flags & ABF_GLYPH_SEEN)
        return ABF_SKIP_RET; /* Ignore duplicate glyph */

    if (info->flags & ABF_GLYPH_CID) {
        h->lastiFD = info->iFD;
        sprintf(glyphName, "cid%05hu", info->cid);
    } else {
        sprintf(glyphName, "%s", info->gname.ptr);
        sprintf(glifName, "%s", info->gname.ptr);
    }

    mapGlyphToGLIFName(glyphName, glifName);

    /* Initialize */
    h->path.x = 0;
    h->path.y = 0;
    h->path.state = 1;

    DURING_EX(h->err.env)

    /* Open GLIF file as dst stream */
    sprintf(glifRelPath, "%s/%s", h->arg.glyphLayer, glifName);
    h->cb.stm.clientFileName = glifRelPath;
    h->stm.dst = h->cb.stm.open(&h->cb.stm, UFW_DST_STREAM_ID, 0);
    if (h->stm.dst == NULL)
        fatal(h, ufwErrDstStream);
    // write start of GL:IF file and open glyph element.
    writeLine(h, XML_HEADER);
    writeStr(h, "<glyph");

    // write glyph name
    writeStr(h, " name=\"");
    writeStr(h, glyphName);
    writeStr(h, "\"");

    // close glyph element
    writeLine(h, " format=\"1\" >");

    // write encoding, if present.

    if (info->flags & ABF_GLYPH_UNICODE) {
        writeStr(h, "\t<unicode hex=\"");
        sprintf(buf, "%06lX", info->encoding.code);
        writeStr(h, buf);
        writeLine(h, "\"/>");
    }

    glyphRec = dnaNEXT(h->glyphs);
    strcpy(glyphRec->glyphName, glyphName);
    strcpy(glyphRec->glifFileName, glifName);

    HANDLER

    return Exception.Code;

    END_HANDLER

    return ABF_CONT_RET;
}
Exemple #18
0
/* Add anonymous table to list */
void anonAddTable(hotCtx g, unsigned long tag, hotAnonRefill refill) {
    anonCtx h = g->ctx.anon;
    AnonTbl *tbl = dnaNEXT(h->tbls);
    tbl->tag = tag;
    tbl->refill = refill;
}
Exemple #19
0
/* Split font set file into arg list */
static void makeArgs(char *filename) {
	int state;
	long i;
	long length;
	File file;
	char *start = NULL;	/* Suppress optimizer warning */

	/* Read whole file into buffer */
	fileOpen(&file, cbctx, filename, "r");
	fileSeek(&file, 0, SEEK_END);

	length = fileTell(&file);
	script.buf = cbMemNew(cbctx, length + 1);

	fileSeek(&file, 0, SEEK_SET);
	fileReadN(&file, length, script.buf);
	fileClose(&file);

	script.buf[length] = '\n';	/* Ensure termination */

	/* Parse buffer into args */
	state = 0;
	for (i = 0; i < length + 1; i++) {
		int c = script.buf[i];
		switch (state) {
			case 0:
				switch (c) {
					case ' ':
					case '\n':
					case '\t':
					case '\r':
					case '\f':
						break;

					case '#':
						state = 1;
						break;

					case '"':
						start = &script.buf[i + 1];
						state = 2;
						break;

					default:
						start = &script.buf[i];
						state = 3;
						break;
				}
				break;

			case 1:	/* Comment */
				if (c == '\n' || c == '\r') {
					state = 0;
				}
				break;

			case 2:	/* Quoted string */
				if (c == '"') {
					script.buf[i] = '\0';	/* Terminate string */
					*dnaNEXT(script.args) = start;
					state = 0;
				}
				break;

			case 3:	/* Space-delimited string */
				if (isspace(c)) {
					script.buf[i] = '\0';	/* Terminate string */
					*dnaNEXT(script.args) = start;
					state = 0;
				}
				break;
		}
	}
}
Exemple #20
0
void setGlyphClassGDef(hotCtx g, GNode *simple, GNode *ligature, GNode *mark,
								 GNode *component)
	{
	GDEFCtx h = g->ctx.GDEF;
	GNode **simpleClass = dnaNEXT(h->glyphClasess);
	GNode **ligClass = dnaNEXT(h->glyphClasess);
	GNode **markClass = dnaNEXT(h->glyphClasess);
	GNode **compClass = dnaNEXT(h->glyphClasess);
	int hadConflictingClassDef = 0;
	
	char* glyphClassNames[] = {"Base", "Ligature", "Mark","Component"};
	
	long i,j;

	if (simple == NULL)
		*simpleClass = NULL;
	else
		 *simpleClass = simple;
	if (ligature == NULL)
		*ligClass = NULL;
	else
		 *ligClass = ligature;
		
	if (mark == NULL)
		*markClass = NULL;
	else
		 *markClass = mark;
		
	if (component == NULL)
		*compClass = NULL;
	else
		 *compClass = component;

	
	/* Check and warn if the same glyph has ended up in more than one class */
	for (i = 0; i < h->glyphClasess.cnt; i++)
		{
		GNode *p1;
		GNode *prev1 = NULL;
		GNode *headNode1 = h->glyphClasess.array[i];
		if (headNode1 == NULL)
			continue;

		for (j = i+1; j < h->glyphClasess.cnt; j++)
			{
			GNode *p2;
			GNode *headNode2 = h->glyphClasess.array[j];
			if (headNode2 == NULL)
				continue;
			for (p1 = headNode1; p1 != NULL;)
				{
				GNode *prev2 = NULL;
				unsigned int removedP1 = 0;
				for (p2 = headNode2; p2 != NULL;)
					{
					if (p1->gid == p2->gid)
						{
						if (j != 2)
							{
							// remove glyph from current class.
							if (i != 2) /* If the gid in class j is being overridden by the mark class definition, then we do not complain */
								{
								hadConflictingClassDef = 1;
								featGlyphDump(g, p1->gid, 0, 0);
								hotMsg(g, hotWARNING, "GDEF GlyphClass. Glyph '%s' gid '%d'. previous glyph class '%s' overrides new class '%s'.", g->note.array, p1->gid, glyphClassNames[i],  glyphClassNames[j]);
								}
								removeNodeFromClass(h, &(h->glyphClasess.array[j]), &headNode2, &prev2, &p2);
							}
						else
							{
							// class j is the mark class; we need to remove p1 from the glyph class i. We do this silently, as the mark class always supersedes other classes.
								removeNodeFromClass(h, &(h->glyphClasess.array[i]), &headNode1, &prev1, &p1);
								removedP1 = 1;
							}

						}
					else
						{
						prev2 = p2;
						p2 = p2->nextCl;
						}
						
					if (p1 == NULL)
						break; /* This can happen because all teh p1's get removed by mark class overrides above */
					}
				if (!removedP1)
				{
				prev1 = p1;
				if (p1 != NULL)
					p1 = p1->nextCl;
				}
				}
			
			}
		}
		if (hadConflictingClassDef)
		 {
			hotMsg(g, hotWARNING, "GDEF Glyph Class. Since there were conflicting GlyphClass assignments, you should examine this auto-built GDEF table, and make sure that the glyph class assignments are as needed. If not, you should specify the GDEF table explicitly, in the features file.\n");
		 }
	
	
	}