39 #define SVG_Default_X 720
40 #define SVG_Default_Y 540
42 #define POINTS_PER_INCH 72
44 #define MAX_STRING_LEN 1000
49 #define FONT_SIZE_RATIO 1.34
50 #define FONT_SHIFT_RATIO 0.705
51 #define FONT_SHIFT_OFFSET 0.5
103 static void write_hex( FILE *,
unsigned char );
131 #ifndef ENABLE_DYNDRIVERS
132 pdt->
pl_MenuStr =
"Scalable Vector Graphics (SVG 1.1)";
183 free( (
void *)
pls->
dev );
185 pls->
dev = calloc( 1, (
size_t)
sizeof (
SVG ) );
187 plexit(
"plD_init_svg: Out of memory." );
227 svg_general( aStream,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
228 svg_general( aStream,
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n" );
229 svg_general( aStream,
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n" );
260 svg_attr_value( aStream,
"xmlns:xlink",
"http://www.w3.org/1999/xlink" );
309 svg_attr_values( aStream,
"points",
"%r,%r %r,%r", (
double) x1a / aStream->
scale, (
double) y1a / aStream->
scale, (
double) x2a / aStream->
scale, (
double) y2a / aStream->
scale );
453 fprintf( aStream->
svgFile,
"points=\"" );
454 for ( i = 0; i < npts; i++ )
456 fprintf( aStream->
svgFile,
"%.2f,%.2f ", (
double) xa[i] / aStream->
scale, (
double) ya[i] / aStream->
scale );
457 if ( ( ( i + 1 ) % 10 ) == 0 )
459 fprintf( aStream->
svgFile,
"\n" );
463 fprintf( aStream->
svgFile,
"\"/>\n" );
484 svg_open( aStream,
"linearGradient" );
502 fprintf( aStream->
svgFile,
"<stop offset=\"%.3f\" ",
503 (
double) i / (
double) (
pls->
ncol1 - 1 ) );
504 fprintf( aStream->
svgFile,
"stop-color=\"#" );
508 fprintf( aStream->
svgFile,
"\" " );
518 fprintf( aStream->
svgFile,
"points=\"" );
519 for ( i = 0; i < npts; i++ )
521 fprintf( aStream->
svgFile,
"%.2f,%.2f ", (
double) xa[i] / aStream->
scale, (
double) ya[i] / aStream->
scale );
522 if ( ( ( i + 1 ) % 10 ) == 0 )
524 fprintf( aStream->
svgFile,
"\n" );
528 fprintf( aStream->
svgFile,
"\"/>\n" );
568 double ftHt, scaled_offset, scaled_ftHt;
570 PLINT rcx[4], rcy[4];
571 static PLINT prev_rcx[4], prev_rcy[4];
572 PLFLT rotation, shear, stride, cos_rot, sin_rot, sin_shear, cos_shear;
574 int glyph_size, sum_glyph_size;
579 PLFLT old_sscale, sscale, old_soffset, soffset, old_dup, ddup;
586 printf(
"Non unicode string passed to SVG driver, ignoring\n" );
599 if ( aStream->textClipping )
605 if ( aStream->which_clip == 0 )
611 for ( i = 0; i < 4; i++ )
613 if ( rcx[i] != prev_rcx[i] ||
614 rcy[i] != prev_rcy[i] )
621 svg_attr_values( aStream,
"id",
"text-clipping%d", aStream->which_clip );
628 "%f,%f %f,%f %f,%f %f,%f",
629 ( (
PLFLT) rcx[0] ) / aStream->scale,
630 ( (
PLFLT) rcy[0] ) / aStream->scale,
631 ( (
PLFLT) rcx[1] ) / aStream->scale,
632 ( (
PLFLT) rcy[1] ) / aStream->scale,
633 ( (
PLFLT) rcx[2] ) / aStream->scale,
634 ( (
PLFLT) rcy[2] ) / aStream->scale,
635 ( (
PLFLT) rcx[3] ) / aStream->scale,
636 ( (
PLFLT) rcy[3] ) / aStream->scale );
640 for ( i = 0; i < 4; i++ )
642 prev_rcx[i] = rcx[i];
643 prev_rcy[i] = rcy[i];
645 aStream->which_clip++;
649 "url(#text-clipping%d)", aStream->which_clip - 1 );
682 cos_rot = cos( rotation );
683 sin_rot = -sin( rotation );
684 sin_shear = sin( shear );
685 cos_shear = -cos( shear );
686 t[0] = cos_rot * stride;
687 t[1] = -sin_rot * stride;
688 t[2] = cos_rot * sin_shear + sin_rot * cos_shear;
689 t[3] = -sin_rot * sin_shear + cos_rot * cos_shear;
711 t[0], t[1], t[2], t[3],
712 (
double) ( args->
x / aStream->scale ),
713 (
double) ( args->
y / aStream->scale ) );
727 glyph_size = (int) ftHt;
730 while ( if_write < 2 )
744 if ( args->
just < 0.33 )
749 else if ( args->
just > 0.66 )
766 fprintf( aStream->svgFile,
">" );
775 while ( i < ucs4Len )
787 sum_glyph_size += glyph_size;
801 sum_glyph_size += glyph_size;
814 &old_sscale, &sscale, &old_soffset, &soffset );
820 ddup = 0.5 * ( 1.0 - sscale );
823 scaled_offset =
FONT_SHIFT_RATIO * ftHt * ( 0.80 * ( soffset - old_soffset ) - ( ddup - old_dup ) );
827 scaled_offset = -
FONT_SHIFT_RATIO * ftHt * ( 0.80 * ( soffset - old_soffset ) + ( ddup - old_dup ) );
829 scaled_ftHt = sscale * ftHt;
833 fprintf( aStream->svgFile,
"<tspan dy=\"%f\" font-size=\"%d\">", scaled_offset, (
int) scaled_ftHt );
837 glyph_size = (int) scaled_ftHt;
843 &old_sscale, &sscale, &old_soffset, &soffset );
849 ddup = 0.5 * ( 1.0 - sscale );
852 scaled_offset =
FONT_SHIFT_RATIO * ftHt * ( 0.80 * ( soffset - old_soffset ) - ( ddup - old_dup ) );
856 scaled_offset = -
FONT_SHIFT_RATIO * ftHt * ( 0.80 * ( soffset - old_soffset ) + ( ddup - old_dup ) );
858 scaled_ftHt = sscale * ftHt;
862 fprintf( aStream->svgFile,
"<tspan dy=\"%f\" font-size=\"%d\">", scaled_offset, (
int) scaled_ftHt );
866 glyph_size = (int) scaled_ftHt;
889 for ( i = 0; i < totalTags; i++ )
891 fprintf( aStream->svgFile,
"</tspan>" );
901 fprintf( aStream->svgFile,
"</text>\n" );
902 aStream->svgIndent -= 2;
903 if ( aStream->textClipping )
918 fprintf( aStream->
svgFile,
"<%s\n", tag );
932 fprintf( aStream->
svgFile,
"/>\n" );
946 fprintf( aStream->
svgFile,
"%s=\"%s\"\n", attribute,
value );
963 const char *p, *sval;
968 fprintf( aStream->
svgFile,
"%s=\"", attribute );
969 va_start( ap, format );
970 for ( p = format; *p; p++ )
974 fprintf( aStream->
svgFile,
"%c", *p );
980 ival = va_arg( ap,
int );
981 fprintf( aStream->
svgFile,
"%d", ival );
984 dval = va_arg( ap,
double );
985 fprintf( aStream->
svgFile,
"%f", dval );
989 dval = va_arg( ap,
double );
990 fprintf( aStream->
svgFile,
"%.2f", dval );
993 sval = va_arg( ap,
char * );
994 fprintf( aStream->
svgFile,
"%s", sval );
997 fprintf( aStream->
svgFile,
"%c", *p );
1001 fprintf( aStream->
svgFile,
"\"\n" );
1015 if ( strlen( tag ) > 0 )
1017 fprintf( aStream->
svgFile,
"</%s>\n", tag );
1021 fprintf( aStream->
svgFile,
"/>\n" );
1046 for ( i = 0; i < aStream->
svgIndent; i++ )
1048 fprintf( aStream->
svgFile,
" " );
1079 fprintf( aStream->
svgFile,
"stroke=\"#" );
1083 fprintf( aStream->
svgFile,
"\"\n" );
1100 fprintf( aStream->
svgFile,
"fill=\"#" );
1104 fprintf( aStream->
svgFile,
"\"\n" );
1121 fprintf( aStream->
svgFile,
"fill=\"#" );
1125 fprintf( aStream->
svgFile,
"\"\n" );
1148 plwarn(
"All pages after the first skipped because family file output not specified.\n" );
1164 fprintf( svgFile,
"0%X", val );
1168 fprintf( svgFile,
"%X", val );
1181 if ( ucs4_char >=
' ' || ucs4_char ==
'\t' || ucs4_char ==
'\n' || ucs4_char ==
'\r' )
1182 fprintf( svgFile,
"&#x%x;", ucs4_char );
1184 fprintf( svgFile,
"&#x%x;",
' ' );
1204 fprintf( svgFile,
"<tspan " );
1208 if ( ( ucs4_char & 0x00F ) == 0x000 )
1210 fprintf( svgFile,
"font-family=\"sans-serif\" " );
1212 else if ( ( ucs4_char & 0x00F ) == 0x001 )
1214 fprintf( svgFile,
"font-family=\"serif\" " );
1216 else if ( ( ucs4_char & 0x00F ) == 0x002 )
1218 fprintf( svgFile,
"font-family=\"mono-space\" " );
1220 else if ( ( ucs4_char & 0x00F ) == 0x003 )
1222 fprintf( svgFile,
"font-family=\"cursive\" " );
1224 else if ( ( ucs4_char & 0x00F ) == 0x004 )
1227 fprintf( svgFile,
"font-family=\"sans-serif\" " );
1232 if ( ( ucs4_char & 0x0F0 ) == 0x000 )
1234 fprintf( svgFile,
"font-style=\"normal\" " );
1236 else if ( ( ucs4_char & 0x0F0 ) == 0x010 )
1238 fprintf( svgFile,
"font-style=\"italic\" " );
1240 else if ( ( ucs4_char & 0x0F0 ) == 0x020 )
1242 fprintf( svgFile,
"font-style=\"oblique\" " );
1247 if ( ( ucs4_char & 0xF00 ) == 0x000 )
1249 fprintf( svgFile,
"font-weight=\"normal\">" );
1251 else if ( ( ucs4_char & 0xF00 ) == 0x100 )
1253 fprintf( svgFile,
"font-weight=\"bold\">" );