~ubuntu-branches/ubuntu/oneiric/evince/oneiric-updates

« back to all changes in this revision

Viewing changes to backend/impress/r_text.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-01-10 19:35:11 UTC
  • mto: (1.3.1 experimental) (52.1.1 hardy-proposed)
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: james.westby@ubuntu.com-20070110193511-yjrnndv8e8wv03yy
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* imposter (OO.org Impress viewer)
 
2
** Copyright (C) 2003-2005 Gurer Ozen
 
3
** This code is free software; you can redistribute it and/or
 
4
** modify it under the terms of GNU General Public License.
 
5
*/
 
6
 
 
7
#include "common.h"
 
8
#include "internal.h"
 
9
 
 
10
struct Span {
 
11
        struct Span *next;
 
12
        int x, y;
 
13
        int w, h;
 
14
        char *text;
 
15
        int len;
 
16
        int size;
 
17
        int styles;
 
18
        ImpColor fg;
 
19
};
 
20
 
 
21
struct Line {
 
22
        struct Line *next;
 
23
        struct Span *spans;
 
24
        struct Span *last_span;
 
25
        int x, y;
 
26
        int w, h;
 
27
};
 
28
 
 
29
struct Layout {
 
30
        ikstack *s;
 
31
        int x, y, w, h;
 
32
        int tw, th;
 
33
        struct Line *lines;
 
34
        struct Line *last_line;
 
35
        char spaces[128];
 
36
};
 
37
 
 
38
static struct Line *
 
39
add_line(struct Layout *lay)
 
40
{
 
41
        struct Line *line;
 
42
 
 
43
        line = iks_stack_alloc(lay->s, sizeof(struct Line));
 
44
        memset(line, 0, sizeof(struct Line));
 
45
 
 
46
        if (!lay->lines) lay->lines = line;
 
47
        if (lay->last_line) lay->last_line->next = line;
 
48
        lay->last_line = line;
 
49
 
 
50
        return line;
 
51
}
 
52
 
 
53
static struct Span *
 
54
add_span(struct Layout *lay, char *text, int len, int size, int styles)
 
55
{
 
56
        struct Line *line;
 
57
        struct Span *span;
 
58
 
 
59
        span = iks_stack_alloc(lay->s, sizeof(struct Span));
 
60
        memset(span, 0, sizeof(struct Span));
 
61
        span->text = text;
 
62
        span->len = len;
 
63
        span->size = size;
 
64
        span->styles = styles;
 
65
 
 
66
        line = lay->last_line;
 
67
        if (!line) line = add_line(lay);
 
68
        if (line->spans) {
 
69
                span->x = line->last_span->x + line->last_span->w;
 
70
                span->y = line->last_span->y;
 
71
        } else {
 
72
                span->x = line->x;
 
73
                span->y = line->y;
 
74
        }
 
75
 
 
76
        if (!line->spans) line->spans = span;
 
77
        if (line->last_span) line->last_span->next = span;
 
78
        line->last_span = span;
 
79
 
 
80
        return span;
 
81
}
 
82
 
 
83
static void
 
84
calc_sizes(ImpRenderCtx *ctx, void *drw_data, struct Layout *lay)
 
85
{
 
86
        struct Line *line;
 
87
        struct Span *span;
 
88
 
 
89
        for (line = lay->lines; line; line = line->next) {
 
90
                for (span = line->spans; span; span = span->next) {
 
91
                        ctx->drw->get_text_size(drw_data,
 
92
                                span->text, span->len,
 
93
                                span->size, span->styles,
 
94
                                &span->w, &span->h
 
95
                        );
 
96
                        line->w += span->w;
 
97
                        if (span->h > line->h) line->h = span->h;
 
98
                }
 
99
                if (line->w > lay->tw) lay->tw = line->w;
 
100
                lay->th += line->h;
 
101
        }
 
102
}
 
103
 
 
104
static void
 
105
calc_pos(ImpRenderCtx *ctx, struct Layout *lay)
 
106
{
 
107
        struct Line *line;
 
108
        struct Span *span;
 
109
        int x, y, x2;
 
110
 
 
111
        x = lay->x;
 
112
        y = lay->y;
 
113
        for (line = lay->lines; line; line = line->next) {
 
114
                line->x = x;
 
115
                line->y = y;
 
116
                y += line->h;
 
117
                x2 = x;
 
118
                for (span = line->spans; span; span = span->next) {
 
119
                        span->x = x2;
 
120
                        span->y = y;
 
121
                        x2 += span->w;
 
122
                }
 
123
        }
 
124
}
 
