+}
+
+/* the logic seems to be as following:
+ first, beginType3Char is called, with the charcode and the coordinates.
+ if this function returns true, it already knew about the char and has now drawn it.
+ if the function returns false, it's a new char, and type3D1 is called with some parameters-
+ the all draw operations until endType3Char are part of the char (which in this moment is
+ at the position first passed to beginType3Char). the char ends with endType3Char.
+
+ The drawing operations between beginType3Char and endType3Char are somewhat different to
+ the normal ones. For example, the fillcolor equals the stroke color.
+*/
+
+GBool SWFOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen)
+{
+ msg("<debug> beginType3Char %d, %08x, %d", code, *u, uLen);
+ type3active = 1;
+ /* the character itself is going to be passed using the draw functions */
+ return gFalse; /* gTrue= is_in_cache? */
+}
+
+void SWFOutputDev::type3D0(GfxState *state, double wx, double wy) {
+ msg("<debug> type3D0 width=%f height=%f", wx, wy);
+}
+void SWFOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) {
+ msg("<debug> type3D1 width=%f height=%f bbox=(%f,%f,%f,%f)", wx, wy,
+ llx,lly,urx,ury);
+}
+
+void SWFOutputDev::endType3Char(GfxState *state)
+{
+ type3active = 0;
+ msg("<debug> endType3Char");
+}
+
+void SWFOutputDev::startFrame(int width, int height)
+{
+ output->startpage(output, width, height);
+}
+
+void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, double crop_y1, double crop_x2, double crop_y2)
+{
+ this->currentpage = pageNum;
+ double x1,y1,x2,y2;
+ int rot = doc->getPageRotate(1);
+ gfxcolor_t white;
+ laststate = state;
+ gfxline_t clippath[5];
+
+ white.r = white.g = white.b = white.a = 255;
+
+ /* state->transform(state->getX1(),state->getY1(),&x1,&y1);
+ state->transform(state->getX2(),state->getY2(),&x2,&y2);
+ Use CropBox, not MediaBox, as page size
+ */
+
+ /*x1 = crop_x1;
+ y1 = crop_y1;
+ x2 = crop_x2;
+ y2 = crop_y2;*/
+ state->transform(crop_x1,crop_y1,&x1,&y1); //x1 += user_movex; y1 += user_movey;
+ state->transform(crop_x2,crop_y2,&x2,&y2); //x2 += user_movex; y2 += user_movey;
+
+ if(x2<x1) {double x3=x1;x1=x2;x2=x3;}
+ if(y2<y1) {double y3=y1;y1=y2;y2=y3;}
+
+
+ /* apply user clip box */
+ if(user_clipx1|user_clipy1|user_clipx2|user_clipy2) {
+ /*if(user_clipx1 > x1)*/ x1 = user_clipx1;
+ /*if(user_clipx2 < x2)*/ x2 = user_clipx2;
+ /*if(user_clipy1 > y1)*/ y1 = user_clipy1;
+ /*if(user_clipy2 < y2)*/ y2 = user_clipy2;
+ }
+
+ //msg("<verbose> Bounding box is (%f,%f)-(%f,%f) [shifted by %d/%d]", x1,y1,x2,y2, user_movex, user_movey);
+
+ if(outer_clip_box) {
+ output->endclip(output);
+ outer_clip_box = 0;
+ }
+
+ msg("<notice> processing PDF page %d (%dx%d:%d:%d) (move:%d:%d)", pageNum, (int)x2-(int)x1,(int)y2-(int)y1, (int)x1, (int)y1, user_movex, user_movey);
+ if(rot!=0)
+ msg("<verbose> page is rotated %d degrees\n", rot);
+
+ clippath[0].type = gfx_moveTo;clippath[0].x = x1; clippath[0].y = y1; clippath[0].next = &clippath[1];
+ clippath[1].type = gfx_lineTo;clippath[1].x = x2; clippath[1].y = y1; clippath[1].next = &clippath[2];
+ clippath[2].type = gfx_lineTo;clippath[2].x = x2; clippath[2].y = y2; clippath[2].next = &clippath[3];
+ clippath[3].type = gfx_lineTo;clippath[3].x = x1; clippath[3].y = y2; clippath[3].next = &clippath[4];
+ clippath[4].type = gfx_lineTo;clippath[4].x = x1; clippath[4].y = y1; clippath[4].next = 0;
+ output->startclip(output, clippath); outer_clip_box = 1;
+ output->fill(output, clippath, &white);
+}
+
+void SWFOutputDev::drawLink(Link *link, Catalog *catalog)
+{
+ double x1, y1, x2, y2, w;
+ gfxline_t points[5];
+ int x, y;
+
+ msg("<debug> drawlink\n");
+
+ link->getRect(&x1, &y1, &x2, &y2);
+ cvtUserToDev(x1, y1, &x, &y);
+ points[0].type = gfx_moveTo;
+ points[0].x = points[4].x = x + user_movex;
+ points[0].y = points[4].y = y + user_movey;
+ points[0].next = &points[1];
+ cvtUserToDev(x2, y1, &x, &y);
+ points[1].type = gfx_lineTo;
+ points[1].x = x + user_movex;
+ points[1].y = y + user_movey;
+ points[1].next = &points[2];
+ cvtUserToDev(x2, y2, &x, &y);
+ points[2].type = gfx_lineTo;
+ points[2].x = x + user_movex;
+ points[2].y = y + user_movey;
+ points[2].next = &points[3];
+ cvtUserToDev(x1, y2, &x, &y);
+ points[3].type = gfx_lineTo;
+ points[3].x = x + user_movex;
+ points[3].y = y + user_movey;
+ points[3].next = &points[4];
+ cvtUserToDev(x1, y1, &x, &y);
+ points[4].type = gfx_lineTo;
+ points[4].x = x + user_movex;
+ points[4].y = y + user_movey;
+ points[4].next = 0;
+
+ LinkAction*action=link->getAction();
+ char buf[128];
+ char*s = 0;
+ char*type = "-?-";
+ char*url = 0;
+ char*named = 0;
+ int page = -1;
+ switch(action->getKind())
+ {
+ case actionGoTo: {
+ type = "GoTo";
+ LinkGoTo *ha=(LinkGoTo *)link->getAction();
+ LinkDest *dest=NULL;
+ if (ha->getDest()==NULL)
+ dest=catalog->findDest(ha->getNamedDest());
+ else dest=ha->getDest();
+ if (dest){
+ if (dest->isPageRef()){
+ Ref pageref=dest->getPageRef();
+ page=catalog->findPage(pageref.num,pageref.gen);
+ }
+ else page=dest->getPageNum();
+ sprintf(buf, "%d", page);
+ s = strdup(buf);
+ }
+ }
+ break;
+ case actionGoToR: {
+ type = "GoToR";
+ LinkGoToR*l = (LinkGoToR*)action;
+ GString*g = l->getNamedDest();
+ if(g)
+ s = strdup(g->getCString());
+ }
+ break;
+ case actionNamed: {
+ type = "Named";
+ LinkNamed*l = (LinkNamed*)action;
+ GString*name = l->getName();
+ if(name) {
+ s = strdup(name->lowerCase()->getCString());
+ named = name->getCString();
+ if(!strchr(s,':'))
+ {
+ if(strstr(s, "next") || strstr(s, "forward"))
+ {
+ page = currentpage + 1;
+ }
+ else if(strstr(s, "prev") || strstr(s, "back"))
+ {
+ page = currentpage - 1;
+ }
+ else if(strstr(s, "last") || strstr(s, "end"))
+ {
+ if(pages && pagepos>0)
+ page = pages[pagepos-1];
+ }
+ else if(strstr(s, "first") || strstr(s, "top"))
+ {
+ page = 1;
+ }
+ }
+ }
+ }
+ break;
+ case actionLaunch: {
+ type = "Launch";
+ LinkLaunch*l = (LinkLaunch*)action;
+ GString * str = new GString(l->getFileName());
+ GString * params = l->getParams();
+ if(params)
+ str->append(params);
+ s = strdup(str->getCString());
+ delete str;
+ }
+ break;
+ case actionURI: {
+ type = "URI";
+ LinkURI*l = (LinkURI*)action;
+ GString*g = l->getURI();
+ if(g) {
+ url = g->getCString();
+ s = strdup(url);
+ }
+ }
+ break;
+ case actionUnknown: {
+ type = "Unknown";
+ LinkUnknown*l = (LinkUnknown*)action;
+ s = strdup("");
+ }
+ break;
+ default: {
+ msg("<error> Unknown link type!\n");
+ break;
+ }
+ }
+
+ if(!s) s = strdup("-?-");
+