1 /* text.c
2
3 Part of the swftools package.
4
5 Copyright (c) 2006 Matthias Kramm <kramm@quiss.org>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <stdarg.h>
25 #include <unistd.h>
26 #include <memory.h>
27 #include "../types.h"
28 #include "../mem.h"
29 #include "../gfxdevice.h"
30 #include "../gfxtools.h"
31 #include "../utf8.h"
32
33 typedef struct _textpage {
34 char*text;
35 int textsize;
36 int textpos;
37 struct _textpage*next;
38 } textpage_t;
39
40 typedef struct _internal {
41 textpage_t*first_page;
42 textpage_t*current_page;
43 double currentx;
44 double currenty;
45 double lastadvance;
46 } internal_t;
47
text_setparameter(gfxdevice_t * dev,const char * key,const char * value)48 int text_setparameter(gfxdevice_t*dev, const char*key, const char*value)
49 {
50 internal_t*i = (internal_t*)dev->internal;
51 return 0;
52 }
text_startpage(gfxdevice_t * dev,int width,int height)53 void text_startpage(gfxdevice_t*dev, int width, int height)
54 {
55 internal_t*i = (internal_t*)dev->internal;
56 if(!i->first_page) {
57 i->first_page = i->current_page = (textpage_t*)malloc(sizeof(textpage_t));
58 } else {
59 i->current_page->next = (textpage_t*)malloc(sizeof(textpage_t));
60 i->current_page = i->current_page->next;
61 }
62 i->current_page->textsize = 4096;
63 i->current_page->text = (char*)malloc(i->current_page->textsize);
64 i->current_page->textpos = 0;
65 i->current_page->next = 0;
66 i->currentx = 0;
67 i->currenty = 0;
68 i->lastadvance = 0;
69 }
text_startclip(gfxdevice_t * dev,gfxline_t * line)70 void text_startclip(gfxdevice_t*dev, gfxline_t*line)
71 {
72 internal_t*i = (internal_t*)dev->internal;
73 }
text_endclip(gfxdevice_t * dev)74 void text_endclip(gfxdevice_t*dev)
75 {
76 internal_t*i = (internal_t*)dev->internal;
77 }
text_stroke(gfxdevice_t * dev,gfxline_t * line,gfxcoord_t width,gfxcolor_t * color,gfx_capType cap_style,gfx_joinType joint_style,gfxcoord_t miterLimit)78 void text_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit)
79 {
80 internal_t*i = (internal_t*)dev->internal;
81 }
text_fill(gfxdevice_t * dev,gfxline_t * line,gfxcolor_t * color)82 void text_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
83 {
84 internal_t*i = (internal_t*)dev->internal;
85 }
text_fillbitmap(gfxdevice_t * dev,gfxline_t * line,gfximage_t * img,gfxmatrix_t * matrix,gfxcxform_t * cxform)86 void text_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
87 {
88 internal_t*i = (internal_t*)dev->internal;
89 }
text_fillgradient(gfxdevice_t * dev,gfxline_t * line,gfxgradient_t * gradient,gfxgradienttype_t type,gfxmatrix_t * matrix)90 void text_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
91 {
92 internal_t*i = (internal_t*)dev->internal;
93 }
text_addfont(gfxdevice_t * dev,gfxfont_t * font)94 void text_addfont(gfxdevice_t*dev, gfxfont_t*font) {}
95
addchar(gfxdevice_t * dev,int unicode)96 static void addchar(gfxdevice_t*dev, int unicode)
97 {
98 internal_t*i = (internal_t*)dev->internal;
99 if(!i->current_page) {
100 text_startpage(dev, 0, 0);
101 }
102 if(i->current_page->textpos + 10 > i->current_page->textsize) {
103 i->current_page->textsize += 4096;
104 i->current_page->text = realloc(i->current_page->text, i->current_page->textsize);
105 }
106 writeUTF8(unicode, &i->current_page->text[i->current_page->textpos]);
107 i->current_page->textpos += strlen(&i->current_page->text[i->current_page->textpos]);
108 }
109
text_drawchar(gfxdevice_t * dev,gfxfont_t * font,int glyphnr,gfxcolor_t * color,gfxmatrix_t * matrix)110 void text_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
111 {
112 internal_t*i = (internal_t*)dev->internal;
113 double xshift = matrix->tx - i->currentx;
114 double yshift = matrix->ty - i->currenty;
115 i->currentx = matrix->tx;
116 i->currenty = matrix->ty;
117
118 if(fabs(yshift)>1.0) {
119 addchar(dev, 10);
120 } else if(xshift > i->lastadvance*1.3 || xshift<0) {
121 addchar(dev, 32);
122 }
123 int u;
124 if(font) {
125 i->lastadvance = font->glyphs[glyphnr].advance*matrix->m00;
126 u = font->glyphs[glyphnr].unicode;
127 } else {
128 u = glyphnr;
129 i->currentx = 0;i->currenty = 0;
130 }
131 if(u>13) {
132 addchar(dev, u);
133 }
134 }
135
text_drawlink(gfxdevice_t * dev,gfxline_t * line,const char * action,const char * drawlink)136 void text_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action, const char*drawlink)
137 {
138 internal_t*i = (internal_t*)dev->internal;
139 }
140
text_endpage(gfxdevice_t * dev)141 void text_endpage(gfxdevice_t*dev)
142 {
143 internal_t*i = (internal_t*)dev->internal;
144 }
145
text_result_write(gfxresult_t * r,int filedesc)146 void text_result_write(gfxresult_t*r, int filedesc)
147 {
148 textpage_t*i= (textpage_t*)r->internal;
149 }
text_result_save(gfxresult_t * r,const char * filename)150 int text_result_save(gfxresult_t*r, const char*filename)
151 {
152 textpage_t*i= (textpage_t*)r->internal;
153 if(!i) {
154 return 0; // no pages drawn
155 }
156 FILE*fi = fopen(filename, "wb");
157 if(!fi)
158 return 0;
159 while(i) {
160 fwrite(i->text, i->textpos, 1, fi);
161 i = i->next;
162 }
163 fclose(fi);
164 return 1;
165 }
text_result_get(gfxresult_t * r,const char * name)166 void*text_result_get(gfxresult_t*r, const char*name)
167 {
168 textpage_t*i= (textpage_t*)r->internal;
169 if(!strcmp(name,"text")) {
170 textpage_t*j = i;
171 int len = 0;
172 while(j) {
173 len += i->textpos;
174 j = j->next;
175 }
176 char*text = (char*)malloc(len);
177 int pos = 0;
178 j = i;
179 while(j) {
180 memcpy(&text[pos], i->text, i->textpos);
181 pos += i->textpos;
182 j = j->next;
183 }
184 text[pos] = 0;
185 return text;
186 } else if(!strncmp(name,"page",4)) {
187 int pagenr = atoi(&name[4]);
188 if(pagenr<0)
189 pagenr=0;
190 while(pagenr>0) {
191 i = i->next;
192 if(!i)
193 return 0;
194 }
195 i->text[i->textpos] = 0;
196 return strdup(i->text);
197 }
198 return 0;
199 }
text_result_destroy(gfxresult_t * r)200 void text_result_destroy(gfxresult_t*r)
201 {
202 textpage_t*i= (textpage_t*)r->internal;
203 r->internal = 0;
204 while(i) {
205 textpage_t*next = i->next;
206 free(i->text);i->text = 0;
207 free(i);
208 i = next;
209 }
210 free(r);
211 }
212
text_finish(struct _gfxdevice * dev)213 gfxresult_t* text_finish(struct _gfxdevice*dev)
214 {
215 internal_t*i = (internal_t*)dev->internal;
216
217 gfxresult_t* res = (gfxresult_t*)rfx_calloc(sizeof(gfxresult_t));
218
219 res->internal = i->first_page;i->first_page = 0;i->current_page=0;
220 res->write = text_result_write;
221 res->save = text_result_save;
222 res->get = text_result_get;
223 res->destroy = text_result_destroy;
224
225 free(dev->internal); dev->internal = 0; i = 0;
226
227 return res;
228 }
229
230
231
gfxdevice_text_init(gfxdevice_t * dev,gfxdevice_t * out)232 void gfxdevice_text_init(gfxdevice_t*dev, gfxdevice_t*out)
233 {
234 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
235 memset(dev, 0, sizeof(gfxdevice_t));
236
237 dev->name = "text";
238
239 dev->internal = i;
240
241 dev->setparameter = text_setparameter;
242 dev->startpage = text_startpage;
243 dev->startclip = text_startclip;
244 dev->endclip = text_endclip;
245 dev->stroke = text_stroke;
246 dev->fill = text_fill;
247 dev->fillbitmap = text_fillbitmap;
248 dev->fillgradient = text_fillgradient;
249 dev->addfont = text_addfont;
250 dev->drawchar = text_drawchar;
251 dev->drawlink = text_drawlink;
252 dev->endpage = text_endpage;
253 dev->finish = text_finish;
254 }
255
256