125
 
 
126
static void
 
127
_imp_draw_layout(ImpRenderCtx *ctx, void *drw_data, struct Layout *lay)
 
128
{
 
129
        struct Line *line;
 
130
        struct Span *span;
 
131
 
 
132
        for (line = lay->lines; line; line = line->next) {
 
133
                for (span = line->spans; span; span = span->next) {
 
134
                        ctx->drw->set_fg_color(drw_data, &span->fg);
 
135
                        ctx->drw->draw_text(drw_data,
 
136
                                span->x, span->y,
 
137
                                span->text, span->len,
 
138
                                span->size,
 
139
                                span->styles
 
140
                        );
 
141
                }
 
142
        }
 
143
}
 
144
 
 
145
static void
 
146
text_span(ImpRenderCtx *ctx, struct Layout *lay, iks *node, char *text, size_t len)
 
147
{
 
148
        struct Span *span;
 
149
        double cm;
 
150
        char *attr, *t, *s;
 
151
        int px = 0, cont = 1;
 
152
        int styles = IMP_NORMAL;
 
153
 
 
154
        attr = r_get_style(ctx, node, "fo:font-size");
 
155
        if (attr) {
 
156
                cm = atof(attr);
 
157
                if (strstr(attr, "pt")) cm = cm * 2.54 / 102;
 
158
                px = cm * ctx->fact_y;
 
159
        }
 
160
        attr = r_get_style(ctx, node, "fo:font-weight");
 
161
        if (attr && strcmp(attr, "bold") == 0) styles |= IMP_BOLD;
 
162
        attr = r_get_style(ctx, node, "style:text-underline");
 
163
        if (attr && strcmp(attr, "single") == 0) styles |= IMP_UNDERLINE;
 
164
        attr = r_get_style(ctx, node, "fo:font-style");
 
165
        if (attr && strcmp(attr, "italic") == 0) styles |= IMP_ITALIC;
 
166
 
 
167
        t = text;
 
168
        while (cont) {
 
169
                s = strchr(t, '\n');
 
170
                if (s) {
 
171
                        int len2 = s - t;
 
172
                        span = add_span(lay, t, len2, px, styles);
 
173
                        t = s + 1;
 
174
                        len -= len2;
 
175
                        add_line(lay);
 
176
                } else {
 
177
                        span = add_span(lay, text, len, px, styles);
 
178
                        cont = 0;
 
179
                }
 
180
                r_get_color(ctx, node, "fo:color", &span->fg);
 
181
        }
 
182
}
 
183
 
 
184
static void
 
185
text_p(ImpRenderCtx *ctx, struct Layout *lay, iks *node)
 
186
{
 
187
        iks *n, *n2;
 
188
 
 
189
        add_line(lay);
 
190
        for (n = iks_child(node); n; n = iks_next(n)) {
 
191
                if (iks_type(n) == IKS_CDATA) {
 
192
                        text_span(ctx, lay, node, iks_cdata(n), iks_cdata_size(n));
 
193
                } else if (iks_strcmp(iks_name(n), "text:span") == 0) {
 
194
                        for (n2 = iks_child(n); n2; n2 = iks_next(n2)) {
 
195
                                if (iks_type(n2) == IKS_CDATA) {
 
196
                                        text_span(ctx, lay, n2, iks_cdata(n2), iks_cdata_size(n2));
 
197
                                } else if (iks_strcmp(iks_name(n2), "text:s") == 0) {
 
198
                                        char *attr;
 
199
                                        int c = 1;
 
200
                                        attr = iks_find_attrib(n2, "text:c");
 
201
                                        if (attr) c = atoi(attr);
 
202
                                        if (c > 127) {
 
203
                                                c = 127;
 
204
                                                puts("bork bork");
 
205
                                        }
 
206
                                        text_span(ctx, lay, n, lay->spaces, c);
 
207
                                } else if (iks_strcmp(iks_name(n2), "text:a") == 0) {
 
208
                                        text_span(ctx, lay, n, iks_cdata(iks_child(n2)), iks_cdata_size(iks_child(n2)));
 
209
                                } else if (iks_strcmp(iks_name(n2), "text:tab-stop") == 0) {
 
210
                                        text_span(ctx, lay, n, "\t", 1);
 
211
                                } else if (iks_strcmp(iks_name(n2), "text:page-number") == 0) {
 
212
                                        char buf[8];
 
213
                                        sprintf(buf, "%d", ctx->page->nr);
 
214
                                        text_span(ctx, lay, n, iks_stack_strdup(lay->s, buf, 0), strlen(buf));
 
215
                                }
 
216
                        }
 
217
                } else if (iks_strcmp(iks_name(n), "text:line-break") == 0) {
 
218
                        add_line(lay);
 
219
                } else if (iks_strcmp(iks_name(n), "text:a") == 0) {
 
220
                        text_span(ctx, lay, n, iks_cdata(iks_child(n)), iks_cdata_size(iks_child(n)));
 
221
                } else if (iks_strcmp(iks_name(n), "text:page-number") == 0) {
 
222
                        char buf[8];
 
223
                        sprintf(buf, "%d", ctx->page->nr);
 
224
                        text_span(ctx, lay, n, iks_stack_strdup(lay->s, buf, 0), strlen(buf));
 
225
                }
 
226
        }
 
227
}
 
