Example #1
0
static void MVInline(MetricsView *mv, real width, real inset) {
    StrokeInfo si;
    SplineSet *temp, *spl, *temp2;
    int i, changed;

    memset(&si,0,sizeof(si));
    si.removeexternal = true;
    /* si.removeoverlapifneeded = true;*/

    for ( i=mv->glyphcnt-1; i>=0; --i )
	if ( mv->perchar[i].selected )
    break;
    if ( i!=-1 ) {
	SplineChar *sc = mv->glyphs[i].sc;
	SCPreserveLayer(sc,mv->layer,false);
	si.radius = width;
	temp = SplineSetStroke(sc->layers[mv->layer].splines,&si,sc->layers[mv->layer].order2);
	si.radius = width+inset;
	temp2 = SplineSetStroke(sc->layers[mv->layer].splines,&si,sc->layers[mv->layer].order2);
	for ( spl=sc->layers[mv->layer].splines; spl->next!=NULL; spl=spl->next );
	spl->next = temp;
	for ( ; spl->next!=NULL; spl=spl->next );
	spl->next = temp2;
	SplineSetsCorrect(sc->layers[mv->layer].splines,&changed);
	SCCharChangedUpdate(sc,mv->layer);
    }
}
Example #2
0
void FVOutline(FontViewBase * fv, real width) {
   StrokeInfo si;
   SplineSet *temp, *spl;
   int i, cnt=0, changed, gid;
   SplineChar *sc;
   int layer=fv->active_layer;

   for (i=0; i < fv->map->enccount; ++i)
      if ((gid=fv->map->map[i]) != -1 && (sc=fv->sf->glyphs[gid]) != NULL
	  && fv->selected[i] && sc->layers[layer].splines)
	 ++cnt;

   memset(&si, 0, sizeof(si));
   si.removeexternal=true;
   si.radius=width;
   /*si.removeoverlapifneeded=true; */

   SFUntickAll(fv->sf);
   for (i=0; i < fv->map->enccount; ++i)
      if ((gid=fv->map->map[i]) != -1 && (sc=fv->sf->glyphs[gid]) != NULL
	  && fv->selected[i] && sc->layers[layer].splines && !sc->ticked) {
	 sc->ticked=true;
	 SCPreserveLayer(sc, layer, false);
	 temp =
	    SplineSetStroke(sc->layers[layer].splines, &si,
			    sc->layers[layer].order2);
	 for (spl=sc->layers[layer].splines; spl->next != NULL;
	      spl=spl->next);
	 spl->next=temp;
	 SplineSetsCorrect(sc->layers[layer].splines, &changed);
	 SCCharChangedUpdate(sc, layer, true);
      }
}
Example #3
0
static SplineChar *_SFMakeChar(SplineFont *sf,EncMap *map,int enc) {
    SplineChar dummy, *sc;
    SplineFont *ssf;
    int j, real_uni, gid;
    extern const int cns14pua[], amspua[];

    if ( enc>=map->enccount )
	gid = -1;
    else
	gid = map->map[enc];
    if ( sf->subfontcnt!=0 && gid!=-1 ) {
	ssf = NULL;
	for ( j=0; j<sf->subfontcnt; ++j )
	    if ( gid<sf->subfonts[j]->glyphcnt ) {
		ssf = sf->subfonts[j];
		if ( ssf->glyphs[gid]!=NULL ) {
return( ssf->glyphs[gid] );
		}
	    }
	sf = ssf;
    }

    if ( gid==-1 || (sc = sf->glyphs[gid])==NULL ) {
	if (( map->enc->is_unicodebmp || map->enc->is_unicodefull ) &&
		( enc>=0xe000 && enc<=0xf8ff ) &&
		( sf->uni_interp==ui_ams || sf->uni_interp==ui_trad_chinese ) &&
		( real_uni = (sf->uni_interp==ui_ams ? amspua : cns14pua)[enc-0xe000])!=0 ) {
	    if ( real_uni<map->enccount ) {
		SplineChar *sc;
		/* if necessary, create the real unicode code point */
		/*  and then make us be a duplicate of it */
		sc = _SFMakeChar(sf,map,real_uni);
		map->map[enc] = gid = sc->orig_pos;
		SCCharChangedUpdate(sc,ly_all);
return( sc );
	    }
	}

	SCBuildDummy(&dummy,sf,map,enc);
	/* Let's say a user has a postscript encoding where the glyph ".notdef" */
	/*  is assigned to many slots. Once the user creates a .notdef glyph */
	/*  all those slots should fill in. If they don't they damn well better*/
	/*  when the user clicks on one to edit it */
	/* Used to do that with all encodings. It just confused people */
	if ( map->enc->psnames!=NULL &&
		(sc = SFGetChar(sf,dummy.unicodeenc,dummy.name))!=NULL ) {
	    map->map[enc] = sc->orig_pos;
return( sc );
	}
	sc = SFSplineCharCreate(sf);
	sc->unicodeenc = dummy.unicodeenc;
	sc->name = copy(dummy.name);
	sc->width = dummy.width;
	sc->orig_pos = 0xffff;
	/*SCLigDefault(sc);*/
	SFAddGlyphAndEncode(sf,sc,map,enc);
    }
return( sc );
}
Example #4
0
static void MVShadow(MetricsView *mv,real angle, real outline_width,
	real shadow_length,int wireframe) {
    int i;

    for ( i=mv->glyphcnt-1; i>=0; --i )
	if ( mv->perchar[i].selected )
    break;
    if ( i!=-1 ) {
	SplineChar *sc = mv->glyphs[i].sc;
	SCPreserveLayer(sc,mv->layer,false);
	sc->layers[mv->layer].splines = SSShadow(sc->layers[mv->layer].splines,angle,outline_width,shadow_length,sc,wireframe);
	SCCharChangedUpdate(sc,mv->layer);
    }
}
Example #5
0
static void ApplyChanges(WidthInfo *wi) {
    EncMap *map = wi->fv->map;
    uint8 *rsel = calloc(map->enccount,sizeof(char));
    int i, width;
    real transform[6];
    struct charone *ch;
    DBounds bb;

    for ( i=0; i<wi->real_rcnt; ++i ) {
	int gid = map->map[wi->right[i]->sc->orig_pos];
	if ( gid!=-1 )
	    rsel[gid] = true;
    }
    transform[0] = transform[3] = 1.0;
    transform[1] = transform[2] = transform[5] = 0;

    for ( i=0; i<wi->real_rcnt; ++i ) {
	ch = wi->right[i];
	transform[4] = ch->newl-ch->lbearing;
	if ( transform[4]!=0 ) {
	    FVTrans(wi->fv,ch->sc,transform,rsel,false);
	    SCCharChangedUpdate(ch->sc,ly_none);
	}
    }
    free(rsel);

    for ( i=0; i<wi->real_lcnt; ++i ) {
	ch = wi->left[i];
	SplineCharLayerFindBounds(ch->sc,wi->layer,&bb);
	width = rint(bb.maxx + ch->newr);
	if ( width!=ch->sc->width ) {
	    SCPreserveWidth(ch->sc);
	    SCSynchronizeWidth(ch->sc,width,ch->sc->width,wi->fv);
	    SCCharChangedUpdate(ch->sc,ly_none);
	}
    }
}
Example #6
0
static void SetAnchor(SplineChar *sc,int layer, AnchorPoint *ap,DeviceTable *xadjust, DeviceTable *yadjust, BasePoint *pos) {
    int ly;

    free(ap->xadjust.corrections);
    if ( xadjust->corrections==NULL ) {
	memset(&ap->xadjust,0,sizeof(DeviceTable));
    } else {
	ap->xadjust = *xadjust;
	xadjust->corrections = NULL;
    }
    free(ap->yadjust.corrections);
    if ( yadjust->corrections==NULL ) {
	memset(&ap->yadjust,0,sizeof(DeviceTable));
    } else {
	ap->yadjust = *yadjust;
	yadjust->corrections = NULL;
    }
    ap->me = *pos;
    /* If the anchor is bound to a truetype point we must move the point too */
    /*  or the anchor will just snap back to the point */
    ly = ly_none;
    if ( ap->has_ttf_pt && ap->ttf_pt_index!=0xffff ) {
	int any = false;
	for ( ly=ly_fore; ly<sc->layer_cnt; ++ly ) if ( sc->layers[ly].order2 ) {
	    SplinePoint *sp = SCFindPoint(sc,layer,ap->ttf_pt_index);
	    if ( sp!=NULL ) {
		sp->nextcp.x += pos->x - sp->me.x;
		sp->prevcp.x += pos->x - sp->me.x;
		sp->nextcp.y += pos->y - sp->me.y;
		sp->prevcp.y += pos->y - sp->me.y;
		sp->me = *pos;
		any = true;
	    }
	}
	if ( !any ) {
	    ff_post_notice(_("Detaching Anchor Point"),_("This anchor was attached to point %d, but that's not a point I can move. I'm detaching the anchor from the point.") );
	    ap->has_ttf_pt = false;
	    ly = ly_none;
	}
    }
    SCCharChangedUpdate(sc,ly);
}
Example #7
0
void FVInline(FontViewBase *fv, real width, real inset) {
    StrokeInfo si;
    SplineSet *temp, *spl, *temp2;
    int i, cnt=0, changed, gid;
    SplineChar *sc;
    int layer = fv->active_layer;

    for ( i=0; i<fv->map->enccount; ++i )
	if ( (gid=fv->map->map[i])!=-1 && (sc=fv->sf->glyphs[gid])!=NULL && fv->selected[i] &&
		sc->layers[layer].splines )
	    ++cnt;
    ff_progress_start_indicator(10,_("Inlining glyphs"),_("Inlining glyphs"),0,cnt,1);

    memset(&si,0,sizeof(si));
    si.removeexternal = true;
    /*si.removeoverlapifneeded = true;*/

    SFUntickAll(fv->sf);
    for ( i=0; i<fv->map->enccount; ++i )
	if ( (gid=fv->map->map[i])!=-1 && (sc=fv->sf->glyphs[gid])!=NULL && fv->selected[i] &&
		sc->layers[layer].splines && !sc->ticked ) {
	    sc->ticked = true;
	    SCPreserveLayer(sc,layer,false);
	    si.radius = width;
	    temp = SplineSetStroke(sc->layers[layer].splines,&si,sc->layers[layer].order2);
	    si.radius = width+inset;
	    temp2 = SplineSetStroke(sc->layers[layer].splines,&si,sc->layers[layer].order2);
	    for ( spl=sc->layers[layer].splines; spl->next!=NULL; spl=spl->next );
	    spl->next = temp;
	    for ( ; spl->next!=NULL; spl=spl->next );
	    spl->next = temp2;
	    SplineSetsCorrect(sc->layers[layer].splines,&changed);
	    SCCharChangedUpdate(sc,layer);
	    if ( !ff_progress_next())
    break;
	}
    ff_progress_end_indicator();
}
Example #8
0
static void DoChar(SplineChar *sc,CreateWidthData *wd, FontViewBase *fv,
	BDFChar *bc) {
    real transform[6];
    DBounds bb;
    IBounds ib;
    int width=0;
    BVTFunc bvts[2];
    BDFFont *bdf;
    RefChar *r = HasUseMyMetrics(sc,fv->active_layer);

    /* Can't change the horizontal or vertical advance if there's a "use my metrics" bit set */
    if ( r!=NULL && wd->wtype != wt_lbearing )
return;

    if ( wd->wtype == wt_width ) {
	if ( wd->type==st_set )
	    width = wd->setto;
	else if ( wd->type == st_incr )
	    width = sc->width + wd->increment;
	else
	    width = sc->width * wd->scale/100;
	sc->widthset = true;
	if ( width!=sc->width ) {
	    SCPreserveWidth(sc);
	    SCSynchronizeWidth(sc,width,sc->width,fv);
	}
    } else if ( wd->wtype == wt_lbearing ) {
	transform[0] = transform[3] = 1.0;
	transform[1] = transform[2] = transform[5] = 0;
	bvts[1].func = bvt_none;
	bvts[0].func = bvt_transmove; bvts[0].y = 0;
	if ( bc==NULL ) {
	    SplineCharFindBounds(sc,&bb);
	    if ( wd->type==st_set )
		transform[4] = wd->setto-bb.minx;
	    else if ( wd->type == st_incr )
		transform[4] = wd->increment;
	    else
		transform[4] = bb.minx*wd->scale/100 - bb.minx;
	} else {
	    double scale = (fv->sf->ascent+fv->sf->descent)/(double) (fv->active_bitmap->pixelsize);
	    BDFCharFindBounds(bc,&ib);
	    if ( wd->type==st_set )
		transform[4] = wd->setto-ib.minx*scale;
	    else if ( wd->type == st_incr )
		transform[4] = wd->increment;
	    else
		transform[4] = scale*ib.minx*wd->scale/100 - ib.minx;
	}
	if ( transform[4]!=0 ) {
	    FVTrans(fv,sc,transform,NULL,fvt_dontmovewidth);
	    bvts[0].x = transform[4];
	    for ( bdf = fv->sf->bitmaps; bdf!=NULL; bdf=bdf->next ) if ( bdf->glyphs[sc->orig_pos]!=NULL )
		BCTrans(bdf,bdf->glyphs[sc->orig_pos],bvts,fv);
	}
return;
    } else if ( wd->wtype == wt_rbearing ) {
	if ( bc==NULL ) {
	    SplineCharFindBounds(sc,&bb);
	    if ( wd->type==st_set )
		width = bb.maxx + wd->setto;
	    else if ( wd->type == st_incr )
		width = sc->width+wd->increment;
	    else
		width = (sc->width-bb.maxx) * wd->scale/100 + bb.maxx;
	} else {
	    double scale = (fv->sf->ascent+fv->sf->descent)/(double) (fv->active_bitmap->pixelsize);
	    BDFCharFindBounds(bc,&ib);
	    ++ib.maxx;
	    if ( wd->type==st_set )
		width = rint(ib.maxx*scale + wd->setto);
	    else if ( wd->type == st_incr )
		width = rint(sc->width+wd->increment);
	    else
		width = rint(scale * (bc->width-ib.maxx) * wd->scale/100 + ib.maxx*scale);
	}
	if ( width!=sc->width ) {
	    SCPreserveWidth(sc);
	    SCSynchronizeWidth(sc,width,sc->width,fv);
	}
    } else if ( wd->wtype == wt_bearings ) {
	transform[0] = transform[3] = 1.0;
	transform[1] = transform[2] = transform[5] = 0;
	bvts[1].func = bvt_none;
	bvts[0].func = bvt_transmove; bvts[0].y = 0;
	if ( bc==NULL ) {
	    SplineCharFindBounds(sc,&bb);
	    if ( wd->type==st_set ) {
		transform[4] = wd->setto-bb.minx;
		width = bb.maxx-bb.minx + 2*wd->setto;
	    } else if ( wd->type == st_incr ) {
		transform[4] = wd->increment;
		width += 2*wd->increment;
	    } else {
		transform[4] = bb.minx*wd->scale/100 - bb.minx;
		width = bb.maxx-bb.minx +
			(bb.minx + (sc->width-bb.maxx))*wd->scale/100;
	    }
	} else {
	    double scale = (fv->sf->ascent+fv->sf->descent)/(double) (fv->active_bitmap->pixelsize);
	    BDFCharFindBounds(bc,&ib);
	    ++ib.maxx;
	    if ( wd->type==st_set ) {
		transform[4] = wd->setto-ib.minx;
		width = (ib.maxx-ib.minx + 2*wd->setto);
	    } else if ( wd->type == st_incr ) {
		transform[4] = wd->increment;
		width += 2*wd->increment;
	    } else {
		transform[4] = ib.minx*wd->scale/100 - ib.minx;
		width = ib.maxx-ib.minx +
			(ib.minx + (bc->width-ib.maxx))*wd->scale/100;
	    }
	    transform[4] *= scale;
	    width = rint(width*scale);
	}
	if ( width!=sc->width ) {
	    SCPreserveWidth(sc);
	    SCSynchronizeWidth(sc,width,sc->width,fv);
	}
	if ( transform[4]!=0 ) {
	    FVTrans(fv,sc,transform,NULL,fvt_dontmovewidth);
	    bvts[0].x = transform[4];
	    for ( bdf = fv->sf->bitmaps; bdf!=NULL; bdf=bdf->next ) if ( bdf->glyphs[sc->orig_pos]!=NULL )
		BCTrans(bdf,bdf->glyphs[sc->orig_pos],bvts,fv);
	}
return;
    } else {
	if ( wd->type==st_set )
	    width = wd->setto;
	else if ( wd->type == st_incr )
	    width = sc->vwidth + wd->increment;
	else
	    width = sc->vwidth * wd->scale/100;
	if ( width!=sc->vwidth ) {
	    SCPreserveVWidth(sc);
	    sc->vwidth = width;
	}
    }
    SCCharChangedUpdate(sc,fv->active_layer);
}
Example #9
0
static void aw2_figure_all_sidebearing(AW_Data *all) {
    int i,j;
    AW_Glyph *me, *other;
    real transform[6], half;
    int width, changed;
    uint8 *rsel = calloc(all->fv->map->enccount,sizeof(char));
    real denom = (all->sf->ascent + all->sf->descent)/DENOM_FACTOR_OF_EMSIZE;
    int ldiff, rdiff;

    all->denom = denom;
    all->visual_separation = malloc(all->gcnt*all->gcnt*sizeof(int));
    for ( i=0; i<all->gcnt; ++i ) {
	int *vpt = all->visual_separation + i*all->gcnt;
	me = &all->glyphs[i];
	for ( j=0; j<all->gcnt; ++j ) {
	    other = &all->glyphs[j];
	    vpt[j] = aw2_bbox_separation(me,other,all);
	}
    }

    half = all->desired_separation/2;
    for ( i=0; i<all->gcnt; ++i ) {
	me = &all->glyphs[i];	
	me->lsb = me->rsb = half;
    }

    for ( j=0; j<all->loop_cnt; ++j ) {
	for ( i=0; i<all->gcnt; ++i )
	    aw2_figure_lsb(i,all);
	for ( i=0; i<all->gcnt; ++i )
	    aw2_figure_rsb(i,all);
	for ( i=0; i<all->gcnt; ++i ) {
	    AW_Glyph *me = &all->glyphs[i];
	    me->rsb = me->nrsb;
	    me->lsb = me->nlsb;
	}
    }
    free(all->visual_separation); all->visual_separation = NULL;

    if ( all->normalize ) {
	/* This is the dummy flat edge we added. We want the separation between */
	/*  two adjacent flat edges to be desired_separation */
	me = &all->glyphs[all->gcnt-1];
	if ( me->lsb+me->rsb != all->desired_separation && me->sc==NULL ) {
	    if ( me->lsb+me->rsb!=0 ) {
		ldiff = (all->desired_separation-(me->lsb+me->rsb)) * me->lsb/(me->lsb+me->rsb);
	    } else {
		ldiff = all->desired_separation/2;
	    }
	    rdiff = (all->desired_separation-(me->lsb+me->rsb)) - ldiff;
	    for ( i=0; (me = &all->glyphs[i])->sc!=NULL; ++i ) {
		me->lsb += ldiff;
		me->rsb += rdiff;
	    }
	}
    }

    transform[0] = transform[3] = 1.0;
    transform[1] = transform[2] = transform[5] = 0;
    for ( i=0; (me = &all->glyphs[i])->sc!=NULL; ++i ) {
	changed = 0;
	if ( me->lsb != me->bb.minx ) {
	    transform[4] = me->lsb-me->bb.minx;
	    FVTrans(all->fv,me->sc,transform,rsel,false);
	    changed = true;
	}
	width = me->lsb + me->rsb + rint(me->bb.maxx - me->bb.minx);
	if ( me->sc->width != width ) {
	    SCPreserveWidth(me->sc);
	    SCSynchronizeWidth(me->sc,width,me->sc->width,all->fv);
	    changed = true;
	}
	if ( changed )
	    SCCharChangedUpdate(me->sc,ly_none);
    }
    free(rsel);
}
Example #10
0
static SplineChar *AddAnchor(AnchorDlg *a, SplineFont *sf, AnchorClass *ac,
	int ismarklike) {
    char *ret, *def;
    SplineChar *sc;
    int isliga = false, ismrk=false, maxlig=-1;
    AnchorPoint *ap;
    PST *pst;
    int i;

    def = copy(".notdef");
    for (;;) {
	ret = gwwv_ask_string(_("Provide a glyph name"),def,_("Please identify a glyph by name, and FontForge will add an anchor to that glyph."));
	free(def);
	if ( ret==NULL )
return( NULL );
	sc = SFGetChar(sf,-1,ret);
	def = ret;
	if ( sc==NULL )
	    ff_post_error(_("Non-existant glyph"), _("The glyph, %.80s, is not in the font"), ret );
	else {
	    isliga = ismrk = false;
	    for ( ap=sc->anchor ; ap!=NULL; ap=ap->next ) {
		if ( ap->type == at_baselig )
		    isliga = true;
		else if ( ap->type == at_basemark || ap->type == at_mark )
		    ismrk = true;
		if ( ap->anchor == ac ) {
		    if ( (ap->type == at_centry ||
			    (ap->type == at_mark && ac->type==act_mkmk) ||
			    ap->type == at_baselig ) && ismarklike==-1 )
			ismarklike = false;
		    else if ( (ap->type == at_cexit || (ap->type == at_basemark && ac->type==act_mkmk)) && ismarklike==-1 )
			ismarklike = true;
		    else if ( ap->type != at_baselig ||
			      ( ap->type == at_baselig && ismarklike>0 ))
			ff_post_error(_("Duplicate Anchor Class"), _("The glyph, %.80s, already contains an anchor in this class, %.80s."), ret, ac->name );
		    else if ( maxlig<ap->lig_index )
			maxlig = ap->lig_index;
	    break;
		}
	    }
	    if ( ap==NULL )
    break;
	}
    }

    ap = chunkalloc(sizeof(AnchorPoint));
    ap->anchor = ac;
    ap->me.x = ap->me.y = 0;
    ap->next = sc->anchor;
    sc->anchor = ap;
    SCCharChangedUpdate(sc,ly_none);

    if ( sc->width==0 ) ismrk = true;
    for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
	if ( pst->type == pst_ligature || pst->type == pst_lcaret ) {
	    isliga = true;
    break;
	}
    }

    if ( isliga || (ac->type==act_mklg && ismarklike==0 ) ) {
	ap->type = at_baselig;
	ap->lig_index = maxlig+1;
    } else if ( ismrk && ismarklike!=0 )
	ap->type = at_mark;
    else if ( ismarklike==0 && (ismrk || ac->type==act_mkmk) )
	ap->type = at_basemark;
    else if ( ac->type == act_curs ) {
	if ( ismarklike==true )
	    ap->type = at_centry;
	else
	    ap->type = at_cexit;
    } else if ( ismarklike==true )
	ap->type = at_mark;
    else
	ap->type = at_basechar;

    if ( a!=NULL ) {
	GTextInfo **ti = AnchorD_GlyphsInClass(a);
	GGadgetSetList(GWidgetGetControl(a->gw,CID_Glyph),ti,false);
	for ( i=0; ti[i]->text!=NULL || ti[i]->line; ++i ) {
	    if ( ti[i]->userdata == ap ) {
		GGadgetSelectOneListItem(GWidgetGetControl(a->gw,CID_Glyph),i);
	break;
	    }
	}
	AnchorD_ChangeGlyph(a,sc,ap);
    }
return( sc );
}