NetSurf
redraw.c
Go to the documentation of this file.
1/*
2 * Copyright 2004-2008 James Bursa <bursa@users.sourceforge.net>
3 * Copyright 2004-2007 John M Bell <jmb202@ecs.soton.ac.uk>
4 * Copyright 2004-2007 Richard Wilson <info@tinct.net>
5 * Copyright 2005-2006 Adrian Lees <adrianl@users.sourceforge.net>
6 * Copyright 2006 Rob Kendrick <rjek@netsurf-browser.org>
7 * Copyright 2008 Michael Drake <tlsa@netsurf-browser.org>
8 * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
9 *
10 * This file is part of NetSurf, http://www.netsurf-browser.org/
11 *
12 * NetSurf is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2 of the License.
15 *
16 * NetSurf is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25/**
26 * \file
27 *
28 * Redrawing CONTENT_HTML implementation.
29 */
30
31#include "utils/config.h"
32#include <assert.h>
33#include <stdbool.h>
34#include <stdlib.h>
35#include <string.h>
36#include <math.h>
37#include <dom/dom.h>
38
39#include "utils/log.h"
40#include "utils/messages.h"
41#include "utils/utils.h"
42#include "utils/nsoption.h"
43#include "utils/corestrings.h"
44#include "netsurf/content.h"
46#include "netsurf/plotters.h"
47#include "netsurf/bitmap.h"
48#include "netsurf/layout.h"
49#include "content/content.h"
51#include "content/textsearch.h"
52#include "css/utils.h"
53#include "desktop/selection.h"
54#include "desktop/print.h"
55#include "desktop/scrollbar.h"
56#include "desktop/textarea.h"
58
59#include "html/box.h"
60#include "html/box_inspect.h"
61#include "html/box_manipulate.h"
62#include "html/font.h"
63#include "html/form_internal.h"
64#include "html/private.h"
65#include "html/layout.h"
66
67
68bool html_redraw_debug = false;
69
70/**
71 * Determine if a box has a background that needs drawing
72 *
73 * \param box Box to consider
74 * \return True if box has a background, false otherwise.
75 */
77{
78 if (box->background != NULL)
79 return true;
80
81 if (box->style != NULL) {
82 css_color colour;
83
84 css_computed_background_color(box->style, &colour);
85
87 return true;
88 }
89
90 return false;
91}
92
93/**
94 * Find the background box for a box
95 *
96 * \param box Box to find background box for
97 * \return Pointer to background box, or NULL if there is none
98 */
99static struct box *html_redraw_find_bg_box(struct box *box)
100{
101 /* Thanks to backwards compatibility, CSS defines the following:
102 *
103 * + If the box is for the root element and it has a background,
104 * use that (and then process the body box with no special case)
105 * + If the box is for the root element and it has no background,
106 * then use the background (if any) from the body element as if
107 * it were specified on the root. Then, when the box for the body
108 * element is processed, ignore the background.
109 * + For any other box, just use its own styling.
110 */
111 if (box->parent == NULL) {
112 /* Root box */
114 return box;
115
116 /* No background on root box: consider body box, if any */
117 if (box->children != NULL) {
119 return box->children;
120 }
121 } else if (box->parent != NULL && box->parent->parent == NULL) {
122 /* Body box: only render background if root has its own */
125 return box;
126 } else {
127 /* Any other box */
129 return box;
130 }
131
132 return NULL;
133}
134
135/**
136 * Redraw a short text string, complete with highlighting
137 * (for selection/search)
138 *
139 * \param utf8_text pointer to UTF-8 text string
140 * \param utf8_len length of string, in bytes
141 * \param offset byte offset within textual representation
142 * \param space width of space that follows string (0 = no space)
143 * \param fstyle text style to use (pass text size unscaled)
144 * \param x x ordinate at which to plot text
145 * \param y y ordinate at which to plot text
146 * \param clip pointer to current clip rectangle
147 * \param height height of text string
148 * \param scale current display scale (1.0 = 100%)
149 * \param excluded exclude this text string from the selection
150 * \param c Content being redrawn.
151 * \param sel Selection context
152 * \param search Search context
153 * \param ctx current redraw context
154 * \return true iff successful and redraw should proceed
155 */
156
157static bool
158text_redraw(const char *utf8_text,
159 size_t utf8_len,
160 size_t offset,
161 int space,
162 const plot_font_style_t *fstyle,
163 int x,
164 int y,
165 const struct rect *clip,
166 int height,
167 float scale,
168 bool excluded,
169 struct content *c,
170 const struct selection *sel,
171 const struct redraw_context *ctx)
172{
173 bool highlighted = false;
174 plot_font_style_t plot_fstyle = *fstyle;
175 nserror res;
176
177 /* Need scaled text size to pass to plotters */
178 plot_fstyle.size *= scale;
179
180 /* is this box part of a selection? */
181 if (!excluded && ctx->interactive == true) {
182 unsigned len = utf8_len + (space ? 1 : 0);
183 unsigned start_idx;
184 unsigned end_idx;
185
186 /* first try the browser window's current selection */
187 if (selection_highlighted(sel,
188 offset,
189 offset + len,
190 &start_idx,
191 &end_idx)) {
192 highlighted = true;
193 }
194
195 /* what about the current search operation, if any? */
196 if (!highlighted &&
197 (c->textsearch.context != NULL) &&
199 offset,
200 offset + len,
201 &start_idx,
202 &end_idx)) {
203 highlighted = true;
204 }
205
206 /* \todo make search terms visible within selected text */
207 if (highlighted) {
208 struct rect r;
209 unsigned endtxt_idx = end_idx;
210 bool clip_changed = false;
211 bool text_visible = true;
212 int startx, endx;
213 plot_style_t pstyle_fill_hback = *plot_style_fill_white;
214 plot_font_style_t fstyle_hback = plot_fstyle;
215
216 if (end_idx > utf8_len) {
217 /* adjust for trailing space, not present in
218 * utf8_text */
219 assert(end_idx == utf8_len + 1);
220 endtxt_idx = utf8_len;
221 }
222
223 res = guit->layout->width(fstyle,
224 utf8_text, start_idx,
225 &startx);
226 if (res != NSERROR_OK) {
227 startx = 0;
228 }
229
230 res = guit->layout->width(fstyle,
231 utf8_text, endtxt_idx,
232 &endx);
233 if (res != NSERROR_OK) {
234 endx = 0;
235 }
236
237 /* is there a trailing space that should be highlighted
238 * as well? */
239 if (end_idx > utf8_len) {
240 endx += space;
241 }
242
243 if (scale != 1.0) {
244 startx *= scale;
245 endx *= scale;
246 }
247
248 /* draw any text preceding highlighted portion */
249 if ((start_idx > 0) &&
250 (ctx->plot->text(ctx,
251 &plot_fstyle,
252 x,
253 y + (int)(height * 0.75 * scale),
254 utf8_text,
255 start_idx) != NSERROR_OK))
256 return false;
257
258 pstyle_fill_hback.fill_colour = fstyle->foreground;
259
260 /* highlighted portion */
261 r.x0 = x + startx;
262 r.y0 = y;
263 r.x1 = x + endx;
264 r.y1 = y + height * scale;
265 res = ctx->plot->rectangle(ctx, &pstyle_fill_hback, &r);
266 if (res != NSERROR_OK) {
267 return false;
268 }
269
270 if (start_idx > 0) {
271 int px0 = max(x + startx, clip->x0);
272 int px1 = min(x + endx, clip->x1);
273
274 if (px0 < px1) {
275 r.x0 = px0;
276 r.y0 = clip->y0;
277 r.x1 = px1;
278 r.y1 = clip->y1;
279 res = ctx->plot->clip(ctx, &r);
280 if (res != NSERROR_OK) {
281 return false;
282 }
283
284 clip_changed = true;
285 } else {
286 text_visible = false;
287 }
288 }
289
290 fstyle_hback.background =
291 pstyle_fill_hback.fill_colour;
292 fstyle_hback.foreground = colour_to_bw_furthest(
293 pstyle_fill_hback.fill_colour);
294
295 if (text_visible &&
296 (ctx->plot->text(ctx,
297 &fstyle_hback,
298 x,
299 y + (int)(height * 0.75 * scale),
300 utf8_text,
301 endtxt_idx) != NSERROR_OK)) {
302 return false;
303 }
304
305 /* draw any text succeeding highlighted portion */
306 if (endtxt_idx < utf8_len) {
307 int px0 = max(x + endx, clip->x0);
308 if (px0 < clip->x1) {
309
310 r.x0 = px0;
311 r.y0 = clip->y0;
312 r.x1 = clip->x1;
313 r.y1 = clip->y1;
314 res = ctx->plot->clip(ctx, &r);
315 if (res != NSERROR_OK) {
316 return false;
317 }
318
319 clip_changed = true;
320
321 res = ctx->plot->text(ctx,
322 &plot_fstyle,
323 x,
324 y + (int)(height * 0.75 * scale),
325 utf8_text,
326 utf8_len);
327 if (res != NSERROR_OK) {
328 return false;
329 }
330 }
331 }
332
333 if (clip_changed &&
334 (ctx->plot->clip(ctx, clip) != NSERROR_OK)) {
335 return false;
336 }
337 }
338 }
339
340 if (!highlighted) {
341 res = ctx->plot->text(ctx,
342 &plot_fstyle,
343 x,
344 y + (int) (height * 0.75 * scale),
345 utf8_text,
346 utf8_len);
347 if (res != NSERROR_OK) {
348 return false;
349 }
350 }
351 return true;
352}
353
354
355/**
356 * Plot a checkbox.
357 *
358 * \param x left coordinate
359 * \param y top coordinate
360 * \param width dimensions of checkbox
361 * \param height dimensions of checkbox
362 * \param selected the checkbox is selected
363 * \param ctx current redraw context
364 * \return true if successful, false otherwise
365 */
366
367static bool html_redraw_checkbox(int x, int y, int width, int height,
368 bool selected, const struct redraw_context *ctx)
369{
370 double z;
371 nserror res;
372 struct rect rect;
373
374 z = width * 0.15;
375 if (z == 0) {
376 z = 1;
377 }
378
379 rect.x0 = x;
380 rect.y0 = y ;
381 rect.x1 = x + width;
382 rect.y1 = y + height;
383 res = ctx->plot->rectangle(ctx, plot_style_fill_wbasec, &rect);
384 if (res != NSERROR_OK) {
385 return false;
386 }
387
388 /* dark line across top */
389 rect.y1 = y;
390 res = ctx->plot->line(ctx, plot_style_stroke_darkwbasec, &rect);
391 if (res != NSERROR_OK) {
392 return false;
393 }
394
395 /* dark line across left */
396 rect.x1 = x;
397 rect.y1 = y + height;
398 res = ctx->plot->line(ctx, plot_style_stroke_darkwbasec, &rect);
399 if (res != NSERROR_OK) {
400 return false;
401 }
402
403 /* light line across right */
404 rect.x0 = x + width;
405 rect.x1 = x + width;
406 res = ctx->plot->line(ctx, plot_style_stroke_lightwbasec, &rect);
407 if (res != NSERROR_OK) {
408 return false;
409 }
410
411 /* light line across bottom */
412 rect.x0 = x;
413 rect.y0 = y + height;
414 res = ctx->plot->line(ctx, plot_style_stroke_lightwbasec, &rect);
415 if (res != NSERROR_OK) {
416 return false;
417 }
418
419 if (selected) {
420 if (width < 12 || height < 12) {
421 /* render a solid box instead of a tick */
422 rect.x0 = x + z + z;
423 rect.y0 = y + z + z;
424 rect.x1 = x + width - z;
425 rect.y1 = y + height - z;
426 res = ctx->plot->rectangle(ctx, plot_style_fill_wblobc, &rect);
427 if (res != NSERROR_OK) {
428 return false;
429 }
430 } else {
431 /* render a tick, as it'll fit comfortably */
432 rect.x0 = x + width - z;
433 rect.y0 = y + z;
434 rect.x1 = x + (z * 3);
435 rect.y1 = y + height - z;
436 res = ctx->plot->line(ctx, plot_style_stroke_wblobc, &rect);
437 if (res != NSERROR_OK) {
438 return false;
439 }
440
441 rect.x0 = x + (z * 3);
442 rect.y0 = y + height - z;
443 rect.x1 = x + z + z;
444 rect.y1 = y + (height / 2);
445 res = ctx->plot->line(ctx, plot_style_stroke_wblobc, &rect);
446 if (res != NSERROR_OK) {
447 return false;
448 }
449 }
450 }
451 return true;
452}
453
454
455/**
456 * Plot a radio icon.
457 *
458 * \param x left coordinate
459 * \param y top coordinate
460 * \param width dimensions of radio icon
461 * \param height dimensions of radio icon
462 * \param selected the radio icon is selected
463 * \param ctx current redraw context
464 * \return true if successful, false otherwise
465 */
466static bool html_redraw_radio(int x, int y, int width, int height,
467 bool selected, const struct redraw_context *ctx)
468{
469 nserror res;
470
471 /* plot background of radio button */
472 res = ctx->plot->disc(ctx,
474 x + width * 0.5,
475 y + height * 0.5,
476 width * 0.5 - 1);
477 if (res != NSERROR_OK) {
478 return false;
479 }
480
481 /* plot dark arc */
482 res = ctx->plot->arc(ctx,
484 x + width * 0.5,
485 y + height * 0.5,
486 width * 0.5 - 1,
487 45,
488 225);
489 if (res != NSERROR_OK) {
490 return false;
491 }
492
493 /* plot light arc */
494 res = ctx->plot->arc(ctx,
496 x + width * 0.5,
497 y + height * 0.5,
498 width * 0.5 - 1,
499 225,
500 45);
501 if (res != NSERROR_OK) {
502 return false;
503 }
504
505 if (selected) {
506 /* plot selection blob */
507 res = ctx->plot->disc(ctx,
509 x + width * 0.5,
510 y + height * 0.5,
511 width * 0.3 - 1);
512 if (res != NSERROR_OK) {
513 return false;
514 }
515 }
516
517 return true;
518}
519
520
521/**
522 * Plot a file upload input.
523 *
524 * \param x left coordinate
525 * \param y top coordinate
526 * \param width dimensions of input
527 * \param height dimensions of input
528 * \param box box of input
529 * \param scale scale for redraw
530 * \param background_colour current background colour
531 * \param unit_len_ctx Length conversion context
532 * \param ctx current redraw context
533 * \return true if successful, false otherwise
534 */
535
536static bool html_redraw_file(int x, int y, int width, int height,
537 struct box *box, float scale, colour background_colour,
538 const css_unit_ctx *unit_len_ctx,
539 const struct redraw_context *ctx)
540{
541 int text_width;
542 const char *text;
543 size_t length;
544 plot_font_style_t fstyle;
545 nserror res;
546
547 font_plot_style_from_css(unit_len_ctx, box->style, &fstyle);
548 fstyle.background = background_colour;
549
550 if (box->gadget->value) {
551 text = box->gadget->value;
552 } else {
553 text = messages_get("Form_Drop");
554 }
555 length = strlen(text);
556
557 res = guit->layout->width(&fstyle, text, length, &text_width);
558 if (res != NSERROR_OK) {
559 return false;
560 }
561 text_width *= scale;
562 if (width < text_width + 8) {
563 x = x + width - text_width - 4;
564 } else {
565 x = x + 4;
566 }
567
568 res = ctx->plot->text(ctx, &fstyle, x, y + height * 0.75, text, length);
569 if (res != NSERROR_OK) {
570 return false;
571 }
572 return true;
573}
574
575
576/**
577 * Plot background images.
578 *
579 * The reason for the presence of \a background is the backwards compatibility
580 * mess that is backgrounds on &lt;body&gt;. The background will be drawn relative
581 * to \a box, using the background information contained within \a background.
582 *
583 * \param x coordinate of box
584 * \param y coordinate of box
585 * \param box box to draw background image of
586 * \param scale scale for redraw
587 * \param clip current clip rectangle
588 * \param background_colour current background colour
589 * \param background box containing background details (usually \a box)
590 * \param unit_len_ctx Length conversion context
591 * \param ctx current redraw context
592 * \return true if successful, false otherwise
593 */
594
595static bool html_redraw_background(int x, int y, struct box *box, float scale,
596 const struct rect *clip, colour *background_colour,
597 struct box *background,
598 const css_unit_ctx *unit_len_ctx,
599 const struct redraw_context *ctx)
600{
601 bool repeat_x = false;
602 bool repeat_y = false;
603 bool plot_colour = true;
604 bool plot_content;
605 bool clip_to_children = false;
606 struct box *clip_box = box;
607 int ox = x, oy = y;
608 int width, height;
609 css_fixed hpos = 0, vpos = 0;
610 css_unit hunit = CSS_UNIT_PX, vunit = CSS_UNIT_PX;
611 struct box *parent;
612 struct rect r = *clip;
613 css_color bgcol;
614 plot_style_t pstyle_fill_bg = {
616 .fill_colour = *background_colour,
617 };
618 nserror res;
619
620 if (ctx->background_images == false)
621 return true;
622
623 plot_content = (background->background != NULL);
624
625 if (plot_content) {
626 if (!box->parent) {
627 /* Root element, special case:
628 * background origin calc. is based on margin box */
629 x -= box->margin[LEFT] * scale;
630 y -= box->margin[TOP] * scale;
632 box->width + box->padding[RIGHT] +
633 box->margin[RIGHT];
634 height = box->margin[TOP] + box->padding[TOP] +
636 box->margin[BOTTOM];
637 } else {
638 width = box->padding[LEFT] + box->width +
639 box->padding[RIGHT];
640 height = box->padding[TOP] + box->height +
642 }
643 /* handle background-repeat */
644 switch (css_computed_background_repeat(background->style)) {
645 case CSS_BACKGROUND_REPEAT_REPEAT:
646 repeat_x = repeat_y = true;
647 /* optimisation: only plot the colour if
648 * bitmap is not opaque */
649 plot_colour = !content_get_opaque(background->background);
650 break;
651
652 case CSS_BACKGROUND_REPEAT_REPEAT_X:
653 repeat_x = true;
654 break;
655
656 case CSS_BACKGROUND_REPEAT_REPEAT_Y:
657 repeat_y = true;
658 break;
659
660 case CSS_BACKGROUND_REPEAT_NO_REPEAT:
661 break;
662
663 default:
664 break;
665 }
666
667 /* handle background-position */
668 css_computed_background_position(background->style,
669 &hpos, &hunit, &vpos, &vunit);
670 if (hunit == CSS_UNIT_PCT) {
671 x += (width -
672 content_get_width(background->background)) *
673 scale * FIXTOFLT(hpos) / 100.;
674 } else {
675 x += (int) (FIXTOFLT(css_unit_len2device_px(
676 background->style, unit_len_ctx,
677 hpos, hunit)) * scale);
678 }
679
680 if (vunit == CSS_UNIT_PCT) {
681 y += (height -
682 content_get_height(background->background)) *
683 scale * FIXTOFLT(vpos) / 100.;
684 } else {
685 y += (int) (FIXTOFLT(css_unit_len2device_px(
686 background->style, unit_len_ctx,
687 vpos, vunit)) * scale);
688 }
689 }
690
691 /* special case for table rows as their background needs
692 * to be clipped to all the cells */
693 if (box->type == BOX_TABLE_ROW) {
694 css_fixed h = 0, v = 0;
695 css_unit hu = CSS_UNIT_PX, vu = CSS_UNIT_PX;
696
697 for (parent = box->parent;
698 ((parent) && (parent->type != BOX_TABLE));
699 parent = parent->parent);
700 assert(parent && (parent->style));
701
702 css_computed_border_spacing(parent->style, &h, &hu, &v, &vu);
703
704 clip_to_children = (h > 0) || (v > 0);
705
706 if (clip_to_children)
707 clip_box = box->children;
708 }
709
710 for (; clip_box; clip_box = clip_box->next) {
711 /* clip to child boxes if needed */
712 if (clip_to_children) {
713 assert(clip_box->type == BOX_TABLE_CELL);
714
715 /* update clip.* to the child cell */
716 r.x0 = ox + (clip_box->x * scale);
717 r.y0 = oy + (clip_box->y * scale);
718 r.x1 = r.x0 + (clip_box->padding[LEFT] +
719 clip_box->width +
720 clip_box->padding[RIGHT]) * scale;
721 r.y1 = r.y0 + (clip_box->padding[TOP] +
722 clip_box->height +
723 clip_box->padding[BOTTOM]) * scale;
724
725 if (r.x0 < clip->x0) r.x0 = clip->x0;
726 if (r.y0 < clip->y0) r.y0 = clip->y0;
727 if (r.x1 > clip->x1) r.x1 = clip->x1;
728 if (r.y1 > clip->y1) r.y1 = clip->y1;
729
730 css_computed_background_color(clip_box->style, &bgcol);
731
732 /* <td> attributes override <tr> */
733 /* if the background content is opaque there
734 * is no need to plot underneath it.
735 */
736 if ((r.x0 >= r.x1) ||
737 (r.y0 >= r.y1) ||
738 (nscss_color_is_transparent(bgcol) == false) ||
739 ((clip_box->background != NULL) &&
740 content_get_opaque(clip_box->background)))
741 continue;
742 }
743
744 /* plot the background colour */
745 css_computed_background_color(background->style, &bgcol);
746
747 if (nscss_color_is_transparent(bgcol) == false) {
748 *background_colour = nscss_color_to_ns(bgcol);
749 pstyle_fill_bg.fill_colour = *background_colour;
750 if (plot_colour) {
751 res = ctx->plot->rectangle(ctx, &pstyle_fill_bg, &r);
752 if (res != NSERROR_OK) {
753 return false;
754 }
755 }
756 }
757 /* and plot the image */
758 if (plot_content) {
759 width = content_get_width(background->background);
760 height = content_get_height(background->background);
761
762 /* ensure clip area only as large as required */
763 if (!repeat_x) {
764 if (r.x0 < x)
765 r.x0 = x;
766 if (r.x1 > x + width * scale)
767 r.x1 = x + width * scale;
768 }
769 if (!repeat_y) {
770 if (r.y0 < y)
771 r.y0 = y;
772 if (r.y1 > y + height * scale)
773 r.y1 = y + height * scale;
774 }
775 /* valid clipping rectangles only */
776 if ((r.x0 < r.x1) && (r.y0 < r.y1)) {
777 struct content_redraw_data bg_data;
778
779 res = ctx->plot->clip(ctx, &r);
780 if (res != NSERROR_OK) {
781 return false;
782 }
783
784 bg_data.x = x;
785 bg_data.y = y;
786 bg_data.width = ceilf(width * scale);
787 bg_data.height = ceilf(height * scale);
789 bg_data.scale = scale;
790 bg_data.repeat_x = repeat_x;
791 bg_data.repeat_y = repeat_y;
792
793 /* We just continue if redraw fails */
794 content_redraw(background->background,
795 &bg_data, &r, ctx);
796 }
797 }
798
799 /* only <tr> rows being clipped to child boxes loop */
800 if (!clip_to_children)
801 return true;
802 }
803 return true;
804}
805
806
807/**
808 * Plot an inline's background and/or background image.
809 *
810 * \param x coordinate of box
811 * \param y coordinate of box
812 * \param box BOX_INLINE which created the background
813 * \param scale scale for redraw
814 * \param clip coordinates of clip rectangle
815 * \param b coordinates of border edge rectangle
816 * \param first true if this is the first rectangle associated with the inline
817 * \param last true if this is the last rectangle associated with the inline
818 * \param background_colour updated to current background colour if plotted
819 * \param unit_len_ctx Length conversion context
820 * \param ctx current redraw context
821 * \return true if successful, false otherwise
822 */
823
824static bool html_redraw_inline_background(int x, int y, struct box *box,
825 float scale, const struct rect *clip, struct rect b,
826 bool first, bool last, colour *background_colour,
827 const css_unit_ctx *unit_len_ctx,
828 const struct redraw_context *ctx)
829{
830 struct rect r = *clip;
831 bool repeat_x = false;
832 bool repeat_y = false;
833 bool plot_colour = true;
834 bool plot_content;
835 css_fixed hpos = 0, vpos = 0;
836 css_unit hunit = CSS_UNIT_PX, vunit = CSS_UNIT_PX;
837 css_color bgcol;
838 plot_style_t pstyle_fill_bg = {
840 .fill_colour = *background_colour,
841 };
842 nserror res;
843
844 plot_content = (box->background != NULL);
845
846 if (html_redraw_printing && nsoption_bool(remove_backgrounds))
847 return true;
848
849 if (plot_content) {
850 /* handle background-repeat */
851 switch (css_computed_background_repeat(box->style)) {
852 case CSS_BACKGROUND_REPEAT_REPEAT:
853 repeat_x = repeat_y = true;
854 /* optimisation: only plot the colour if
855 * bitmap is not opaque
856 */
857 plot_colour = !content_get_opaque(box->background);
858 break;
859
860 case CSS_BACKGROUND_REPEAT_REPEAT_X:
861 repeat_x = true;
862 break;
863
864 case CSS_BACKGROUND_REPEAT_REPEAT_Y:
865 repeat_y = true;
866 break;
867
868 case CSS_BACKGROUND_REPEAT_NO_REPEAT:
869 break;
870
871 default:
872 break;
873 }
874
875 /* handle background-position */
876 css_computed_background_position(box->style,
877 &hpos, &hunit, &vpos, &vunit);
878 if (hunit == CSS_UNIT_PCT) {
879 x += (b.x1 - b.x0 -
881 scale) * FIXTOFLT(hpos) / 100.;
882
883 if (!repeat_x && ((hpos < 2 && !first) ||
884 (hpos > 98 && !last))){
885 plot_content = false;
886 }
887 } else {
888 x += (int) (FIXTOFLT(css_unit_len2device_px(
889 box->style, unit_len_ctx,
890 hpos, hunit)) * scale);
891 }
892
893 if (vunit == CSS_UNIT_PCT) {
894 y += (b.y1 - b.y0 -
896 scale) * FIXTOFLT(vpos) / 100.;
897 } else {
898 y += (int) (FIXTOFLT(css_unit_len2device_px(
899 box->style, unit_len_ctx,
900 vpos, vunit)) * scale);
901 }
902 }
903
904 /* plot the background colour */
905 css_computed_background_color(box->style, &bgcol);
906
907 if (nscss_color_is_transparent(bgcol) == false) {
908 *background_colour = nscss_color_to_ns(bgcol);
909 pstyle_fill_bg.fill_colour = *background_colour;
910
911 if (plot_colour) {
912 res = ctx->plot->rectangle(ctx, &pstyle_fill_bg, &r);
913 if (res != NSERROR_OK) {
914 return false;
915 }
916 }
917 }
918 /* and plot the image */
919 if (plot_content) {
922
923 if (!repeat_x) {
924 if (r.x0 < x)
925 r.x0 = x;
926 if (r.x1 > x + width * scale)
927 r.x1 = x + width * scale;
928 }
929 if (!repeat_y) {
930 if (r.y0 < y)
931 r.y0 = y;
932 if (r.y1 > y + height * scale)
933 r.y1 = y + height * scale;
934 }
935 /* valid clipping rectangles only */
936 if ((r.x0 < r.x1) && (r.y0 < r.y1)) {
937 struct content_redraw_data bg_data;
938
939 res = ctx->plot->clip(ctx, &r);
940 if (res != NSERROR_OK) {
941 return false;
942 }
943
944 bg_data.x = x;
945 bg_data.y = y;
946 bg_data.width = ceilf(width * scale);
947 bg_data.height = ceilf(height * scale);
949 bg_data.scale = scale;
950 bg_data.repeat_x = repeat_x;
951 bg_data.repeat_y = repeat_y;
952
953 /* We just continue if redraw fails */
954 content_redraw(box->background, &bg_data, &r, ctx);
955 }
956 }
957
958 return true;
959}
960
961
962/**
963 * Plot text decoration for an inline box.
964 *
965 * \param box box to plot decorations for, of type BOX_INLINE
966 * \param x x coordinate of parent of box
967 * \param y y coordinate of parent of box
968 * \param scale scale for redraw
969 * \param colour colour for decorations
970 * \param ratio position of line as a ratio of line height
971 * \param ctx current redraw context
972 * \return true if successful, false otherwise
973 */
974
975static bool
977 int x, int y,
978 float scale,
980 float ratio,
981 const struct redraw_context *ctx)
982{
983 struct box *c;
984 plot_style_t plot_style_box = {
986 .stroke_colour = colour,
987 };
988 nserror res;
989 struct rect rect;
990
991 for (c = box->next;
992 c && c != box->inline_end;
993 c = c->next) {
994 if (c->type != BOX_TEXT) {
995 continue;
996 }
997 rect.x0 = (x + c->x) * scale;
998 rect.y0 = (y + c->y + c->height * ratio) * scale;
999 rect.x1 = (x + c->x + c->width) * scale;
1000 rect.y1 = (y + c->y + c->height * ratio) * scale;
1001 res = ctx->plot->line(ctx, &plot_style_box, &rect);
1002 if (res != NSERROR_OK) {
1003 return false;
1004 }
1005 }
1006 return true;
1007}
1008
1009
1010/**
1011 * Plot text decoration for an non-inline box.
1012 *
1013 * \param box box to plot decorations for, of type other than BOX_INLINE
1014 * \param x x coordinate of box
1015 * \param y y coordinate of box
1016 * \param scale scale for redraw
1017 * \param colour colour for decorations
1018 * \param ratio position of line as a ratio of line height
1019 * \param ctx current redraw context
1020 * \return true if successful, false otherwise
1021 */
1022
1023static bool
1025 int x, int y,
1026 float scale,
1027 colour colour,
1028 float ratio,
1029 const struct redraw_context *ctx)
1030{
1031 struct box *c;
1032 plot_style_t plot_style_box = {
1034 .stroke_colour = colour,
1035 };
1036 nserror res;
1037 struct rect rect;
1038
1039 /* draw through text descendants */
1040 for (c = box->children; c; c = c->next) {
1041 if (c->type == BOX_TEXT) {
1042 rect.x0 = (x + c->x) * scale;
1043 rect.y0 = (y + c->y + c->height * ratio) * scale;
1044 rect.x1 = (x + c->x + c->width) * scale;
1045 rect.y1 = (y + c->y + c->height * ratio) * scale;
1046 res = ctx->plot->line(ctx, &plot_style_box, &rect);
1047 if (res != NSERROR_OK) {
1048 return false;
1049 }
1050 } else if ((c->type == BOX_INLINE_CONTAINER) || (c->type == BOX_BLOCK)) {
1052 x + c->x, y + c->y,
1053 scale, colour, ratio, ctx))
1054 return false;
1055 }
1056 }
1057 return true;
1058}
1059
1060
1061/**
1062 * Plot text decoration for a box.
1063 *
1064 * \param box box to plot decorations for
1065 * \param x_parent x coordinate of parent of box
1066 * \param y_parent y coordinate of parent of box
1067 * \param scale scale for redraw
1068 * \param background_colour current background colour
1069 * \param ctx current redraw context
1070 * \return true if successful, false otherwise
1071 */
1072
1074 int x_parent, int y_parent, float scale,
1075 colour background_colour, const struct redraw_context *ctx)
1076{
1077 static const enum css_text_decoration_e decoration[] = {
1078 CSS_TEXT_DECORATION_UNDERLINE, CSS_TEXT_DECORATION_OVERLINE,
1079 CSS_TEXT_DECORATION_LINE_THROUGH };
1080 static const float line_ratio[] = { 0.9, 0.1, 0.5 };
1081 colour fgcol;
1082 unsigned int i;
1083 css_color col;
1084
1085 css_computed_color(box->style, &col);
1086 fgcol = nscss_color_to_ns(col);
1087
1088 /* antialias colour for under/overline */
1089 if (html_redraw_printing == false)
1090 fgcol = blend_colour(background_colour, fgcol);
1091
1092 if (box->type == BOX_INLINE) {
1093 if (!box->inline_end)
1094 return true;
1095 for (i = 0; i != NOF_ELEMENTS(decoration); i++)
1096 if (css_computed_text_decoration(box->style) &
1097 decoration[i])
1099 x_parent, y_parent, scale,
1100 fgcol, line_ratio[i], ctx))
1101 return false;
1102 } else {
1103 for (i = 0; i != NOF_ELEMENTS(decoration); i++)
1104 if (css_computed_text_decoration(box->style) &
1105 decoration[i])
1107 x_parent + box->x,
1108 y_parent + box->y,
1109 scale,
1110 fgcol, line_ratio[i], ctx))
1111 return false;
1112 }
1113
1114 return true;
1115}
1116
1117
1118/**
1119 * Redraw the text content of a box, possibly partially highlighted
1120 * because the text has been selected, or matches a search operation.
1121 *
1122 * \param html The html content to redraw text within.
1123 * \param box box with text content
1124 * \param x x co-ord of box
1125 * \param y y co-ord of box
1126 * \param clip current clip rectangle
1127 * \param scale current scale setting (1.0 = 100%)
1128 * \param current_background_color
1129 * \param ctx current redraw context
1130 * \return true iff successful and redraw should proceed
1131 */
1132
1133static bool html_redraw_text_box(const html_content *html, struct box *box,
1134 int x, int y, const struct rect *clip, float scale,
1135 colour current_background_color,
1136 const struct redraw_context *ctx)
1137{
1138 bool excluded = (box->object != NULL);
1139 plot_font_style_t fstyle;
1140
1142 fstyle.background = current_background_color;
1143
1144 if (!text_redraw(box->text,
1145 box->length,
1147 box->space,
1148 &fstyle,
1149 x, y,
1150 clip,
1151 box->height,
1152 scale,
1153 excluded,
1154 (struct content *)html,
1155 html->sel,
1156 ctx))
1157 return false;
1158
1159 return true;
1160}
1161
1162bool html_redraw_box(const html_content *html, struct box *box,
1163 int x_parent, int y_parent,
1164 const struct rect *clip, float scale,
1165 colour current_background_color,
1166 const struct redraw_context *ctx);
1167
1168/**
1169 * Draw the various children of a box.
1170 *
1171 * \param html html content
1172 * \param box box to draw children of
1173 * \param x_parent coordinate of parent box
1174 * \param y_parent coordinate of parent box
1175 * \param clip clip rectangle
1176 * \param scale scale for redraw
1177 * \param current_background_color background colour under this box
1178 * \param ctx current redraw context
1179 * \return true if successful, false otherwise
1180 */
1181
1182static bool html_redraw_box_children(const html_content *html, struct box *box,
1183 int x_parent, int y_parent,
1184 const struct rect *clip, float scale,
1185 colour current_background_color,
1186 const struct redraw_context *ctx)
1187{
1188 struct box *c;
1189
1190 for (c = box->children; c; c = c->next) {
1191
1192 if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT)
1193 if (!html_redraw_box(html, c,
1194 x_parent + box->x -
1196 y_parent + box->y -
1198 clip, scale, current_background_color,
1199 ctx))
1200 return false;
1201 }
1202 for (c = box->float_children; c; c = c->next_float)
1203 if (!html_redraw_box(html, c,
1204 x_parent + box->x -
1206 y_parent + box->y -
1208 clip, scale, current_background_color,
1209 ctx))
1210 return false;
1211
1212 return true;
1213}
1214
1215/**
1216 * Recursively draw a box.
1217 *
1218 * \param html html content
1219 * \param box box to draw
1220 * \param x_parent coordinate of parent box
1221 * \param y_parent coordinate of parent box
1222 * \param clip clip rectangle
1223 * \param scale scale for redraw
1224 * \param current_background_color background colour under this box
1225 * \param ctx current redraw context
1226 * \return true if successful, false otherwise
1227 *
1228 * x, y, clip_[xy][01] are in target coordinates.
1229 */
1230
1231bool html_redraw_box(const html_content *html, struct box *box,
1232 int x_parent, int y_parent,
1233 const struct rect *clip, const float scale,
1234 colour current_background_color,
1235 const struct redraw_context *ctx)
1236{
1237 const struct plotter_table *plot = ctx->plot;
1238 int x, y;
1239 int width, height;
1240 int padding_left, padding_top, padding_width, padding_height;
1241 int border_left, border_top, border_right, border_bottom;
1242 struct rect r;
1243 struct rect rect;
1244 int x_scrolled, y_scrolled;
1245 struct box *bg_box = NULL;
1246 css_computed_clip_rect css_rect;
1247 enum css_overflow_e overflow_x = CSS_OVERFLOW_VISIBLE;
1248 enum css_overflow_e overflow_y = CSS_OVERFLOW_VISIBLE;
1249 dom_exception exc;
1250 dom_html_element_type tag_type;
1251
1252
1254 return true;
1255
1256 if (box->style != NULL) {
1257 overflow_x = css_computed_overflow_x(box->style);
1258 overflow_y = css_computed_overflow_y(box->style);
1259 }
1260
1261 /* avoid trivial FP maths */
1262 if (scale == 1.0) {
1263 x = x_parent + box->x;
1264 y = y_parent + box->y;
1265 width = box->width;
1266 height = box->height;
1267 padding_left = box->padding[LEFT];
1268 padding_top = box->padding[TOP];
1269 padding_width = padding_left + box->width + box->padding[RIGHT];
1270 padding_height = padding_top + box->height +
1271 box->padding[BOTTOM];
1272 border_left = box->border[LEFT].width;
1273 border_top = box->border[TOP].width;
1274 border_right = box->border[RIGHT].width;
1275 border_bottom = box->border[BOTTOM].width;
1276 } else {
1277 x = (x_parent + box->x) * scale;
1278 y = (y_parent + box->y) * scale;
1279 width = box->width * scale;
1280 height = box->height * scale;
1281 /* left and top padding values are normally zero,
1282 * so avoid trivial FP maths */
1283 padding_left = box->padding[LEFT] ? box->padding[LEFT] * scale
1284 : 0;
1285 padding_top = box->padding[TOP] ? box->padding[TOP] * scale
1286 : 0;
1287 padding_width = (box->padding[LEFT] + box->width +
1288 box->padding[RIGHT]) * scale;
1289 padding_height = (box->padding[TOP] + box->height +
1290 box->padding[BOTTOM]) * scale;
1291 border_left = box->border[LEFT].width * scale;
1292 border_top = box->border[TOP].width * scale;
1293 border_right = box->border[RIGHT].width * scale;
1294 border_bottom = box->border[BOTTOM].width * scale;
1295 }
1296
1297 /* calculate rectangle covering this box and descendants */
1298 if (box->style && overflow_x != CSS_OVERFLOW_VISIBLE &&
1299 box->parent != NULL) {
1300 /* box contents clipped to box size */
1301 r.x0 = x - border_left;
1302 r.x1 = x + padding_width + border_right;
1303 } else {
1304 /* box contents can hang out of the box; use descendant box */
1305 if (scale == 1.0) {
1306 r.x0 = x + box->descendant_x0;
1307 r.x1 = x + box->descendant_x1 + 1;
1308 } else {
1309 r.x0 = x + box->descendant_x0 * scale;
1310 r.x1 = x + box->descendant_x1 * scale + 1;
1311 }
1312 if (!box->parent) {
1313 /* root element */
1314 int margin_left, margin_right;
1315 if (scale == 1.0) {
1316 margin_left = box->margin[LEFT];
1317 margin_right = box->margin[RIGHT];
1318 } else {
1319 margin_left = box->margin[LEFT] * scale;
1320 margin_right = box->margin[RIGHT] * scale;
1321 }
1322 r.x0 = x - border_left - margin_left < r.x0 ?
1323 x - border_left - margin_left : r.x0;
1324 r.x1 = x + padding_width + border_right +
1325 margin_right > r.x1 ?
1326 x + padding_width + border_right +
1327 margin_right : r.x1;
1328 }
1329 }
1330
1331 /* calculate rectangle covering this box and descendants */
1332 if (box->style && overflow_y != CSS_OVERFLOW_VISIBLE &&
1333 box->parent != NULL) {
1334 /* box contents clipped to box size */
1335 r.y0 = y - border_top;
1336 r.y1 = y + padding_height + border_bottom;
1337 } else {
1338 /* box contents can hang out of the box; use descendant box */
1339 if (scale == 1.0) {
1340 r.y0 = y + box->descendant_y0;
1341 r.y1 = y + box->descendant_y1 + 1;
1342 } else {
1343 r.y0 = y + box->descendant_y0 * scale;
1344 r.y1 = y + box->descendant_y1 * scale + 1;
1345 }
1346 if (!box->parent) {
1347 /* root element */
1348 int margin_top, margin_bottom;
1349 if (scale == 1.0) {
1350 margin_top = box->margin[TOP];
1351 margin_bottom = box->margin[BOTTOM];
1352 } else {
1353 margin_top = box->margin[TOP] * scale;
1354 margin_bottom = box->margin[BOTTOM] * scale;
1355 }
1356 r.y0 = y - border_top - margin_top < r.y0 ?
1357 y - border_top - margin_top : r.y0;
1358 r.y1 = y + padding_height + border_bottom +
1359 margin_bottom > r.y1 ?
1360 y + padding_height + border_bottom +
1361 margin_bottom : r.y1;
1362 }
1363 }
1364
1365 /* return if the rectangle is completely outside the clip rectangle */
1366 if (clip->y1 < r.y0 || r.y1 < clip->y0 ||
1367 clip->x1 < r.x0 || r.x1 < clip->x0)
1368 return true;
1369
1370 /*if the rectangle is under the page bottom but it can fit in a page,
1371 don't print it now*/
1374 if (r.y1 - r.y0 <= html_redraw_printing_border &&
1375 (box->type == BOX_TEXT ||
1377 || box->object || box->gadget)) {
1378 /*remember the highest of all points from the
1379 not printed elements*/
1382 return true;
1383 }
1384 }
1385 else box->flags |= PRINTED; /*it won't be printed anymore*/
1386 }
1387
1388 /* if visibility is hidden render children only */
1389 if (box->style && css_computed_visibility(box->style) ==
1390 CSS_VISIBILITY_HIDDEN) {
1391 if ((ctx->plot->group_start) &&
1392 (ctx->plot->group_start(ctx, "hidden box") != NSERROR_OK))
1393 return false;
1394 if (!html_redraw_box_children(html, box, x_parent, y_parent,
1395 &r, scale, current_background_color, ctx))
1396 return false;
1397 return ((!ctx->plot->group_end) || (ctx->plot->group_end(ctx) == NSERROR_OK));
1398 }
1399
1400 if ((ctx->plot->group_start) &&
1401 (ctx->plot->group_start(ctx,"vis box") != NSERROR_OK)) {
1402 return false;
1403 }
1404
1405 if (box->style != NULL &&
1406 css_computed_position(box->style) ==
1407 CSS_POSITION_ABSOLUTE &&
1408 css_computed_clip(box->style, &css_rect) ==
1409 CSS_CLIP_RECT) {
1410 /* We have an absolutly positioned box with a clip rect */
1411 if (css_rect.left_auto == false)
1412 r.x0 = x - border_left + FIXTOINT(css_unit_len2device_px(
1413 box->style, &html->unit_len_ctx,
1414 css_rect.left, css_rect.lunit));
1415
1416 if (css_rect.top_auto == false)
1417 r.y0 = y - border_top + FIXTOINT(css_unit_len2device_px(
1418 box->style, &html->unit_len_ctx,
1419 css_rect.top, css_rect.tunit));
1420
1421 if (css_rect.right_auto == false)
1422 r.x1 = x - border_left + FIXTOINT(css_unit_len2device_px(
1423 box->style, &html->unit_len_ctx,
1424 css_rect.right, css_rect.runit));
1425
1426 if (css_rect.bottom_auto == false)
1427 r.y1 = y - border_top + FIXTOINT(css_unit_len2device_px(
1428 box->style, &html->unit_len_ctx,
1429 css_rect.bottom, css_rect.bunit));
1430
1431 /* find intersection of clip rectangle and box */
1432 if (r.x0 < clip->x0) r.x0 = clip->x0;
1433 if (r.y0 < clip->y0) r.y0 = clip->y0;
1434 if (clip->x1 < r.x1) r.x1 = clip->x1;
1435 if (clip->y1 < r.y1) r.y1 = clip->y1;
1436 /* Nothing to do for invalid rectangles */
1437 if (r.x0 >= r.x1 || r.y0 >= r.y1)
1438 /* not an error */
1439 return ((!ctx->plot->group_end) ||
1440 (ctx->plot->group_end(ctx) == NSERROR_OK));
1441 /* clip to it */
1442 if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
1443 return false;
1444
1445 } else if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
1446 box->type == BOX_TABLE_CELL || box->object) {
1447 /* find intersection of clip rectangle and box */
1448 if (r.x0 < clip->x0) r.x0 = clip->x0;
1449 if (r.y0 < clip->y0) r.y0 = clip->y0;
1450 if (clip->x1 < r.x1) r.x1 = clip->x1;
1451 if (clip->y1 < r.y1) r.y1 = clip->y1;
1452 /* no point trying to draw 0-width/height boxes */
1453 if (r.x0 == r.x1 || r.y0 == r.y1)
1454 /* not an error */
1455 return ((!ctx->plot->group_end) ||
1456 (ctx->plot->group_end(ctx) == NSERROR_OK));
1457 /* clip to it */
1458 if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
1459 return false;
1460 } else {
1461 /* clip box is fine, clip to it */
1462 r = *clip;
1463 if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
1464 return false;
1465 }
1466
1467 /* background colour and image for block level content and replaced
1468 * inlines */
1469
1470 bg_box = html_redraw_find_bg_box(box);
1471
1472 /* bg_box == NULL implies that this box should not have
1473 * its background rendered. Otherwise filter out linebreaks,
1474 * optimize away non-differing inlines, only plot background
1475 * for BOX_TEXT it's in an inline */
1476 if (bg_box && bg_box->type != BOX_BR &&
1477 bg_box->type != BOX_TEXT &&
1478 bg_box->type != BOX_INLINE_END &&
1479 (bg_box->type != BOX_INLINE || bg_box->object ||
1480 bg_box->flags & IFRAME || box->flags & REPLACE_DIM ||
1481 (bg_box->gadget != NULL &&
1482 (bg_box->gadget->type == GADGET_TEXTAREA ||
1483 bg_box->gadget->type == GADGET_TEXTBOX ||
1484 bg_box->gadget->type == GADGET_PASSWORD)))) {
1485 /* find intersection of clip box and border edge */
1486 struct rect p;
1487 p.x0 = x - border_left < r.x0 ? r.x0 : x - border_left;
1488 p.y0 = y - border_top < r.y0 ? r.y0 : y - border_top;
1489 p.x1 = x + padding_width + border_right < r.x1 ?
1490 x + padding_width + border_right : r.x1;
1491 p.y1 = y + padding_height + border_bottom < r.y1 ?
1492 y + padding_height + border_bottom : r.y1;
1493 if (!box->parent) {
1494 /* Root element, special case:
1495 * background covers margins too */
1496 int m_left, m_top, m_right, m_bottom;
1497 if (scale == 1.0) {
1498 m_left = box->margin[LEFT];
1499 m_top = box->margin[TOP];
1500 m_right = box->margin[RIGHT];
1501 m_bottom = box->margin[BOTTOM];
1502 } else {
1503 m_left = box->margin[LEFT] * scale;
1504 m_top = box->margin[TOP] * scale;
1505 m_right = box->margin[RIGHT] * scale;
1506 m_bottom = box->margin[BOTTOM] * scale;
1507 }
1508 p.x0 = p.x0 - m_left < r.x0 ? r.x0 : p.x0 - m_left;
1509 p.y0 = p.y0 - m_top < r.y0 ? r.y0 : p.y0 - m_top;
1510 p.x1 = p.x1 + m_right < r.x1 ? p.x1 + m_right : r.x1;
1511 p.y1 = p.y1 + m_bottom < r.y1 ? p.y1 + m_bottom : r.y1;
1512 }
1513 /* valid clipping rectangles only */
1514 if ((p.x0 < p.x1) && (p.y0 < p.y1)) {
1515 /* plot background */
1516 if (!html_redraw_background(x, y, box, scale, &p,
1517 &current_background_color, bg_box,
1518 &html->unit_len_ctx, ctx))
1519 return false;
1520 /* restore previous graphics window */
1521 if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
1522 return false;
1523 }
1524 }
1525
1526 /* borders for block level content and replaced inlines */
1527 if (box->style &&
1528 box->type != BOX_TEXT &&
1529 box->type != BOX_INLINE_END &&
1530 (box->type != BOX_INLINE || box->object ||
1531 box->flags & IFRAME || box->flags & REPLACE_DIM ||
1532 (box->gadget != NULL &&
1535 box->gadget->type == GADGET_PASSWORD))) &&
1536 (border_top || border_right || border_bottom || border_left)) {
1537 if (!html_redraw_borders(box, x_parent, y_parent,
1538 padding_width, padding_height, &r,
1539 scale, ctx))
1540 return false;
1541 }
1542
1543 /* backgrounds and borders for non-replaced inlines */
1544 if (box->style && box->type == BOX_INLINE && box->inline_end &&
1546 border_top || border_right ||
1547 border_bottom || border_left)) {
1548 /* inline backgrounds and borders span other boxes and may
1549 * wrap onto separate lines */
1550 struct box *ib;
1551 struct rect b; /* border edge rectangle */
1552 struct rect p; /* clipped rect */
1553 bool first = true;
1554 int ib_x;
1555 int ib_y = y;
1556 int ib_p_width;
1557 int ib_b_left, ib_b_right;
1558
1559 b.x0 = x - border_left;
1560 b.x1 = x + padding_width + border_right;
1561 b.y0 = y - border_top;
1562 b.y1 = y + padding_height + border_bottom;
1563
1564 p.x0 = b.x0 < r.x0 ? r.x0 : b.x0;
1565 p.x1 = b.x1 < r.x1 ? b.x1 : r.x1;
1566 p.y0 = b.y0 < r.y0 ? r.y0 : b.y0;
1567 p.y1 = b.y1 < r.y1 ? b.y1 : r.y1;
1568 for (ib = box; ib; ib = ib->next) {
1569 /* to get extents of rectangle(s) associated with
1570 * inline, cycle though all boxes in inline, skipping
1571 * over floats */
1572 if (ib->type == BOX_FLOAT_LEFT ||
1573 ib->type == BOX_FLOAT_RIGHT)
1574 continue;
1575 if (scale == 1.0) {
1576 ib_x = x_parent + ib->x;
1577 ib_y = y_parent + ib->y;
1578 ib_p_width = ib->padding[LEFT] + ib->width +
1579 ib->padding[RIGHT];
1580 ib_b_left = ib->border[LEFT].width;
1581 ib_b_right = ib->border[RIGHT].width;
1582 } else {
1583 ib_x = (x_parent + ib->x) * scale;
1584 ib_y = (y_parent + ib->y) * scale;
1585 ib_p_width = (ib->padding[LEFT] + ib->width +
1586 ib->padding[RIGHT]) * scale;
1587 ib_b_left = ib->border[LEFT].width * scale;
1588 ib_b_right = ib->border[RIGHT].width * scale;
1589 }
1590
1591 if ((ib->flags & NEW_LINE) && ib != box) {
1592 /* inline element has wrapped, plot background
1593 * and borders */
1595 x, y, box, scale, &p, b,
1596 first, false,
1597 &current_background_color,
1598 &html->unit_len_ctx, ctx))
1599 return false;
1600 /* restore previous graphics window */
1601 if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
1602 return false;
1603 if (!html_redraw_inline_borders(box, b, &r,
1604 scale, first, false, ctx))
1605 return false;
1606 /* reset coords */
1607 b.x0 = ib_x - ib_b_left;
1608 b.y0 = ib_y - border_top - padding_top;
1609 b.y1 = ib_y + padding_height - padding_top +
1610 border_bottom;
1611
1612 p.x0 = b.x0 < r.x0 ? r.x0 : b.x0;
1613 p.y0 = b.y0 < r.y0 ? r.y0 : b.y0;
1614 p.y1 = b.y1 < r.y1 ? b.y1 : r.y1;
1615
1616 first = false;
1617 }
1618
1619 /* increase width for current box */
1620 b.x1 = ib_x + ib_p_width + ib_b_right;
1621 p.x1 = b.x1 < r.x1 ? b.x1 : r.x1;
1622
1623 if (ib == box->inline_end)
1624 /* reached end of BOX_INLINE span */
1625 break;
1626 }
1627 /* plot background and borders for last rectangle of
1628 * the inline */
1629 if (!html_redraw_inline_background(x, ib_y, box, scale, &p, b,
1630 first, true, &current_background_color,
1631 &html->unit_len_ctx, ctx))
1632 return false;
1633 /* restore previous graphics window */
1634 if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
1635 return false;
1636 if (!html_redraw_inline_borders(box, b, &r, scale, first, true,
1637 ctx))
1638 return false;
1639
1640 }
1641
1642 /* Debug outlines */
1643 if (html_redraw_debug) {
1644 int margin_left, margin_right;
1645 int margin_top, margin_bottom;
1646 if (scale == 1.0) {
1647 /* avoid trivial fp maths */
1648 margin_left = box->margin[LEFT];
1649 margin_top = box->margin[TOP];
1650 margin_right = box->margin[RIGHT];
1651 margin_bottom = box->margin[BOTTOM];
1652 } else {
1653 margin_left = box->margin[LEFT] * scale;
1654 margin_top = box->margin[TOP] * scale;
1655 margin_right = box->margin[RIGHT] * scale;
1656 margin_bottom = box->margin[BOTTOM] * scale;
1657 }
1658 /* Content edge -- blue */
1659 rect.x0 = x + padding_left;
1660 rect.y0 = y + padding_top;
1661 rect.x1 = x + padding_left + width;
1662 rect.y1 = y + padding_top + height;
1664 return false;
1665
1666 /* Padding edge -- red */
1667 rect.x0 = x;
1668 rect.y0 = y;
1669 rect.x1 = x + padding_width;
1670 rect.y1 = y + padding_height;
1672 return false;
1673
1674 /* Margin edge -- yellow */
1675 rect.x0 = x - border_left - margin_left;
1676 rect.y0 = y - border_top - margin_top;
1677 rect.x1 = x + padding_width + border_right + margin_right;
1678 rect.y1 = y + padding_height + border_bottom + margin_bottom;
1680 return false;
1681 }
1682
1683 /* clip to the padding edge for objects, or boxes with overflow hidden
1684 * or scroll, unless it's the root element */
1685 if (box->parent != NULL) {
1686 bool need_clip = false;
1687 if (box->object || box->flags & IFRAME ||
1688 (overflow_x != CSS_OVERFLOW_VISIBLE &&
1689 overflow_y != CSS_OVERFLOW_VISIBLE)) {
1690 r.x0 = x;
1691 r.y0 = y;
1692 r.x1 = x + padding_width;
1693 r.y1 = y + padding_height;
1694 if (r.x0 < clip->x0) r.x0 = clip->x0;
1695 if (r.y0 < clip->y0) r.y0 = clip->y0;
1696 if (clip->x1 < r.x1) r.x1 = clip->x1;
1697 if (clip->y1 < r.y1) r.y1 = clip->y1;
1698 if (r.x1 <= r.x0 || r.y1 <= r.y0) {
1699 return (!ctx->plot->group_end ||
1700 (ctx->plot->group_end(ctx) == NSERROR_OK));
1701 }
1702 need_clip = true;
1703
1704 } else if (overflow_x != CSS_OVERFLOW_VISIBLE) {
1705 r.x0 = x;
1706 r.y0 = clip->y0;
1707 r.x1 = x + padding_width;
1708 r.y1 = clip->y1;
1709 if (r.x0 < clip->x0) r.x0 = clip->x0;
1710 if (clip->x1 < r.x1) r.x1 = clip->x1;
1711 if (r.x1 <= r.x0) {
1712 return (!ctx->plot->group_end ||
1713 (ctx->plot->group_end(ctx) == NSERROR_OK));
1714 }
1715 need_clip = true;
1716
1717 } else if (overflow_y != CSS_OVERFLOW_VISIBLE) {
1718 r.x0 = clip->x0;
1719 r.y0 = y;
1720 r.x1 = clip->x1;
1721 r.y1 = y + padding_height;
1722 if (r.y0 < clip->y0) r.y0 = clip->y0;
1723 if (clip->y1 < r.y1) r.y1 = clip->y1;
1724 if (r.y1 <= r.y0) {
1725 return (!ctx->plot->group_end ||
1726 (ctx->plot->group_end(ctx) == NSERROR_OK));
1727 }
1728 need_clip = true;
1729 }
1730
1731 if (need_clip &&
1732 (box->type == BOX_BLOCK ||
1734 box->type == BOX_TABLE_CELL || box->object)) {
1735 if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
1736 return false;
1737 }
1738 }
1739
1740 /* text decoration */
1741 if ((box->type != BOX_TEXT) &&
1742 box->style &&
1743 css_computed_text_decoration(box->style) != CSS_TEXT_DECORATION_NONE) {
1744 if (!html_redraw_text_decoration(box, x_parent, y_parent,
1745 scale, current_background_color, ctx))
1746 return false;
1747 }
1748
1749 if (box->node != NULL) {
1750 exc = dom_html_element_get_tag_type(box->node, &tag_type);
1751 if (exc != DOM_NO_ERR) {
1752 tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
1753 }
1754 } else {
1755 tag_type = DOM_HTML_ELEMENT_TYPE__UNKNOWN;
1756 }
1757
1758 if (box->object && width != 0 && height != 0) {
1759 struct content_redraw_data obj_data;
1760
1761 x_scrolled = x - scrollbar_get_offset(box->scroll_x) * scale;
1762 y_scrolled = y - scrollbar_get_offset(box->scroll_y) * scale;
1763
1764 obj_data.x = x_scrolled + padding_left;
1765 obj_data.y = y_scrolled + padding_top;
1766 obj_data.width = width;
1767 obj_data.height = height;
1768 obj_data.background_colour = current_background_color;
1769 obj_data.scale = scale;
1770 obj_data.repeat_x = false;
1771 obj_data.repeat_y = false;
1772
1774 obj_data.x /= scale;
1775 obj_data.y /= scale;
1776 }
1777
1778 if (!content_redraw(box->object, &obj_data, &r, ctx)) {
1779 /* Show image fail */
1780 /* Unicode (U+FFFC) 'OBJECT REPLACEMENT CHARACTER' */
1781 const char *obj = "\xef\xbf\xbc";
1782 int obj_width;
1783 int obj_x = x + padding_left;
1784 nserror res;
1785
1786 rect.x0 = x + padding_left;
1787 rect.y0 = y + padding_top;
1788 rect.x1 = x + padding_left + width - 1;
1789 rect.y1 = y + padding_top + height - 1;
1790 res = ctx->plot->rectangle(ctx, plot_style_broken_object, &rect);
1791 if (res != NSERROR_OK) {
1792 return false;
1793 }
1794
1796 obj,
1797 sizeof(obj) - 1,
1798 &obj_width);
1799 if (res != NSERROR_OK) {
1800 obj_x += 1;
1801 } else {
1802 obj_x += width / 2 - obj_width / 2;
1803 }
1804
1805 if (ctx->plot->text(ctx,
1807 obj_x, y + padding_top + (int)(height * 0.75),
1808 obj, sizeof(obj) - 1) != NSERROR_OK)
1809 return false;
1810 }
1811 } else if (tag_type == DOM_HTML_ELEMENT_TYPE_CANVAS &&
1812 box->node != NULL &&
1813 box->flags & REPLACE_DIM) {
1814 /* Canvas to draw */
1815 struct bitmap *bitmap = NULL;
1816 exc = dom_node_get_user_data(box->node,
1817 corestring_dom___ns_key_canvas_node_data,
1818 &bitmap);
1819 if (exc != DOM_NO_ERR) {
1820 bitmap = NULL;
1821 }
1822 if (bitmap != NULL &&
1823 ctx->plot->bitmap(ctx, bitmap, x + padding_left, y + padding_top,
1824 width, height, current_background_color,
1826 return false;
1827 } else if (box->iframe) {
1828 /* Offset is passed to browser window redraw unscaled */
1830 x + padding_left,
1831 y + padding_top, &r, ctx);
1832
1833 } else if (box->gadget && box->gadget->type == GADGET_CHECKBOX) {
1834 if (!html_redraw_checkbox(x + padding_left, y + padding_top,
1835 width, height, box->gadget->selected, ctx))
1836 return false;
1837
1838 } else if (box->gadget && box->gadget->type == GADGET_RADIO) {
1839 if (!html_redraw_radio(x + padding_left, y + padding_top,
1840 width, height, box->gadget->selected, ctx))
1841 return false;
1842
1843 } else if (box->gadget && box->gadget->type == GADGET_FILE) {
1844 if (!html_redraw_file(x + padding_left, y + padding_top,
1845 width, height, box, scale,
1846 current_background_color, &html->unit_len_ctx, ctx))
1847 return false;
1848
1849 } else if (box->gadget &&
1852 box->gadget->type == GADGET_TEXTBOX)) {
1853 textarea_redraw(box->gadget->data.text.ta, x, y,
1854 current_background_color, scale, &r, ctx);
1855
1856 } else if (box->text) {
1857 if (!html_redraw_text_box(html, box, x, y, &r, scale,
1858 current_background_color, ctx))
1859 return false;
1860
1861 } else {
1862 if (!html_redraw_box_children(html, box, x_parent, y_parent, &r,
1863 scale, current_background_color, ctx))
1864 return false;
1865 }
1866
1867 if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
1869 if (ctx->plot->clip(ctx, clip) != NSERROR_OK)
1870 return false;
1871
1872 /* list marker */
1873 if (box->list_marker) {
1874 if (!html_redraw_box(html, box->list_marker,
1875 x_parent + box->x -
1877 y_parent + box->y -
1879 clip, scale, current_background_color, ctx))
1880 return false;
1881 }
1882
1883 /* scrollbars */
1884 if (((box->style && box->type != BOX_BR &&
1885 box->type != BOX_TABLE && box->type != BOX_INLINE &&
1886 (box->gadget == NULL || box->gadget->type != GADGET_TEXTAREA) &&
1887 (overflow_x == CSS_OVERFLOW_SCROLL ||
1888 overflow_x == CSS_OVERFLOW_AUTO ||
1889 overflow_y == CSS_OVERFLOW_SCROLL ||
1890 overflow_y == CSS_OVERFLOW_AUTO)) ||
1892 CONTENT_HTML)) && box->parent != NULL) {
1893 nserror res;
1894 bool has_x_scroll = (overflow_x == CSS_OVERFLOW_SCROLL);
1895 bool has_y_scroll = (overflow_y == CSS_OVERFLOW_SCROLL);
1896
1897 has_x_scroll |= (overflow_x == CSS_OVERFLOW_AUTO) &&
1899 has_y_scroll |= (overflow_y == CSS_OVERFLOW_AUTO) &&
1901
1902 res = box_handle_scrollbars((struct content *)html,
1903 box, has_x_scroll, has_y_scroll);
1904 if (res != NSERROR_OK) {
1905 NSLOG(netsurf, INFO, "%s", messages_get_errorcode(res));
1906 return false;
1907 }
1908
1909 if (box->scroll_x != NULL)
1911 x_parent + box->x,
1912 y_parent + box->y + box->padding[TOP] +
1913 box->height + box->padding[BOTTOM] -
1914 SCROLLBAR_WIDTH, clip, scale, ctx);
1915 if (box->scroll_y != NULL)
1917 x_parent + box->x + box->padding[LEFT] +
1918 box->width + box->padding[RIGHT] -
1920 y_parent + box->y, clip, scale, ctx);
1921 }
1922
1923 if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
1925 if (ctx->plot->clip(ctx, clip) != NSERROR_OK)
1926 return false;
1927 }
1928
1929 return ((!plot->group_end) || (ctx->plot->group_end(ctx) == NSERROR_OK));
1930}
1931
1932/**
1933 * Draw a CONTENT_HTML using the current set of plotters (plot).
1934 *
1935 * \param c content of type CONTENT_HTML
1936 * \param data redraw data for this content redraw
1937 * \param clip current clip region
1938 * \param ctx current redraw context
1939 * \return true if successful, false otherwise
1940 *
1941 * x, y, clip_[xy][01] are in target coordinates.
1942 */
1943
1944bool html_redraw(struct content *c, struct content_redraw_data *data,
1945 const struct rect *clip, const struct redraw_context *ctx)
1946{
1947 html_content *html = (html_content *) c;
1948 struct box *box;
1949 bool result = true;
1950 bool select, select_only;
1951 plot_style_t pstyle_fill_bg = {
1953 .fill_colour = data->background_colour,
1954 };
1955
1956 box = html->layout;
1957 assert(box);
1958
1959 /* The select menu needs special treating because, when opened, it
1960 * reaches beyond its layout box.
1961 */
1962 select = false;
1963 select_only = false;
1964 if (ctx->interactive && html->visible_select_menu != NULL) {
1965 struct form_control *control = html->visible_select_menu;
1966 select = true;
1967 /* check if the redraw rectangle is completely inside of the
1968 select menu */
1969 select_only = form_clip_inside_select_menu(control,
1970 data->scale, clip);
1971 }
1972
1973 if (!select_only) {
1974 /* clear to background colour */
1975 result = (ctx->plot->clip(ctx, clip) == NSERROR_OK);
1976
1978 pstyle_fill_bg.fill_colour = html->background_colour;
1979
1980 result &= (ctx->plot->rectangle(ctx, &pstyle_fill_bg, clip) == NSERROR_OK);
1981
1983 data->scale, pstyle_fill_bg.fill_colour, ctx);
1984 }
1985
1986 if (select) {
1987 int menu_x, menu_y;
1989 box_coords(box, &menu_x, &menu_y);
1990
1991 menu_x -= box->border[LEFT].width;
1992 menu_y += box->height + box->border[BOTTOM].width +
1995 data->x + menu_x, data->y + menu_y,
1996 data->scale, clip, ctx);
1997 }
1998
1999 return result;
2000
2001}
STATIC char result[100]
Definition: arexx.c:77
Box interface.
@ BOX_BLOCK
Definition: box.h:56
@ BOX_FLOAT_LEFT
Definition: box.h:63
@ BOX_INLINE_BLOCK
Definition: box.h:65
@ BOX_FLOAT_RIGHT
Definition: box.h:64
@ BOX_INLINE_CONTAINER
Definition: box.h:57
@ BOX_TABLE_CELL
Definition: box.h:61
@ BOX_INLINE_END
Definition: box.h:68
@ BOX_TABLE
Definition: box.h:59
@ BOX_INLINE
Definition: box.h:58
@ BOX_TABLE_ROW
Definition: box.h:60
@ BOX_TEXT
Definition: box.h:67
@ BOX_BR
Definition: box.h:66
@ IFRAME
Definition: box.h:89
@ NEW_LINE
Definition: box.h:79
@ REPLACE_DIM
Definition: box.h:88
@ PRINTED
Definition: box.h:81
@ TOP
Definition: box.h:98
@ BOTTOM
Definition: box.h:98
@ LEFT
Definition: box.h:98
@ RIGHT
Definition: box.h:98
bool box_hscrollbar_present(const struct box *const box)
Determine if a box has a horizontal scrollbar.
Definition: box_inspect.c:839
bool box_vscrollbar_present(const struct box *const box)
Determine if a box has a vertical scrollbar.
Definition: box_inspect.c:829
void box_coords(struct box *box, int *x, int *y)
Find the absolute coordinates of a box.
Definition: box_inspect.c:549
HTML Box tree inspection interface.
nserror box_handle_scrollbars(struct content *c, struct box *box, bool bottom, bool right)
Applies the given scroll setup to a box.
Box tree manipulation interface.
Browser window creation and manipulation interface.
bool browser_window_redraw(struct browser_window *bw, int x, int y, const struct rect *clip, const struct redraw_context *ctx)
Redraw an area of a window.
Content handling interface.
void font_plot_style_from_css(const css_unit_ctx *unit_len_ctx, const css_computed_style *css, plot_font_style_t *fstyle)
Populate a font style using data from a computed CSS style.
Definition: font.c:135
Internal font handling interfaces.
interface to HTML layout.
bool content_get_opaque(hlcache_handle *h)
Determine if a content is opaque from handle.
Definition: content.c:1288
Protected interface to Content handling.
@ CONTENT_HTML
content is HTML
Definition: content_type.h:58
Useful interned string pointers (interface).
bool html_redraw_printing
Definition: print.c:51
int html_redraw_printing_border
Definition: print.c:52
int html_redraw_printing_top_cropped
Definition: print.c:53
Conception: Generalized output-in-pages.
bool selection_highlighted(const struct selection *s, unsigned start, unsigned end, unsigned *start_idx, unsigned *end_idx)
Tests whether a text range lies partially within the selection, if there is a selection defined,...
Definition: selection.c:562
Text selection within browser windows (interface).
void textarea_redraw(struct textarea *ta, int x, int y, colour bg, float scale, const struct rect *clip, const struct redraw_context *ctx)
Handle redraw requests for text areas.
Definition: textarea.c:2131
Single/Multi-line UTF-8 text area interface.
wimp_w parent
Definition: dialog.c:88
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_OK
No error.
Definition: errors.h:30
bool form_clip_inside_select_menu(struct form_control *control, float scale, const struct rect *clip)
Check whether a clipping rectangle is completely contained in the select menu.
Definition: form.c:1807
bool form_redraw_select_menu(struct form_control *control, int x, int y, float scale, const struct rect *clip, const struct redraw_context *ctx)
Redraw an opened select menu.
Definition: form.c:1656
Interface to form handling functions internal to HTML content handler.
@ GADGET_TEXTAREA
Definition: form_internal.h:53
@ GADGET_PASSWORD
Definition: form_internal.h:55
@ GADGET_CHECKBOX
Definition: form_internal.h:51
@ GADGET_FILE
Definition: form_internal.h:58
@ GADGET_TEXTBOX
Definition: form_internal.h:49
@ GADGET_RADIO
Definition: form_internal.h:50
#define NOF_ELEMENTS(array)
Definition: search.c:67
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:49
Interface to core interface table.
Generic bitmap handling interface.
Public content interface.
bool content_redraw(struct hlcache_handle *h, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx)
Display content on screen with optional tiling.
Definition: content.c:558
int content_get_height(struct hlcache_handle *h)
Retrieve height of content.
Definition: content.c:1175
int content_get_width(struct hlcache_handle *h)
Retrieve width of content.
Definition: content.c:1158
content_type content_get_type(struct hlcache_handle *h)
Retrieve computed type of content.
Definition: content.c:1061
#define nscss_color_is_transparent(color)
Determine if a CSS color primitive is transparent.
Definition: css.h:62
#define nscss_color_to_ns(c)
Convert a CSS color to a NetSurf colour primitive.
Definition: css.h:35
Interface to platform-specific layout operation table.
Target independent plotting interface.
#define BITMAPF_NONE
Definition: plotters.h:37
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get_errorcode(nserror code)
lookup of a message by errorcode from the standard Messages hash.
Definition: messages.c:248
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
#define colour_to_bw_furthest(c0)
Definition: plot_style.h:193
plot_style_t * plot_style_fill_white
Definition: plot_style.c:32
plot_style_t const *const plot_style_broken_object
Definition: plot_style.c:79
plot_style_t const *const plot_style_margin_edge
Definition: plot_style.c:68
plot_style_t const *const plot_style_content_edge
Definition: plot_style.c:52
#define blend_colour(c0, c1)
Definition: plot_style.h:163
plot_style_t * plot_style_fill_wbasec
Definition: plot_style.c:109
plot_style_t * plot_style_stroke_darkwbasec
Definition: plot_style.c:146
@ PLOT_OP_TYPE_SOLID
Solid colour.
Definition: plot_style.h:67
plot_style_t const *const plot_style_padding_edge
Definition: plot_style.c:60
plot_style_t * plot_style_fill_wblobc
Definition: plot_style.c:131
#define NS_TRANSPARENT
Transparent colour value.
Definition: plot_style.h:39
plot_font_style_t const *const plot_fstyle_broken_object
Definition: plot_style.c:90
plot_style_t * plot_style_stroke_lightwbasec
Definition: plot_style.c:153
plot_style_t * plot_style_fill_lightwbasec
Definition: plot_style.c:123
plot_style_t * plot_style_stroke_wblobc
Definition: plot_style.c:139
plot_style_t * plot_style_fill_darkwbasec
Definition: plot_style.c:116
Private data for text/html content.
bool html_redraw_borders(struct box *box, int x_parent, int y_parent, int p_width, int p_height, const struct rect *clip, float scale, const struct redraw_context *ctx)
Draw borders for a box.
bool html_redraw_inline_borders(struct box *box, struct rect b, const struct rect *clip, float scale, bool first, bool last, const struct redraw_context *ctx)
Draw an inline's borders.
static bool html_redraw_box_children(const html_content *html, struct box *box, int x_parent, int y_parent, const struct rect *clip, float scale, colour current_background_color, const struct redraw_context *ctx)
Draw the various children of a box.
Definition: redraw.c:1182
bool html_redraw_box(const html_content *html, struct box *box, int x_parent, int y_parent, const struct rect *clip, float scale, colour current_background_color, const struct redraw_context *ctx)
Recursively draw a box.
Definition: redraw.c:1231
static bool html_redraw_background(int x, int y, struct box *box, float scale, const struct rect *clip, colour *background_colour, struct box *background, const css_unit_ctx *unit_len_ctx, const struct redraw_context *ctx)
Plot background images.
Definition: redraw.c:595
static bool html_redraw_radio(int x, int y, int width, int height, bool selected, const struct redraw_context *ctx)
Plot a radio icon.
Definition: redraw.c:466
bool html_redraw(struct content *c, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx)
Draw a CONTENT_HTML using the current set of plotters (plot).
Definition: redraw.c:1944
static bool text_redraw(const char *utf8_text, size_t utf8_len, size_t offset, int space, const plot_font_style_t *fstyle, int x, int y, const struct rect *clip, int height, float scale, bool excluded, struct content *c, const struct selection *sel, const struct redraw_context *ctx)
Redraw a short text string, complete with highlighting (for selection/search)
Definition: redraw.c:158
static bool html_redraw_text_decoration_block(struct box *box, int x, int y, float scale, colour colour, float ratio, const struct redraw_context *ctx)
Plot text decoration for an non-inline box.
Definition: redraw.c:1024
static bool html_redraw_box_has_background(struct box *box)
Determine if a box has a background that needs drawing.
Definition: redraw.c:76
static bool html_redraw_file(int x, int y, int width, int height, struct box *box, float scale, colour background_colour, const css_unit_ctx *unit_len_ctx, const struct redraw_context *ctx)
Plot a file upload input.
Definition: redraw.c:536
bool html_redraw_debug
Render padding and margin box outlines in html_redraw().
Definition: redraw.c:68
static bool html_redraw_text_decoration(struct box *box, int x_parent, int y_parent, float scale, colour background_colour, const struct redraw_context *ctx)
Plot text decoration for a box.
Definition: redraw.c:1073
static bool html_redraw_text_box(const html_content *html, struct box *box, int x, int y, const struct rect *clip, float scale, colour current_background_color, const struct redraw_context *ctx)
Redraw the text content of a box, possibly partially highlighted because the text has been selected,...
Definition: redraw.c:1133
static struct box * html_redraw_find_bg_box(struct box *box)
Find the background box for a box.
Definition: redraw.c:99
static bool html_redraw_text_decoration_inline(struct box *box, int x, int y, float scale, colour colour, float ratio, const struct redraw_context *ctx)
Plot text decoration for an inline box.
Definition: redraw.c:976
static bool html_redraw_checkbox(int x, int y, int width, int height, bool selected, const struct redraw_context *ctx)
Plot a checkbox.
Definition: redraw.c:367
static bool html_redraw_inline_background(int x, int y, struct box *box, float scale, const struct rect *clip, struct rect b, bool first, bool last, colour *background_colour, const css_unit_ctx *unit_len_ctx, const struct redraw_context *ctx)
Plot an inline's background and/or background image.
Definition: redraw.c:824
int width
Definition: gui.c:159
int height
Definition: gui.c:160
int scrollbar_get_offset(struct scrollbar *s)
Get the current scroll offset to the visible part of the full area.
Definition: scrollbar.c:627
nserror scrollbar_redraw(struct scrollbar *s, int x, int y, const struct rect *clip, float scale, const struct redraw_context *ctx)
Redraw a part of the scrollbar.
Definition: scrollbar.c:239
Scrollbar widget interface.
#define SCROLLBAR_WIDTH
Definition: scrollbar.h:32
Interface to utility string handling.
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
int width
border-width (pixels)
Definition: box.h:107
Node in box tree.
Definition: box.h:177
int descendant_y1
bottom edge of descendants
Definition: box.h:312
struct box_border border[4]
Border: TOP, RIGHT, BOTTOM, LEFT.
Definition: box.h:327
int width
Width of content box (excluding padding etc.).
Definition: box.h:289
struct box * parent
Parent box, or NULL.
Definition: box.h:236
struct scrollbar * scroll_x
Horizontal scroll.
Definition: box.h:332
size_t byte_offset
Byte offset within a textual representation of this content.
Definition: box.h:370
struct box * inline_end
INLINE_END box corresponding to this INLINE box, or INLINE box corresponding to this INLINE_END box.
Definition: box.h:242
struct box * children
First child box, or NULL.
Definition: box.h:226
int height
Height of content box (excluding padding etc.).
Definition: box.h:293
struct hlcache_handle * background
Background image for this box, or NULL if none.
Definition: box.h:435
struct box * list_marker
List marker box if this is a list-item, or NULL.
Definition: box.h:417
int margin[4]
Margin: TOP, RIGHT, BOTTOM, LEFT.
Definition: box.h:317
struct box * next_float
Next sibling float box.
Definition: box.h:256
struct box * next
Next sibling box, or NULL.
Definition: box.h:216
int descendant_x0
left edge of descendants
Definition: box.h:309
struct scrollbar * scroll_y
Vertical scroll.
Definition: box.h:337
box_type type
Type of box.
Definition: box.h:181
struct box * float_children
First float child box, or NULL.
Definition: box.h:251
int descendant_x1
right edge of descendants
Definition: box.h:311
struct browser_window * iframe
Iframe's browser_window, or NULL if none.
Definition: box.h:452
css_computed_style * style
Style for this box.
Definition: box.h:205
size_t length
Length of text.
Definition: box.h:360
struct hlcache_handle * object
Object in this box (usually an image), or NULL if none.
Definition: box.h:441
char * text
Text, or NULL if none.
Definition: box.h:355
int padding[4]
Padding: TOP, RIGHT, BOTTOM, LEFT.
Definition: box.h:322
int x
Coordinate of left padding edge relative to parent box, or relative to ancestor that contains this bo...
Definition: box.h:280
box_flags flags
Box flags.
Definition: box.h:186
int space
Width of space after current text (depends on font and size).
Definition: box.h:365
struct form_control * gadget
Form control data, or NULL if not a form control.
Definition: box.h:423
int descendant_y0
top edge of descendants
Definition: box.h:310
struct dom_node * node
DOM node that generated this box or NULL.
Definition: box.h:191
int y
Coordinate of top padding edge, relative as for x.
Definition: box.h:284
parameters to content redraw
Definition: content.h:40
int height
vertical dimension
Definition: content.h:48
bool repeat_y
whether content is tiled in y direction
Definition: content.h:59
bool repeat_x
whether content is tiled in x direction
Definition: content.h:58
int y
coordinate for top-left of redraw
Definition: content.h:42
int x
coordinate for top-left of redraw
Definition: content.h:41
colour background_colour
The background colour.
Definition: content.h:51
int width
dimensions to render content at (for scaling contents with intrinsic dimensions)
Definition: content.h:47
float scale
Scale for redraw (for scaling contents without intrinsic dimensions)
Definition: content.h:56
Content which corresponds to a single URL.
struct content::@117 textsearch
Free text search state.
struct textsearch_context * context
Form control.
Definition: form_internal.h:73
struct form_textarea_data data
struct form_control::@132::@134 select
form_control_type type
Type of control.
Definition: form_internal.h:79
struct html_content * html
HTML content containing control.
Definition: form_internal.h:77
char * value
Current value of control.
Definition: form_internal.h:84
bool selected
Whether control is selected.
Definition: form_internal.h:94
struct box * box
Box for control.
Definition: form_internal.h:89
nserror(* width)(const struct plot_font_style *fstyle, const char *string, size_t length, int *width)
Measure the width of a string.
Definition: layout.h:49
Data specific to CONTENT_HTML.
Definition: private.h:93
struct selection * sel
HTML content's own text selection object.
Definition: private.h:205
colour background_colour
Document background colour.
Definition: private.h:142
struct form_control * visible_select_menu
Open core-handled form SELECT menu, or NULL if none currently open.
Definition: private.h:211
css_unit_ctx unit_len_ctx
CSS length conversion context for document.
Definition: private.h:163
struct box * layout
Box tree, or NULL.
Definition: private.h:140
struct gui_layout_table * layout
Layout table.
Definition: gui_table.h:154
Font style for plotting.
Definition: plot_style.h:111
colour foreground
Colour of text.
Definition: plot_style.h:123
plot_style_fixed size
Font size, in pt.
Definition: plot_style.h:119
colour background
Background colour to blend to, if appropriate.
Definition: plot_style.h:122
Plot style for stroke/fill plotters.
Definition: plot_style.h:76
colour fill_colour
Colour of fill.
Definition: plot_style.h:81
plot_operation_type_t fill_type
Fill plot type.
Definition: plot_style.h:80
plot_operation_type_t stroke_type
Stroke plot type.
Definition: plot_style.h:77
Plotter operations table.
Definition: plotters.h:102
nserror(* group_start)(const struct redraw_context *ctx, const char *name)
Start of a group of objects.
Definition: plotters.h:295
nserror(* line)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *line)
Plots a line.
Definition: plotters.h:170
nserror(* group_end)(const struct redraw_context *ctx)
End of the most recently started group.
Definition: plotters.h:307
nserror(* arc)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int y, int radius, int angle1, int angle2)
Plots an arc.
Definition: plotters.h:131
nserror(* text)(const struct redraw_context *ctx, const plot_font_style_t *fstyle, int x, int y, const char *text, size_t length)
Text plotting.
Definition: plotters.h:278
nserror(* rectangle)(const struct redraw_context *ctx, const plot_style_t *pstyle, const struct rect *rectangle)
Plots a rectangle.
Definition: plotters.h:188
nserror(* clip)(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plotters.h:111
nserror(* bitmap)(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y, int width, int height, colour bg, bitmap_flags_t flags)
Plot a bitmap.
Definition: plotters.h:257
nserror(* disc)(const struct redraw_context *ctx, const plot_style_t *pstyle, int x, int y, int radius)
Plots a circle.
Definition: plotters.h:152
Rectangle coordinates.
Definition: types.h:40
int x0
Definition: types.h:41
int y0
Top left.
Definition: types.h:41
int x1
Definition: types.h:42
int y1
Bottom right.
Definition: types.h:42
Redraw context.
Definition: plotters.h:51
bool background_images
Render background images.
Definition: plotters.h:66
const struct plotter_table * plot
Current plot operation table.
Definition: plotters.h:73
bool interactive
Redraw to show interactive features.
Definition: plotters.h:59
bool content_textsearch_ishighlighted(struct textsearch_context *textsearch, unsigned start_offset, unsigned end_offset, unsigned *start_idx, unsigned *end_idx)
Determines whether any portion of the given text box should be selected because it matches the curren...
Definition: textsearch.c:623
Interface to HTML searching.
uint32_t colour
Colour type: XBGR.
Definition: types.h:35
Option reading and saving interface.
#define nsoption_bool(OPTION)
Get the value of a boolean option.
Definition: nsoption.h:270
Interface to a number of general purpose functionality.
#define min(x, y)
Definition: utils.h:46
#define max(x, y)
Definition: utils.h:50
static nserror text(const struct redraw_context *ctx, const struct plot_font_style *fstyle, int x, int y, const char *text, size_t length)
Text plotting.
Definition: plot.c:978
static nserror clip(const struct redraw_context *ctx, const struct rect *clip)
Sets a clip rectangle for subsequent plot operations.
Definition: plot.c:357