228
 
 
229
static void
 
230
text_list(ImpRenderCtx *ctx, struct Layout *lay, iks *node)
 
231
{
 
232
        iks *n, *n2;
 
233
 
 
234
        for (n = iks_first_tag(node); n; n = iks_next_tag(n)) {
 
235
                for (n2 = iks_first_tag(n); n2; n2 = iks_next_tag(n2)) {
 
236
                        if (strcmp(iks_name(n2), "text:p") == 0) {
 
237
                                text_p(ctx, lay, n2);
 
238
                        } else if (strcmp(iks_name(n2), "text:ordered-list") == 0) {
 
239
                                text_list(ctx, lay, n2);
 
240
                        } else if (strcmp(iks_name(n2), "text:unordered-list") == 0) {
 
241
                                text_list(ctx, lay, n2);
 
242
                        } else if (strcmp(iks_name(n2), "text:list") == 0) {
 
243
                                text_list(ctx, lay, n2);
 
244
                        }
 
245
                }
 
246
        }
 
247
}
 
248
 
 
249
void
 
250
r_text(ImpRenderCtx *ctx, void *drw_data, iks *node)
 
251
{
 
252
        struct Layout lay;
 
253
        iks *n;
 
254
 
 
255
        memset(&lay, 0, sizeof(struct Layout));
 
256
        memset(&lay.spaces, ' ', 128);
 
257
        lay.s = iks_stack_new(sizeof(struct Span) * 16, 0);
 
258
        lay.x = r_get_x(ctx, node, "svg:x");
 
259
        lay.y = r_get_y(ctx, node, "svg:y");
 
260
        lay.w = r_get_y(ctx, node, "svg:width");
 
261
        lay.h = r_get_y(ctx, node, "svg:height");
 
262
 
 
263
        for (n = iks_first_tag(node); n; n = iks_next_tag(n)) {
 
264
                if (strcmp(iks_name(n), "text:p") == 0) {
 
265
                        text_p(ctx, &lay, n);
 
266
                } else if (strcmp(iks_name(n), "text:ordered-list") == 0) {
 
267
                        text_list(ctx, &lay, n);
 
268
                } else if (strcmp(iks_name(n), "text:unordered-list") == 0) {
 
269
                        text_list(ctx, &lay, n);
 
270
                } else if (strcmp(iks_name(n), "text:list") == 0) {
 
271
                        text_list(ctx, &lay, n);
 
272
                }
 
273
        }
 
274
 
 
275
        calc_sizes(ctx, drw_data, &lay);
 
276
        calc_pos(ctx, &lay);
 
277
        _imp_draw_layout(ctx, drw_data, &lay);
 
278
 
 
279
        iks_stack_delete(lay.s);
 
280
}
 
