static void CVOutline(CharView *cv, real width) { StrokeInfo si; SplineSet *temp, *spl; int changed; memset(&si,0,sizeof(si)); si.removeexternal = true; si.radius = width; /* si.removeoverlapifneeded = true;*/ CVPreserveState((CharViewBase *) cv); temp = SplineSetStroke(cv->b.layerheads[cv->b.drawmode]->splines,&si,cv->b.layerheads[cv->b.drawmode]->order2); for ( spl=cv->b.layerheads[cv->b.drawmode]->splines; spl->next!=NULL; spl=spl->next ); spl->next = temp; SplineSetsCorrect(cv->b.layerheads[cv->b.drawmode]->splines,&changed); CVCharChangedUpdate(&cv->b); }
void CVPointOfView(CharView *cv,struct pov_data *pov) { int anysel = CVAnySel(cv,NULL,NULL,NULL,NULL); BasePoint origin; CVPreserveState((CharViewBase *) cv); origin.x = origin.y = 0; if ( pov->xorigin==or_center || pov->yorigin==or_center ) CVFindCenter(cv,&origin,!anysel); if ( pov->xorigin==or_lastpress ) origin.x = cv->p.cx; if ( pov->yorigin==or_lastpress ) origin.y = cv->p.cy; if ( pov->xorigin!=or_value ) pov->x = origin.x; if ( pov->yorigin!=or_value ) pov->y = origin.y; MinimumDistancesFree(cv->b.sc->md); cv->b.sc->md = NULL; SPLPoV(cv->b.layerheads[cv->b.drawmode]->splines,pov,anysel); CVCharChangedUpdate(&cv->b); }
static void CVShadow(CharView *cv,real angle, real outline_width, real shadow_length,int wireframe) { CVPreserveState((CharViewBase *) cv); cv->b.layerheads[cv->b.drawmode]->splines = SSShadow(cv->b.layerheads[cv->b.drawmode]->splines,angle,outline_width,shadow_length,cv->b.sc,wireframe); CVCharChangedUpdate(&cv->b); }
/** * Process the given kvmsg from the server. If create is set and we do * not have any charview for a changed glyph then we first create a * charview for it. This allows the updates from a server to be * processed at startup time, getting us up to speed with any glyphs * that have changed. * * This function is mainly called in response to an update which is * published from the server. However, in sessionJoin() we also call * here to handle the incremental updates to glyphs that have occurred * after the SFD was sent to the server. */ static void zeromq_subscriber_process_update( cloneclient_t* cc, kvmsg_t *kvmsg, int create ) { cc->sequence = kvmsg_sequence (kvmsg); if( cc->sequence >= cc->roundTripTimerWaitingSeq ) cc->roundTripTimerWaitingSeq = 0; char* uuid = kvmsg_get_prop (kvmsg, "uuid" ); byte* data = kvmsg_body (kvmsg); size_t data_size = kvmsg_size (kvmsg); printf("cc process_update() uuid:%s\n", uuid ); FontView* fv = FontViewFind( FontViewFind_byXUIDConnected, uuid ); printf("fv:%p\n", fv ); if( fv ) { if( !data_size ) { printf("WARNING: zero length message!\n" ); return; } SplineFont *sf = fv->b.sf; if( !sf ) { printf("ERROR: font view does not have the splinefont set!\n" ); return; } char* pos = kvmsg_get_prop (kvmsg, "pos" ); char* name = kvmsg_get_prop (kvmsg, "name" ); printf("pos:%s\n", pos ); // SplineChar *sc = sf->glyphs[ atoi(pos) ]; SplineChar* sc = SFGetOrMakeChar( sf, -1, name ); printf("sc:%p\n", sc ); if( !sc ) { printf("WARNING: font view does not have a glyph for pos:%s\n", pos ); printf("WARNING: font view does not have a glyph for name:%s\n", name ); return; } printf("sc.name:%s\n", sc->name ); printf("data.size:%ld\n", data_size ); if( DEBUG_SHOW_SFD_CHUNKS ) printf("data:%s\n", data ); int current_layer = 0; if( !sc->views && create ) { int show = 0; CharView* cv = CharViewCreateExtended( sc, fv, -1, show ); printf("created charview:%p\n", cv ); } for( CharViewBase* cv = sc->views; cv; cv = cv->next ) { printf("have charview:%p\n", cv ); char filename[PATH_MAX]; snprintf(filename, PATH_MAX, "%s/fontforge-collab-inx-%d.sfd", getTempDir(), getpid() ); GFileWriteAll( filename, (char*)data); FILE* file = fopen( filename, "rb" ); Undoes* undo = SFDGetUndo( sf, file, sc, "UndoOperation", "EndUndoOperation", current_layer ); fclose(file); if( !undo ) { printf("***** ERROR ****** reading back undo instance!\n"); printf("data: %s\n\n", data ); } if( undo ) { // NOT HANDLED! if( undo->undotype == ut_statehint ) { printf("*** warning ut_statehint not handled\n"); break; } printf("________________________ READ undo.layer: %d dm:%d layer_sz:%d\n", undo->layer, cv->drawmode, cv->sc->layer_cnt ); int selectedlayer = cv->drawmode; if( undo->layer != UNDO_LAYER_UNKNOWN ) selectedlayer = undo->layer; // use oldlayer to store current setting and switch to the // selected layer for this block. int oldlayer = cv->drawmode; cv->drawmode = selectedlayer; undo->next = 0; undo->next = cv->layerheads[selectedlayer]->redoes; cv->layerheads[selectedlayer]->redoes = undo; CVDoRedo( cv ); char* isLocalUndo = kvmsg_get_prop (kvmsg, "isLocalUndo" ); if( isLocalUndo ) { if( isLocalUndo[0] == '1' ) { Undoes* undo = cv->layerheads[selectedlayer]->undoes; if( undo ) { cv->layerheads[selectedlayer]->undoes = undo->next; undo->next = cv->layerheads[selectedlayer]->redoes; cv->layerheads[selectedlayer]->redoes = undo; } } } if( cv->drawmode != oldlayer ) { cv->drawmode = oldlayer; CVCharChangedUpdate( cv ); } } break; } } printf ("I: processed update=%d\n", (int) cc->sequence); }
void CVMouseUpKnife(CharView *cv, GEvent *event) { #if !defined(KNIFE_CONTINUOUS) /* draw a line from (cv->p.cx,cv->p.cy) to (cv->info.x,cv->info.y) */ /* and cut anything intersected by it */ SplineSet *spl, *spl2; Spline *s, *nexts; Spline dummy; SplinePoint dummyfrom, dummyto, *mid, *mid2; BasePoint inters[9]; extended t1s[10], t2s[10]; int foundsomething = true, ever = false; int i; int spiro_index = 0; memset(&dummy,0,sizeof(dummy)); memset(&dummyfrom,0,sizeof(dummyfrom)); memset(&dummyto,0,sizeof(dummyto)); dummyfrom.me.x = cv->p.cx; dummyfrom.me.y = cv->p.cy; dummyto.me.x = cv->info.x; dummyto.me.y = cv->info.y; dummyfrom.nextcp = dummyfrom.prevcp = dummyfrom.me; dummyto.nextcp = dummyto.prevcp = dummyto.me; dummyfrom.nonextcp = dummyfrom.noprevcp = dummyto.nonextcp = dummyto.noprevcp = true; dummy.splines[0].d = cv->p.cx; dummy.splines[0].c = cv->info.x-cv->p.cx; dummy.splines[1].d = cv->p.cy; dummy.splines[1].c = cv->info.y-cv->p.cy; dummy.from = &dummyfrom; dummy.to = &dummyto; dummy.islinear = dummy.knownlinear = true; dummyfrom.next = dummyto.prev = &dummy; for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL ; spl = spl->next ) spl->ticked = false; while ( foundsomething ) { foundsomething = false; for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL && !foundsomething; spl = spl->next ) { for ( s = spl->first->next; s!=NULL ; ) { nexts = NULL; if ( s->to!=spl->first ) nexts = s->to->next; if ( SplinesIntersect(s,&dummy,inters,t1s,t2s)>0 ) { if ( event->u.mouse.state&ksm_meta ) { for ( i=0; i<4 && t1s[i]!=-1 && (t1s[i]<.0001 || t1s[i]>1-.0001); ++i ); if ( i<4 && t1s[i]!=-1 ) { /* With meta down we just remove the spline rather than */ /* cutting it */ foundsomething = true; nexts = NULL; if ( !ever ) CVPreserveState(&cv->b); ever = true; if ( spl->first==spl->last ) { spl->first = s->to; spl->last = s->from; } else { spl2 = chunkalloc(sizeof(SplineSet)); spl2->next = spl->next; spl->next = spl2; spl2->first = s->to; spl2->last = spl->last; spl->last = s->from; } s->to->prev = s->from->next = NULL; SplineFree(s); SplineSetSpirosClear(spl); } } else { for ( i=0; i<4 && t1s[i]!=-1 && (( t1s[i]<.001 && s->from->prev==NULL ) || ( t1s[i]>1-.001 && s->to->next == NULL )); ++i ); if ( i<4 && t1s[i]!=-1 ) { foundsomething = true; nexts = NULL; if ( !ever ) CVPreserveState(&cv->b); ever = true; spiro_index = -1; if ( cv->b.sc->inspiro && hasspiro()) { if ( spl->spiro_cnt!=0 ) spiro_index = SplineT2SpiroIndex(s,t1s[i],spl); } else SplineSetSpirosClear(spl); if ( t1s[i]<.001 ) { mid = s->from; } else if ( t1s[i]>1-.001 ) { mid = s->to; } else mid = SplineBisect(s,t1s[i]); /* if the intersection is close to an end point */ /* cut at the end point, else break in the middle */ /* Cut here, and then */ /* start all over again (we may need to alter the */ /* splineset structure so drastically that we just */ /* can't continue these loops) */ mid->pointtype = pt_corner; mid2 = chunkalloc(sizeof(SplinePoint)); *mid2 = *mid; mid2->hintmask = NULL; mid->next = NULL; mid2->prev = NULL; mid2->next->from = mid2; spl->ticked = true; if ( spl->first==spl->last ) { spl->first = mid2; spl->last = mid; if ( spiro_index!=-1 ) ReorderSpirosAndAddAndCut(spl,spiro_index); } else { spl2 = chunkalloc(sizeof(SplineSet)); spl2->next = spl->next; spl->next = spl2; spl2->first = mid2; spl2->last = spl->last; spl->last = mid; if ( spiro_index!=-1 ) SplitSpirosAndAddAndCut(spl,spl2,spiro_index); spl2->ticked = true; } } } } s = nexts; } } } if ( ever ) { for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL ; spl = spl->next ) { if ( spl->ticked && spl->spiros!=NULL && cv->b.sc->inspiro && hasspiro()) SSRegenerateFromSpiros(spl); spl->ticked = false; } CVCharChangedUpdate(&cv->b); } #endif }