Beispiel #1
0
void swf_Render_Delete(RENDERBUF*dest)
{
    renderbuf_internal*i = (renderbuf_internal*)dest->internal;
    int y;
    bitmap_t*b = i->bitmaps;
    
    /* delete canvas */
    rfx_free(i->zbuf);
    rfx_free(i->img);
    
    /* delete line buffers */
    for(y=0;y<i->height2;y++) {
        swf_DeleteTag(0, i->lines[y].points);
        i->lines[y].points = 0;
    }
    
    /* delete bitmaps */
    while(b) {
        bitmap_t*next = b->next;
        free(b->data);b->data=0;
        rfx_free(b);
        b = next;
    }
    
    rfx_free(i->lines); i->lines = 0;
    rfx_free(dest->internal); dest->internal = 0;
}
Beispiel #2
0
void swf_ActionFree(ActionTAG*action)
{
    if(!action) {
	return;
    }
    action = action->parent;
    if(!action) {
	fprintf(stderr, "Warning: freeing zero action (no parent)");
	return;
    }

    while(action)
    {
	ActionTAG*tmp;
	if(action->data && action->data != action->tmp) {
	    rfx_free(action->data);
	    action->data = 0;
	}
	action->len = 0;
	
	tmp = action;
	action=action->next;
	rfx_free(tmp);
    }
}
GRADIENT* interpolateGradient(GRADIENT* g1, GRADIENT* g2, float fraction, interpolation_t* inter)
{
    int i;
    GRADIENT g;
    g.ratios = rfx_calloc(16*sizeof(U8));
    g.rgba = rfx_calloc(16*sizeof(RGBA));

    if (g1->num > g2->num)
    {
    	copyGradient(&g, g2);
    	growGradient(&g, g1->num);
    	GRADIENT* result = interpolateNodes(g1, &g, fraction, inter);
    	rfx_free(g.rgba);
    	rfx_free(g.ratios);
    	return result;
    }
    else
    	if (g1->num < g2->num)
    	{
    	    copyGradient(&g, g1);
    	    growGradient(&g, g2->num);
    	    GRADIENT* result = interpolateNodes(&g, g2, fraction, inter);
    	    rfx_free(g.rgba);
    	    rfx_free(g.ratios);
    	    return result;
    	}
    	else
    	    return interpolateNodes(g1, g2, fraction, inter);
}
void gfxline_free(gfxline_t*l)
{
    if(l && (l+1) == l->next) {
	/* flattened */
	rfx_free(l);
    } else {
	gfxline_t*next;
	while(l) {
	    next = l->next;
	    l->next = 0;
	    rfx_free(l);
	    l = next;
	}
    }
}
static void* linedraw_result(gfxdrawer_t*d)
{
    linedraw_internal_t*i = (linedraw_internal_t*)d->internal;
    void*result = (void*)i->start;
    rfx_free(i);
    memset(d, 0, sizeof(gfxdrawer_t));
    return result;
}
Beispiel #6
0
int swf_FreeTags(SWF* swf)
{
int tag_counter;
TAG* t;
TAG* tnew;

	t = swf->firstTag;

	tag_counter = 0;
	while(t)
	{
		tag_counter++;
		tnew = t->next;
		if(t->data) rfx_free(t->data);
		rfx_free(t);
		t = tnew;
	}
	swf->firstTag = 0;

	return tag_counter;
}
Beispiel #7
0
static void swf_ShapeDrawerClear(drawer_t*draw)
{
    SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
    if(sdraw->tagfree) {
	swf_DeleteTag(0, sdraw->tag);
	sdraw->tag = 0;
    }
    swf_ShapeFree(sdraw->shape);
    sdraw->shape = 0;

    rfx_free(draw->internal);
    draw->internal = 0;
}
void gfxline_optimize(gfxline_t*line)
{
    gfxline_t*l = line;
    /* step 1: convert splines to lines, where possible */
    double x=0,y=0;
    while(l) {
	if(l->type == gfx_splineTo && splineIsStraight(x,y,l)) {
	    l->type = gfx_lineTo;
	}
	x = l->x;
	y = l->y;
	l = l->next;
    }
    /* step 2: combine adjacent lines and splines, where possible */
    l = line;
    while(l && l->next) {
	gfxline_t*next = l->next;
	char combine = 0;
	double sx=0,sy=0;
	if(l->type == gfx_lineTo && next->type == gfx_lineTo) {
	    double dx = l->x-x;
	    double dy = l->y-y;
	    double nx = next->x-l->x;
	    double ny = next->y-l->y;
	    if(fabs(dx*ny - dy*nx) < 0.000001 && (dx*nx + dy*ny) >= 0) {
		combine = 1;
	    }
	} else if(l->type == gfx_splineTo && next->type == gfx_splineTo) {
	    /* TODO */
	}
	if(combine) {
	    l->next = next->next;
	    next->next = 0;
	    l->x = next->x;
	    l->y = next->y;
	    l->sx = sx;
	    l->sy = sy;
	    rfx_free(next);
	} else {
	    x = l->x;
	    y = l->y;
	    l = l->next;
	}
    }
}
Beispiel #9
0
static void maketransparent_fillbitmap(gfxfilter_t*f, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform, gfxdevice_t*out)
{
    internal_t*i = (internal_t*)f->internal;
    gfximage_t img2;
    img2.width = img->width;
    img2.height = img->height;
    img2.data = (gfxcolor_t*)rfx_alloc(img->width*img->height*4);
    int x,y; 
    for(y=0;y<img->height;y++)  {
	gfxcolor_t*in = &img->data[y*img->width];
	gfxcolor_t*out = &img2.data[y*img->width];
	for(x=0;x<img->width;x++) {
	    out[x] = transform_color(i, &in[x]);
	}
    }
    out->fillbitmap(out, line, &img2, matrix, cxform);
    rfx_free(img2.data);
}
Beispiel #10
0
ActionTAG* swf_ActionCompile(const char* source, int version)
{
    TAG* tag;
    ActionTAG* a = 0;
    void*buffer = 0;
    int len = 0;
    int ret;
    
    tag = swf_InsertTag(NULL, ST_DOACTION);
    ret = compileSWFActionCode(source, version, &buffer, &len);
    if(!ret || buffer==0 || len == 0)
	return 0;

    swf_SetBlock(tag, (U8*)buffer, len);
    swf_SetU8(tag, 0);

    rfx_free(buffer);

    a = swf_ActionGet(tag);
    swf_DeleteTag(0, tag);
    return a;
}
Beispiel #11
0
void swf_RenderShape(RENDERBUF*dest, SHAPE2*shape, MATRIX*m, CXFORM*c, U16 _depth,U16 _clipdepth)
{
    //    renderbuf_internal*i = (renderbuf_internal*)dest->internal;
    
    SHAPELINE*line;
    int x=0,y=0;
    MATRIX mat = *m;
    SHAPE2* s2 = 0;
    SHAPE2* lshape = 0;
    renderpoint_t p, lp;
    U32 clipdepth;
    double widthmultiply = matrixsize(m);
    
    memset(&p, 0, sizeof(renderpoint_t));
    memset(&lp, 0, sizeof(renderpoint_t));
    
    clipdepth = _clipdepth? _clipdepth << 16 | 0xffff : 0;
    p.depth = _depth << 16;
    
    mat.tx -= dest->posx*20;
    mat.ty -= dest->posy*20;
    
    s2 = swf_Shape2Clone(shape);
    line = s2->lines;
    if(shape->numfillstyles) {
        int t;
        p.s = s2;
        /* multiply fillstyles matrices with placement matrix-
         important for texture and gradient fill */
        for(t=0;t<s2->numfillstyles;t++) {
            MATRIX nm;
            swf_MatrixJoin(&nm, &mat, &s2->fillstyles[t].m);
            /*nm.sx *= i->multiply;
             nm.sy *= i->multiply;
             nm.r0 *= i->multiply;
             nm.r1 *= i->multiply;
             nm.tx *= i->multiply;
             nm.ty *= i->multiply;*/
            s2->fillstyles[t].m = nm;
        }
    }
    
    if(shape->numlinestyles) {
        lshape = linestyle2fillstyle(shape);
        lp.s = lshape;
        lp.depth = (_depth << 16)+1;
    }
    
    
    while(line)
    {
        int x1,y1,x2,y2,x3,y3;
        
        if(line->type == moveTo)
        {
        }
        else if(line->type == lineTo)
        {
            transform_point(&mat, x, y, &x1, &y1);
            transform_point(&mat, line->x, line->y, &x3, &y3);
            
            if(line->linestyle && ! clipdepth)
            {
                lp.shapeline = &lshape->lines[line->linestyle-1];
                add_solidline(dest, x1, y1, x3, y3, shape->linestyles[line->linestyle-1].width * widthmultiply, &lp);
                lp.depth++;
            }
            if(line->fillstyle0 || line->fillstyle1)
            {
                assert(shape->numfillstyles);
                p.shapeline = line;
                add_line(dest, x1, y1, x3, y3, &p);
            }
        }
        else if(line->type == splineTo)
        {
            int c,t,parts;//,qparts;
            double xx,yy;
            
            transform_point(&mat, x, y, &x1, &y1);
            transform_point(&mat, line->sx, line->sy, &x2, &y2);
            transform_point(&mat, line->x, line->y, &x3, &y3);
            
            c = abs(x3-2*x2+x1) + abs(y3-2*y2+y1);
            xx=x1;
            yy=y1;
            
            parts = (int)(sqrt((float)c)/3);
            if(!parts) parts = 1;
            
            for(t=1;t<=parts;t++) {
                double nx = (double)(t*t*x3 + 2*t*(parts-t)*x2 + (parts-t)*(parts-t)*x1)/(double)(parts*parts);
                double ny = (double)(t*t*y3 + 2*t*(parts-t)*y2 + (parts-t)*(parts-t)*y1)/(double)(parts*parts);
                
                if(line->linestyle && ! clipdepth) {
                    lp.shapeline = &lshape->lines[line->linestyle-1];
                    add_solidline(dest, xx, yy, nx, ny, shape->linestyles[line->linestyle-1].width * widthmultiply, &lp);
                    lp.depth++;
                }
                if(line->fillstyle0 || line->fillstyle1) {
                    assert(shape->numfillstyles);
                    p.shapeline = line;
                    add_line(dest, xx, yy, nx, ny, &p);
                }
                
                xx = nx;
                yy = ny;
            }
        }
        x = line->x;
        y = line->y;
        line = line->next;
    }
    
    swf_Process(dest, clipdepth);
    
    if(s2)
    {
        swf_Shape2Free(s2);
        rfx_free(s2);s2=0;
    }
    
    if(lshape)
    {
        swf_Shape2Free(lshape);
        rfx_free(lshape);lshape=0;
    }
    
}
Beispiel #12
0
int swf_ActionEnumerate(ActionTAG*atag, char*(*callback)(char*), int type)
{
    int t;
    U8*data;
    char* cp;
    int count = 0;
    while(atag)
    {
	U16 poollen = 0;
	for(t=0;t<definedactions;t++)
	    if(actions[t].op == atag->op)
		break;

	if(t==definedactions) {
	    // unknown actiontag
	    atag = atag->next;
	    count++;
	    continue;
	}
	cp = actions[t].flags;
	data = atag->data;
	if(atag->len) {
	    while(*cp) {
		U8 * replacepos = 0;
		int replacelen = 0;
		U8 * replacement = 0;
		switch(*cp)
		{
		    case 'u': {
			if(type&TYPE_URL)
			{
			    replacelen = strlen((const char*)data);
			    replacepos = data;
			    replacement = (U8*)callback((char*)data); // may be null
			}
		    } break;
	    	    case 't': {
			if(type&TYPE_TARGET)
			{
			    replacelen = strlen((const char*)data);
			    replacepos = data;
			    replacement = (U8*)callback((char*)data); // may be null
			}
		    } break;
		    case 'c': {
		    	if(type&TYPE_STRING)
			{
			    replacelen = strlen((const char*)data);
			    replacepos = data;
			    replacement = (U8*)callback((char*)data); // may be null
			}
		    } break;
		    case 'C': {
			poollen = (data[0]+256*data[1]);
		    } break;
		    case 'o': {
		    } break;
		    case 'p': {
			U8 datatype = *data;
			char*value = (char*)&data[1];
			if(datatype == 0) { //string
			    if(type&TYPE_STRING)
			    {
				replacelen = strlen(value);
				replacepos = (U8*)value;
				replacement = (U8*)callback(value); // may be null
			    }
			} else if (datatype == 8) { //lookup
			}
		    } break;
		}
		data += OpAdvance(*cp, data);
		if(*cp!='c' || !poollen)
		    cp++;
		if(poollen)
		    poollen--;

		if(replacement)
		{
		    int newlen = strlen((const char *)replacement);
		    char * newdata = (char*)rfx_alloc(atag->len - replacelen + newlen);
		    int rpos = replacepos - atag->data;
		    memcpy(newdata, atag->data, rpos);
		    memcpy(&newdata[rpos], replacement, newlen);
		    memcpy(&newdata[rpos+newlen], &replacepos[replacelen],
			    &data[atag->len] - &replacepos[replacelen]);
		    rfx_free(atag->data);
		    atag->data = (U8*)newdata;
		    data = &atag->data[rpos+newlen+1];
		}
	    }
	}
	atag = atag->next;
	count ++;
    }
    return count;
}
Beispiel #13
0
/* TODO: * this should be in swfdump.c */
void swf_DumpActions(ActionTAG*atag, char*prefix) 
{
    int t;
    U8*data;
    char* cp;
    int entry = 0;
    char spaces[MAX_LEVELS*4+1];
    struct {
	char*text;
	int count;
    } counter[MAX_LEVELS];
    int countpos = 0;
#ifdef MAX_LOOKUP
    char * lookup[MAX_LOOKUP];
    memset(lookup,0x00,sizeof(lookup));
#endif
    memset(spaces, 32, sizeof(spaces));
    spaces[sizeof(spaces)-1] = 0;

   if (!prefix)
        prefix="";

    while(atag)
    {
	char*indent = &spaces[sizeof(spaces)-1-countpos*4];
	U16 poollen = 0;
	for(t=0;t<definedactions;t++)
	    if(actions[t].op == atag->op)
		break;

	if(t==definedactions) {
	    printf("%s (%5d bytes) action:%s unknown[%02x]", prefix, atag->len, indent, atag->op);
	} else {
	    printf("%s (%5d bytes) action:%s %s", prefix, atag->len, indent, actions[t].name);
	}
	data = atag->data;
	if(atag->len && t!=definedactions) //TODO: check for consistency: should we have a length?
	{
	  cp = actions[t].flags;
	  while(*cp)
	  {
	      switch(*cp)
	      {
		  case 'f': { //frame
		      printf(" %d", data[0]+256*data[1]);
		  } break;
		  case 'u': {
		      printf(" URL:\"%s\"", data);
		  } break;
		  case 't': {
		      printf(" Target:\"%s\"", data);
		  } break;
		  case 'l': {
		      printf(" Label:\"%s\"", data);
		  } break;
		  case 'c': {
		      printf(" String:\"%s\"", data);
#ifdef MAX_LOOKUP
		      if (entry<MAX_LOOKUP)
			lookup[entry++] = strdup((const char*)data);
#endif
		  } break;
		  case 'C': {
		      poollen = data[0]+256*data[1];
		      entry = 0;
		      printf("(%d entries)", poollen);
		  } break;
		  case 's': {
		      printf(" +%d", *data);
		  } break;
		  case 'm': {
		      //m: method (byte) url:(0=none, 1=get, 2=datat)/gf2:(1=play)
		      printf(" %d", *data);
		  } break;
		  case '{': {
		      U16 num;
		      U16 codesize;
		      int s = 0;
		      int t;
		      printf(" %s(", data);
		      while(data[s++]); //name
		      num = (data[s++]); //num
		      num += (data[s++])*256;
		      for(t=0;t<num;t++) {
			  printf("%s",data+s);  // 10/22/04 MD: added +s to
			  if(t<num-1)
			      printf(", ");
			  while(data[s++]); //param
		      }
		      printf(")");
		      codesize = (data[s++]); //num
		      codesize += (data[s++])*256;
		      printf(" codesize:%d ",codesize);
		      printf("\n%s                       %s{", prefix, indent);
		      if(countpos>=15) {
			  printf("Error: nested too deep\n");
			  continue;
		      }
		      counter[countpos].text = "}";
		      counter[countpos].count = codesize + ATAG_FULLLENGTH(atag);
		      countpos++;
		  } break;
		  case 'o': {
		      int t;
		      U16 codesize = data[0]+256*data[1];
		      printf(" codesize:%d ", codesize);

		      /* the following tries to find the "string"
			 the flash documentation speaks of- I've
			 never actually seen one yet. -mk */
		      for(t=2;t<atag->len;t++)
			  printf("[%02x]", atag->data[t]);

		      printf("\n%s                       %s{", prefix, indent);
		      if(countpos>=15) {
			  printf("Error: nested too deep\n");
			  continue;
		      }
		      counter[countpos].text = "}";
		      counter[countpos].count = codesize + ATAG_FULLLENGTH(atag);
		      countpos++;
		  } break;
		  case 'b': {
		      printf(" %d", data[0]+256*(signed char)data[1]);
		  } break;
		  case 'r': {
		      printf(" %d", data[0]);
		  } break;
		  case 'p': {
		      U8 type = *data;
		      unsigned char*value = data+1;
		      if(type == 0) {
			  printf(" String:\"%s\"", value);
		      } else if (type == 1) {
			  U32 f = value[0]+(value[1]<<8)+
				  (value[2]<<16)+(value[3]<<24);
			  printf(" Float:%f", *(float*)&f);
		      } else if (type == 2) {
			  printf(" NULL");
		      } else if (type == 3) {
			  printf(" Undefined");
		      } else if (type == 4) {
			  printf(" register:%d", *value);
		      } else if (type == 5) {
			  printf(" bool:%s", *value?"true":"false");
		      } else if (type == 6) {
			  U8 a[8];
			  memcpy(&a[4],value,4);
			  memcpy(a,&value[4],4);
#ifdef WORDS_BIGENDIAN
			  int t;
			  for(t=0;t<4;t++) {
			      U8 tmp = a[t];
			      a[t]=a[7-t];
			      a[7-t] = tmp;
			  }
#endif
			  printf(" double:%f", *(double*)a);
		      } else if (type == 7) {
			  printf(" int:%d", value[0]+(value[1]<<8)+
					    (value[2]<<16)+(value[3]<<24));
		      } else if (type == 8) {
			  printf(" Lookup:%d", *value);
#ifdef MAX_LOOKUP
			  if (lookup[*value])
			    printf(" (\"%s\")",lookup[*value]);
#endif
		      } else if (type == 9) {
			  U32 offset = value[0]+(value[1]<<8);
			  printf(" Lookup16:%d", offset);
#ifdef MAX_LOOKUP
			  if (lookup[offset])
			    printf(" (\"%s\")",lookup[offset]);
#endif
		      } else {
			  printf(" UNKNOWN[%02x]",type);
		      }
		  } break;
	      }
	      data += OpAdvance(*cp, data);
	      if((*cp!='c' || !poollen) &&
		 (*cp!='p' || !(data<&atag->data[atag->len])))
		  cp++;
	      if(poollen)
		  poollen--;
	  }
	}

	if(data < atag->data + atag->len)
	{
	    int nl = ((atag->data+atag->len)-data);
	    int t;
	    printf(" (remainder of %d bytes:\"", nl);
	    for(t=0;t<nl;t++) {
		if(data[t]<32)
		    printf("\\%d",data[t]);
		else
		    printf("%c", data[t]);
	    }
	    printf("\")");
	}
	printf("\n");

	for(t=0;t<countpos;t++) {
	    counter[t].count -= ATAG_FULLLENGTH(atag);
	    if(counter[t].count < 0) {
		printf("===== Error: Oplength errors =====\n");
		countpos = 0;
		break;
	    }
	}

	while(countpos && !counter[countpos-1].count)
	{
	    printf("%s                   %s%s\n", 
		prefix, indent, counter[countpos-1].text);
	    indent += 4;
	    countpos--;
	}

	atag = atag->next;
    }

#ifdef MAX_LOOKUP
  for (t=0;t<MAX_LOOKUP;t++) if (lookup[t]) rfx_free(lookup[t]);
#endif
}
Beispiel #14
0
SWFFONT* swf_LoadT1Font(const char*filename)
{
    SWFFONT * font;
    int nr;
    float angle,underline;
    char*fontname,*fullname,*familyname;
    BBox bbox;
    int s,num;
    char**charnames;
    char**charname;
    char*encoding[256];
    int c;
    int t;

    if(!t1lib_initialized) {
	T1_SetBitmapPad(16);
	if ((T1_InitLib(NO_LOGFILE)==NULL)){
	    fprintf(stderr, "Initialization of t1lib failed\n");
	    return 0;
	}
	t1lib_initialized = 1;
    }
    nr = T1_AddFont(filename);
    T1_LoadFont(nr);

    charnames = T1_GetAllCharNames(nr);
    if(!charnames) {
	fprintf(stderr, "No Charnames record- not a Type1 Font?\n");
	return 0;
    }

    angle = T1_GetItalicAngle(nr);
    fontname = T1_GetFontName(nr);
    fullname = T1_GetFullName(nr);
    familyname = T1_GetFamilyName(nr);
    underline = T1_GetUnderlinePosition(nr);
    bbox = T1_GetFontBBox(nr);

    font = (SWFFONT*)rfx_calloc(sizeof(SWFFONT));

    font->version = 2;
    if(fontname) 
	font->name = (U8*)strdup(fontname);
    else 
	font->name = 0;
    font->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT));

    num = 0;
    charname = charnames;
    while(*charname) {
	charname++;
	if(num<256) {
	    if(*charname) encoding[num] = strdup(*charname);
	    else          encoding[num] = strdup(".notdef");
	}
	num++;
    }
    for(t=num;t<256;t++)
	encoding[t] = strdup(".notdef");
    
    //T1_ReencodeFont(nr, encoding);

    font->maxascii = num;
    font->numchars = num;
    
    font->style = (/*bold*/0?FONT_STYLE_BOLD:0) + (angle>0.05?FONT_STYLE_ITALIC:0);

    font->glyph = (SWFGLYPH*)rfx_calloc(num*sizeof(SWFGLYPH));
    font->glyph2ascii = (U16*)rfx_calloc(num*sizeof(U16));
    font->ascii2glyph = (int*)rfx_calloc(font->maxascii*sizeof(int));
    font->layout->ascent = (U16)(underline - bbox.lly);
    font->layout->descent = (U16)(bbox.ury - underline);
    font->layout->leading = (U16)(font->layout->ascent - 
	                     font->layout->descent -
			     (bbox.lly - bbox.ury));
    font->layout->bounds = (SRECT*)rfx_calloc(sizeof(SRECT)*num);
    font->layout->kerningcount = 0;
    font->layout->kerning = 0;
    font->glyphnames = rfx_calloc(num*sizeof(char*));
  
    num = 0;

    charname = charnames;
    for(c=0;c<font->numchars;c++) {
	drawer_t draw;
	SRECT bbox;
	T1_OUTLINE * outline;
	FPOINT pos,last;
	int firstx;
	
	outline = T1_GetCharOutline(nr, c, 100.0, 0);
	firstx = outline->dest.x/0xffff;

	pos.x = 0;
	pos.y = 0;
	last = pos;
	
	font->glyphnames[c] = strdup(*charname);

	if(c<font->maxascii)
	    font->ascii2glyph[c] = c;
	font->glyph2ascii[c] = c;
	
	swf_Shape01DrawerInit(&draw, 0);

	while(outline) {
	    pos.x += (outline->dest.x/(float)0xffff);
	    pos.y += (outline->dest.y/(float)0xffff);

	    if(outline->type == T1_PATHTYPE_MOVE) {
		draw.moveTo(&draw,&pos);
	    } else if(outline->type == T1_PATHTYPE_LINE) {
		draw.lineTo(&draw,&pos);
	    } else if(outline->type == T1_PATHTYPE_BEZIER) {
		T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
		FPOINT b,c;
		b.x = o2->B.x/(float)0xffff+last.x;
		b.y = o2->B.y/(float)0xffff+last.y;
		c.x = o2->C.x/(float)0xffff+last.x;
		c.y = o2->C.y/(float)0xffff+last.y;
		draw_cubicTo(&draw,&b,&c,&pos);
	    } else {
		fprintf(stderr, "loadT1Font: unknown outline type:%d\n", outline->type);
	    }
	    last = pos;
	    outline = outline->link;
	}
	
	draw.finish(&draw);

	font->glyph[c].shape = swf_ShapeDrawerToShape(&draw);
	bbox = swf_ShapeDrawerGetBBox(&draw);
	draw.dealloc(&draw);
	    
	font->layout->bounds[c] = bbox;
	font->glyph[c].advance = bbox.xmax;
	if(!font->glyph[c].advance) {
	    font->glyph[c].advance = firstx;
	}
	charname++;
    }
    T1_DeleteFont(nr);

    for(t=0;t<256;t++)
	rfx_free(encoding[t]);
    return font;
}
Beispiel #15
0
SWFFONT* swf_LoadTrueTypeFont(const char*filename, char flashtype)
{
    FT_Face face;
    FT_Error error;
    const char* name = 0;
    FT_ULong charcode;
    FT_UInt gindex;
    SWFFONT* font;
    int t;
    int*glyph2glyph;
    int max_unicode = 0;
    int charmap = -1;

    if(ftlibrary == 0) {
	if(FT_Init_FreeType(&ftlibrary)) {
	    fprintf(stderr, "Couldn't init freetype library!\n");
	    exit(1);
	}
    }
    error = FT_New_Face(ftlibrary, filename, 0, &face);

    if(error || !face) {
	fprintf(stderr, "Couldn't load file %s- not a TTF file?\n", filename);
	return 0;
    }
   
    int scale = flashtype?20:1;
    FT_Set_Pixel_Sizes (face, 16*loadfont_scale*scale, 16*loadfont_scale*scale);

    if(face->num_glyphs <= 0) {
	fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs);
	return 0;
    }

    font = (SWFFONT*)rfx_calloc(sizeof(SWFFONT));
    font->id = -1;
    font->version = flashtype?3:2;

    font->layout = (SWFLAYOUT*)rfx_calloc(sizeof(SWFLAYOUT));
    font->layout->bounds = (SRECT*)rfx_calloc(face->num_glyphs*sizeof(SRECT));
    font->style =  ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0)
	          |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
    font->encoding = FONT_ENCODING_UNICODE;
    font->glyph2ascii = (U16*)rfx_calloc(face->num_glyphs*sizeof(U16));
    font->maxascii = 0;
    font->glyph = (SWFGLYPH*)rfx_calloc(face->num_glyphs*sizeof(SWFGLYPH));
    if(FT_HAS_GLYPH_NAMES(face)) {
	font->glyphnames = (char**)rfx_calloc(face->num_glyphs*sizeof(char*));
    }
    
    font->layout->kerningcount = 0;
    
    name = face->family_name;
    if(!(name && *name))
        name = FT_Get_Postscript_Name(face);
    if(name && *name)
	font->name = (U8*)strdup(name);

    while(1) 
    {
    /*    // Map Glyphs to Unicode, version 1 (quick and dirty):
	int t;
	for(t=0;t<65536;t++) {
	    int index = FT_Get_Char_Index(face, t);
	    if(index>=0 && index<face->num_glyphs) {
		if(font->glyph2ascii[index]<0)
		    font->glyph2ascii[index] = t;
	    }
	}*/
	
	// Map Glyphs to Unicode, version 2 (much nicer):
	// (The third way would be the AGL algorithm, as proposed
	//  by Werner Lemberg on [email protected])

	charcode = FT_Get_First_Char(face, &gindex);
	while(gindex != 0)
	{
	    if(gindex >= 0 && gindex<face->num_glyphs) {
		if(!font->glyph2ascii[gindex]) {
		    font->glyph2ascii[gindex] = charcode;
		    if(charcode + 1 > font->maxascii) {
			font->maxascii = charcode + 1;
		    }
		}
	    }
	    charcode = FT_Get_Next_Char(face, charcode, &gindex);
	}

	/* if we didn't find a single encoding character, try
	   the font's charmaps instead. That usually means that
	   the encoding is no longer unicode. 
	   TODO: find a way to convert the encoding to unicode
	 */
	if(font->maxascii == 0 && charmap < face->num_charmaps - 1) {
	    charmap++;
	    FT_Set_Charmap(face, face->charmaps[charmap]);
	    font->encoding = 0;//anything but unicode FIXME
	} else 
	    break;
    }

    if(full_unicode)
	font->maxascii = 65535;
    
    font->ascii2glyph = (int*)rfx_calloc(font->maxascii*sizeof(int));
    
    for(t=0;t<font->maxascii;t++) {
	int g = FT_Get_Char_Index(face, t);
	if(!g || g>=face->num_glyphs)
	    g = -1;
	font->ascii2glyph[t] = g;
	if(g>=0) {
	    max_unicode = t+1;
	    if(!font->glyph2ascii[g]) {
		font->glyph2ascii[g] = t;
	    }
	}
    }
    font->maxascii = max_unicode;

    font->numchars = 0;

    glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int));

    SRECT fontbbox = {0,0,0,0};

    for(t=0; t < face->num_glyphs; t++) {
	FT_Glyph glyph;
	FT_BBox bbox;
	char name[128];
	drawer_t draw;
	char hasname = 0;
	name[0]=0;
	if(FT_HAS_GLYPH_NAMES(face)) {
	    error = FT_Get_Glyph_Name(face, t, name, 127);
	    if(!error && name[0] && !strstr(name, "notdef")) {
		font->glyphnames[font->numchars] = strdup(name);
		hasname = 1;
	    }
	}
	if(!font->glyph2ascii[t] && !hasname && skip_unused) {
	    continue;
	}
	error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
	if(error) {
	    //tends to happen with some pdfs
	    fprintf(stderr, "Warning: Glyph %d has return code %d\n", t, error);
	    glyph=0;
	    if(skip_unused) 
		continue;
	} else {
	    error = FT_Get_Glyph(face->glyph, &glyph);
	    if(error) {
		fprintf(stderr, "Couldn't get glyph %d, error:%d\n", t, error);
		glyph=0;
		if(skip_unused) 
		    continue;
	    }
	}

	if(glyph)
	    FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &bbox);
	else
	    memset(&bbox, 0, sizeof(bbox));

	bbox.yMin = -bbox.yMin;
	bbox.yMax = -bbox.yMax;
	if(bbox.xMax < bbox.xMin) {
	    // swap
	    bbox.xMax ^= bbox.xMin;
	    bbox.xMin ^= bbox.xMax;
	    bbox.xMax ^= bbox.xMin;
	}
	if(bbox.yMax < bbox.yMin) {
	    // swap
	    bbox.yMax ^= bbox.yMin;
	    bbox.yMin ^= bbox.yMax;
	    bbox.yMax ^= bbox.yMin;
	}

	swf_Shape01DrawerInit(&draw, 0);

	//error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw);
	if(glyph)
	    error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw);
	else
	    error = 0;
	draw.finish(&draw);
	
	if(error) {
	    fprintf(stderr, "Couldn't decompose glyph %d\n", t);
	    draw.dealloc(&draw);
	    continue;
	}