281
/*
 
282
static void
 
283
text_span (render_ctx *ctx, text_ctx *tc, struct layout_s *lout, iks *node, char *text, int len)
 
284
{
 
285
        if (tc->bullet_flag && tc->bullet_sz) size = tc->bullet_sz; else size = r_get_font_size (ctx, tc, node);
 
286
}
 
287
 
 
288
static int
 
289
is_animated (render_ctx *ctx, text_ctx *tc, iks *node)
 
290
{
 
291
        if (!ctx->step_mode) return 0;
 
292
        if (!tc->id) return 0;
 
293
        while (strcmp (iks_name (node), "draw:page") != 0
 
294
                && strcmp (iks_name (node), "style:master-page") != 0)
 
295
                        node = iks_parent (node);
 
296
        node = iks_find (node, "presentation:animations");
 
297
        if (!node) return 0;
 
298
        if (iks_find_with_attrib (node, "presentation:show-text", "draw:shape-id", tc->id)) return 1;
 
299
        return 0;
 
300
}
 
301
 
 
302
static void
 
303
text_p (render_ctx *ctx, text_ctx *tc, iks *node)
 
304
{
 
305
        if (is_animated (ctx, tc, node) && ctx->step_cnt >= ctx->step) lout->flag = 0;
 
306
        ctx->step_cnt++;
 
307
 
 
308
        attr = r_get_style (ctx, node, "text:enable-numbering");
 
309
        if (attr && strcmp (attr, "true") == 0) {
 
310
                if (iks_child (node) && tc->bullet) {
 
311
                        tc->bullet_flag = 1;
 
312
                        text_span (ctx, tc, lout, node, tc->bullet, strlen (tc->bullet));
 
313
                        text_span (ctx, tc, lout, node, " ", 1);
 
314
                        tc->bullet_flag = 0;
 
315
                }
 
316
        }
 
317
 
 
318
        if (!lout->text) {
 
319
lout->h = 0;
 
320
attr = r_get_style (ctx, node, "fo:line-height");
 
321
if (attr) {
 
322
        int ratio = atoi (attr);
 
323
        lout->lh = ratio;
 
324
} else {
 
325
        lout->lh = 100;
 
326
}
 
327
tc->layouts = g_list_append (tc->layouts, lout);
 
328
//              g_object_unref (lout->play);
 
329
//              iks_stack_delete (s);
 
330
                return;
 
331
        }
 
332
 
 
333
        attr = r_get_style (ctx, node, "fo:text-align");
 
334
        if (attr) {
 
335
                if (strcmp (attr, "center") == 0)
 
336
                        pango_layout_set_alignment (lout->play, PANGO_ALIGN_CENTER);
 
337
                else if (strcmp (attr, "end") == 0)
 
338
                        pango_layout_set_alignment (lout->play, PANGO_ALIGN_RIGHT);
 
339
        }
 
340
        pango_layout_set_width (lout->play, tc->w * PANGO_SCALE);
 
341
        pango_layout_set_markup (lout->play, lout->text, lout->text_len);
 
342
        pango_layout_get_pixel_size (lout->play, &lout->w, &lout->h);
 
343
        attr = r_get_style (ctx, node, "fo:line-height");
 
344
        if (attr) {
 
345
                int ratio = atoi (attr);
 
346
                lout->lh = ratio;
 
347
        } else {
 
348
                lout->lh = 100;
 
349
        }
 
350
        tc->layouts = g_list_append (tc->layouts, lout);
 
351
}
 
352
 
 
353
static void
 
354
find_bullet (render_ctx *ctx, text_ctx *tc, iks *node)
 
355
{
 
356
        iks *x;
 
357
        char *t;
 
358
        x = r_get_bullet (ctx, node, "text:list-level-style-bullet");
 
359
        x = iks_find (x, "text:list-level-style-bullet");
 
360
        t = iks_find_attrib (x, "text:bullet-char");
 
361
        if (t) tc->bullet = t; else tc->bullet = "*";
 
362
        x = iks_find (x, "style:properties");
 
363
        t = iks_find_attrib (x, "fo:font-size");
 
364
        if (t) tc->bullet_sz = tc->last_sz * atoi (t) / 100;
 
365
        else tc->bullet_sz = 0;
 
366
}
 
367
 
 
368
void
 
369
r_text (render_ctx *ctx, iks *node)
 
370
{
 
371
        tc.id = iks_find_attrib (node, "draw:id");
 
372
        ctx->step_cnt = 0;
 
373
        for (n = iks_first_tag (node); n; n = iks_next_tag (n)) {
 
374
                if (strcmp (iks_name (n), "text:p") == 0) {
 
375
                        text_p (ctx, &tc, n);
 
376
                } else if (strcmp (iks_name (n), "text:ordered-list") == 0) {
 
377
                        text_list (ctx, &tc, n);
 
378
                } else if (strcmp (iks_name (n), "text:unordered-list") == 0) {
 
379
                        find_bullet (ctx, &tc, n);
 
380
                        text_list (ctx, &tc, n);
 
381
                        tc.bullet = 0;
 
382
                }
 
383
        }
 
384
 
 
385
*/