#if 0
	if(bbox.xMin > 0) {
	    font->glyph[font->numchars].advance = (bbox.xMax*20*FT_SCALE)/FT_SUBPIXELS;
	} else {
	    font->glyph[font->numchars].advance = ((bbox.xMax - bbox.xMin)*20*FT_SCALE)/FT_SUBPIXELS;
	}
#else
	if(glyph)
	    font->glyph[font->numchars].advance = glyph->advance.x*20/65536;
	else
	    font->glyph[font->numchars].advance = 0;
#endif
	
	SRECT b = swf_ShapeDrawerGetBBox(&draw);

	//font->layout->bounds[font->numchars].xmin = (bbox.xMin*FT_SCALE*20)/FT_SUBPIXELS;
	//font->layout->bounds[font->numchars].ymin = (bbox.yMin*FT_SCALE*20)/FT_SUBPIXELS;
	//font->layout->bounds[font->numchars].xmax = (bbox.xMax*FT_SCALE*20)/FT_SUBPIXELS;
	//font->layout->bounds[font->numchars].ymax = (bbox.yMax*FT_SCALE*20)/FT_SUBPIXELS;

	font->layout->bounds[font->numchars] = b;
	font->glyph[font->numchars].shape = swf_ShapeDrawerToShape(&draw);

	swf_ExpandRect2(&fontbbox, &font->layout->bounds[font->numchars]);

	draw.dealloc(&draw);

	if(glyph)
	    FT_Done_Glyph(glyph);
	font->glyph2ascii[font->numchars] = font->glyph2ascii[t];
	glyph2glyph[t] = font->numchars;
	font->numchars++;
    }
    
    //font->layout->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
    //font->layout->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
    //font->layout->leading = font->layout->ascent + font->layout->descent;

    if(-fontbbox.ymin < 0)
        font->layout->ascent = 0;
    else
	font->layout->ascent = -fontbbox.ymin;

    if(fontbbox.ymax < 0)
        font->layout->descent = 0;
    else
	font->layout->descent = fontbbox.ymax;

    int leading = fontbbox.ymax - fontbbox.ymin;
    font->layout->leading = leading>0x7fff?0x7fff:leading;

    /* notice: if skip_unused is true, font->glyph2ascii, font->glyphnames and font->layout->bounds will 
	       have more memory allocated than just font->numchars, but only the first font->numchars 
	       are used/valid */

    for(t=0;t<font->maxascii;t++) {
	if(font->ascii2glyph[t]>=0) {
	    font->ascii2glyph[t] = glyph2glyph[font->ascii2glyph[t]];
	}
    }
    rfx_free(glyph2glyph);

    FT_Done_Face(face);
    FT_Done_FreeType(ftlibrary);ftlibrary=0;

    return font;
}