NetSurf
imagemap.c
Go to the documentation of this file.
1/*
2 * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * Implementation of HTML image maps
22 *
23 * \todo should this should use the general hashmap instead of its own
24 */
25
26#include <assert.h>
27#include <stdbool.h>
28#include <string.h>
29#include <strings.h>
30
31#include <dom/dom.h>
32
33#include "utils/log.h"
34#include "utils/corestrings.h"
36#include "content/hlcache.h"
37
38#include "html/box.h"
39#include "html/box_construct.h"
40#include "html/private.h"
41#include "html/imagemap.h"
42
43#define HASH_SIZE 31 /* fixed size hash table */
44
45typedef enum {
51
52struct mapentry {
53 imagemap_entry_type type; /**< type of shape */
54 nsurl *url; /**< absolute url to go to */
55 char *target; /**< target frame (if any) */
56 union {
57 struct {
58 int x; /**< x coordinate of centre */
59 int y; /**< y coordinate of center */
60 int r; /**< radius of circle */
62 struct {
63 int x0; /**< left hand edge */
64 int y0; /**< top edge */
65 int x1; /**< right hand edge */
66 int y1; /**< bottom edge */
68 struct {
69 int num; /**< number of points */
70 float *xcoords; /**< x coordinates */
71 float *ycoords; /**< y coordinates */
74 struct mapentry *next; /**< next entry in list */
75};
76
77struct imagemap {
78 char *key; /**< key for this entry */
79 struct mapentry *list; /**< pointer to linked list of entries */
80 struct imagemap *next; /**< next entry in this hash chain */
81};
82
83/**
84 * Create hashtable of imagemaps
85 *
86 * \param c The containing content
87 * \return true on success, false otherwise
88 */
90{
91 assert(c != NULL);
92
93 if (c->imagemaps == NULL) {
94 c->imagemaps = calloc(HASH_SIZE, sizeof(struct imagemap *));
95 if (c->imagemaps == NULL) {
96 return false;
97 }
98 }
99
100 return true;
101}
102
103/**
104 * Hash function.
105 *
106 * \param key The key to hash.
107 * \return The hashed value.
108 */
109static unsigned int imagemap_hash(const char *key)
110{
111 unsigned int z = 0;
112
113 if (key == 0) return 0;
114
115 for (; *key != 0; key++) {
116 z += *key & 0x1f;
117 }
118
119 return (z % (HASH_SIZE - 1)) + 1;
120}
121
122/**
123 * Add an imagemap to the hashtable, creating it if it doesn't exist
124 *
125 * \param c The containing content
126 * \param key The name of the imagemap
127 * \param list List of map regions
128 * \return true on succes, false otherwise
129 */
130static bool
131imagemap_add(html_content *c, dom_string *key, struct mapentry *list)
132{
133 struct imagemap *map;
134 unsigned int slot;
135
136 assert(c != NULL);
137 assert(key != NULL);
138 assert(list != NULL);
139
140 if (imagemap_create(c) == false)
141 return false;
142
143 map = calloc(1, sizeof(*map));
144 if (map == NULL)
145 return false;
146
147 /* \todo Stop relying on NULL termination of dom_string */
148 map->key = strdup(dom_string_data(key));
149 if (map->key == NULL) {
150 free(map);
151 return false;
152 }
153
154 map->list = list;
155
156 slot = imagemap_hash(map->key);
157
158 map->next = c->imagemaps[slot];
159 c->imagemaps[slot] = map;
160
161 return true;
162}
163
164/**
165 * Free list of imagemap entries
166 *
167 * \param list Pointer to head of list
168 */
169static void imagemap_freelist(struct mapentry *list)
170{
171 struct mapentry *entry, *prev;
172
173 assert(list != NULL);
174
175 entry = list;
176
177 while (entry != NULL) {
178 prev = entry;
179
180 nsurl_unref(entry->url);
181
182 if (entry->target)
183 free(entry->target);
184
185 if (entry->type == IMAGEMAP_POLY) {
186 free(entry->bounds.poly.xcoords);
187 free(entry->bounds.poly.ycoords);
188 }
189
190 entry = entry->next;
191 free(prev);
192 }
193}
194
195/**
196 * Destroy hashtable of imagemaps
197 *
198 * \param c The containing content
199 */
201{
202 unsigned int i;
203
204 assert(c != NULL);
205
206 /* no imagemaps -> return */
207 if (c->imagemaps == NULL)
208 return;
209
210 for (i = 0; i != HASH_SIZE; i++) {
211 struct imagemap *map, *next;
212
213 map = c->imagemaps[i];
214 while (map != NULL) {
215 next = map->next;
217 free(map->key);
218 free(map);
219 map = next;
220 }
221 }
222
223 free(c->imagemaps);
224}
225
226/**
227 * Dump imagemap data to the log
228 *
229 * \param c The containing content
230 */
232{
233 unsigned int i;
234
235 int j;
236
237 assert(c != NULL);
238
239 if (c->imagemaps == NULL)
240 return;
241
242 for (i = 0; i != HASH_SIZE; i++) {
243 struct imagemap *map;
244 struct mapentry *entry;
245
246 map = c->imagemaps[i];
247 while (map != NULL) {
248 NSLOG(netsurf, INFO, "Imagemap: %s", map->key);
249
250 for (entry = map->list; entry; entry = entry->next) {
251 switch (entry->type) {
252 case IMAGEMAP_DEFAULT:
253 NSLOG(netsurf, INFO, "\tDefault: %s",
254 nsurl_access(entry->url));
255 break;
256 case IMAGEMAP_RECT:
257 NSLOG(netsurf, INFO,
258 "\tRectangle: %s: [(%d,%d),(%d,%d)]",
259 nsurl_access(entry->url),
260 entry->bounds.rect.x0,
261 entry->bounds.rect.y0,
262 entry->bounds.rect.x1,
263 entry->bounds.rect.y1);
264 break;
265 case IMAGEMAP_CIRCLE:
266 NSLOG(netsurf, INFO,
267 "\tCircle: %s: [(%d,%d),%d]",
268 nsurl_access(entry->url),
269 entry->bounds.circle.x,
270 entry->bounds.circle.y,
271 entry->bounds.circle.r);
272 break;
273 case IMAGEMAP_POLY:
274 NSLOG(netsurf, INFO,
275 "\tPolygon: %s:",
276 nsurl_access(entry->url));
277 for (j = 0; j != entry->bounds.poly.num;
278 j++) {
279 fprintf(stderr, "(%d,%d) ",
280 (int)entry->bounds.poly.xcoords[j],
281 (int)entry->bounds.poly.ycoords[j]);
282 }
283 fprintf(stderr,"\n");
284 break;
285 }
286 }
287 map = map->next;
288 }
289 }
290}
291
292/**
293 * Adds an imagemap entry to the list
294 *
295 * \param c The html content that the imagemap belongs to
296 * \param n The xmlNode representing the entry to add
297 * \param base_url Base URL for resolving relative URLs
298 * \param entry Pointer to list of entries
299 * \param tagtype The type of tag
300 * \return false on memory exhaustion, true otherwise
301 */
302static bool
304 dom_node *n,
305 nsurl *base_url,
306 struct mapentry **entry,
307 dom_string *tagtype)
308{
309 dom_exception exc;
310 dom_string *href = NULL, *target = NULL, *shape = NULL;
311 dom_string *coords = NULL;
312 struct mapentry *new_map, *temp;
313 bool ret = true;
314
315 if (dom_string_caseless_isequal(tagtype, corestring_dom_area)) {
316 bool nohref = false;
317 exc = dom_element_has_attribute(n,
318 corestring_dom_nohref, &nohref);
319 if ((exc != DOM_NO_ERR) || nohref)
320 /* Skip <area nohref="anything" /> */
321 goto ok_out;
322 }
323
324 exc = dom_element_get_attribute(n, corestring_dom_href, &href);
325 if (exc != DOM_NO_ERR || href == NULL) {
326 /* No href="" attribute, skip this element */
327 goto ok_out;
328 }
329
330 exc = dom_element_get_attribute(n, corestring_dom_target, &target);
331 if (exc != DOM_NO_ERR) {
332 goto ok_out;
333 }
334
335 exc = dom_element_get_attribute(n, corestring_dom_shape, &shape);
336 if (exc != DOM_NO_ERR) {
337 goto ok_out;
338 }
339
340 /* If there's no shape, we default to rectangles */
341 if (shape == NULL)
342 shape = dom_string_ref(corestring_dom_rect);
343
344 if (!dom_string_caseless_lwc_isequal(shape, corestring_lwc_default)) {
345 /* If not 'default' and there's no 'coords' give up */
346 exc = dom_element_get_attribute(n, corestring_dom_coords,
347 &coords);
348 if (exc != DOM_NO_ERR || coords == NULL) {
349 goto ok_out;
350 }
351 }
352
353 new_map = calloc(1, sizeof(*new_map));
354 if (new_map == NULL) {
355 goto bad_out;
356 }
357
358 if (dom_string_caseless_lwc_isequal(shape, corestring_lwc_rect) ||
359 dom_string_caseless_lwc_isequal(shape, corestring_lwc_rectangle))
360 new_map->type = IMAGEMAP_RECT;
361 else if (dom_string_caseless_lwc_isequal(shape, corestring_lwc_circle))
362 new_map->type = IMAGEMAP_CIRCLE;
363 else if (dom_string_caseless_lwc_isequal(shape, corestring_lwc_poly) ||
364 dom_string_caseless_lwc_isequal(shape, corestring_lwc_polygon))
365 new_map->type = IMAGEMAP_POLY;
366 else if (dom_string_caseless_lwc_isequal(shape, corestring_lwc_default))
367 new_map->type = IMAGEMAP_DEFAULT;
368 else
369 goto bad_out;
370
371 if (box_extract_link(c, href, base_url, &new_map->url) == false)
372 goto bad_out;
373
374 if (new_map->url == NULL) {
375 /* non-fatal error -> ignore this */
376 goto ok_free_map_out;
377 }
378
379 if (target != NULL) {
380 /* Copy target dom string into the map data */
381 new_map->target = malloc(dom_string_byte_length(target) + 1);
382 if (new_map->target == NULL)
383 goto bad_out;
384
385 memcpy(new_map->target,
386 dom_string_data(target),
387 dom_string_byte_length(target));
388
389 new_map->target[dom_string_byte_length(target)] = 0;
390 }
391
392 if (new_map->type != IMAGEMAP_DEFAULT) {
393 int x, y;
394 float *xcoords, *ycoords;
395 /* coordinates are a comma-separated list of values */
396 char *val = strtok((char *)dom_string_data(coords), ",");
397 int num = 1;
398
399 switch (new_map->type) {
400 case IMAGEMAP_RECT:
401 /* (left, top, right, bottom) */
402 while (val != NULL && num <= 4) {
403 switch (num) {
404 case 1:
405 new_map->bounds.rect.x0 = atoi(val);
406 break;
407 case 2:
408 new_map->bounds.rect.y0 = atoi(val);
409 break;
410 case 3:
411 new_map->bounds.rect.x1 = atoi(val);
412 break;
413 case 4:
414 new_map->bounds.rect.y1 = atoi(val);
415 break;
416 }
417
418 num++;
419 val = strtok(NULL, ",");
420 }
421 break;
422 case IMAGEMAP_CIRCLE:
423 /* (x, y, radius ) */
424 while (val != NULL && num <= 3) {
425 switch (num) {
426 case 1:
427 new_map->bounds.circle.x = atoi(val);
428 break;
429 case 2:
430 new_map->bounds.circle.y = atoi(val);
431 break;
432 case 3:
433 new_map->bounds.circle.r = atoi(val);
434 break;
435 }
436
437 num++;
438 val = strtok(NULL, ",");
439 }
440 break;
441 case IMAGEMAP_POLY:
442 new_map->bounds.poly.xcoords = NULL;
443 new_map->bounds.poly.ycoords = NULL;
444
445 while (val != NULL) {
446 x = atoi(val);
447
448 val = strtok(NULL, ",");
449 if (val == NULL)
450 break;
451
452 y = atoi(val);
453
454 xcoords = realloc(new_map->bounds.poly.xcoords,
455 num * sizeof(float));
456 if (xcoords == NULL) {
457 goto bad_out;
458 }
459 new_map->bounds.poly.xcoords = xcoords;
460
461 ycoords = realloc(new_map->bounds.poly.ycoords,
462 num * sizeof(float));
463 if (ycoords == NULL) {
464 goto bad_out;
465 }
466 new_map->bounds.poly.ycoords = ycoords;
467
468 new_map->bounds.poly.xcoords[num - 1] = x;
469 new_map->bounds.poly.ycoords[num - 1] = y;
470
471 num++;
472 val = strtok(NULL, ",");
473 }
474
475 new_map->bounds.poly.num = num - 1;
476
477 break;
478 default:
479 break;
480 }
481 }
482
483 new_map->next = NULL;
484
485 if (*entry) {
486 /* add to END of list */
487 for (temp = (*entry); temp->next != NULL; temp = temp->next)
488 ;
489 temp->next = new_map;
490 } else {
491 (*entry) = new_map;
492 }
493
494 /* All good, linked in, let's clean up */
495 goto ok_out;
496
497bad_out:
498 ret = false;
499ok_free_map_out:
500 if (new_map != NULL) {
501 if (new_map->url != NULL)
502 nsurl_unref(new_map->url);
503 if (new_map->type == IMAGEMAP_POLY &&
504 new_map->bounds.poly.ycoords != NULL)
505 free(new_map->bounds.poly.ycoords);
506 if (new_map->type == IMAGEMAP_POLY &&
507 new_map->bounds.poly.xcoords != NULL)
508 free(new_map->bounds.poly.xcoords);
509 if (new_map->target != NULL)
510 free(new_map->target);
511
512 free(new_map);
513 }
514ok_out:
515 if (href != NULL)
516 dom_string_unref(href);
517 if (target != NULL)
518 dom_string_unref(target);
519 if (shape != NULL)
520 dom_string_unref(shape);
521 if (coords != NULL)
522 dom_string_unref(coords);
523
524 return ret;
525}
526
527/**
528 * Extract an imagemap from html source
529 *
530 * \param node XML node containing map
531 * \param c Content containing document
532 * \param entry List of map entries
533 * \param tname The sub-tags to consider on this pass
534 * \return false on memory exhaustion, true otherwise
535 */
536static bool
538 struct mapentry **entry, dom_string *tname)
539{
540 dom_nodelist *nlist;
541 dom_exception exc;
542 unsigned long ent;
543 uint32_t tag_count;
544
545 exc = dom_element_get_elements_by_tag_name(node, tname, &nlist);
546 if (exc != DOM_NO_ERR) {
547 return false;
548 }
549
550 exc = dom_nodelist_get_length(nlist, &tag_count);
551 if (exc != DOM_NO_ERR) {
552 dom_nodelist_unref(nlist);
553 return false;
554 }
555
556 for (ent = 0; ent < tag_count; ++ent) {
557 dom_node *subnode;
558
559 exc = dom_nodelist_item(nlist, ent, &subnode);
560 if (exc != DOM_NO_ERR) {
561 dom_nodelist_unref(nlist);
562 return false;
563 }
564 if (imagemap_addtolist(c, subnode, c->base_url,
565 entry, tname) == false) {
566 dom_node_unref(subnode);
567 dom_nodelist_unref(nlist);
568 return false;
569 }
570 dom_node_unref(subnode);
571 }
572
573 dom_nodelist_unref(nlist);
574
575 return true;
576}
577
578/**
579 * Extract an imagemap from html source
580 *
581 * \param node XML node containing map
582 * \param c Content containing document
583 * \param entry List of map entries
584 * \return false on memory exhaustion, true otherwise
585 */
586static bool imagemap_extract_map(dom_node *node, html_content *c,
587 struct mapentry **entry)
588{
589 if (imagemap_extract_map_entries(node, c, entry,
590 corestring_dom_area) == false)
591 return false;
592 return imagemap_extract_map_entries(node, c, entry,
593 corestring_dom_a);
594}
595
596/**
597 * Extract all imagemaps from a document tree
598 *
599 * \param c The content to extract imagemaps from.
600 * \return false on memory exhaustion, true otherwise
601 */
604{
605 dom_nodelist *nlist;
606 dom_exception exc;
607 unsigned long mapnr;
608 uint32_t maybe_maps;
609 nserror ret = NSERROR_OK;
610
611 exc = dom_document_get_elements_by_tag_name(c->document,
612 corestring_dom_map,
613 &nlist);
614 if (exc != DOM_NO_ERR) {
615 return NSERROR_DOM;
616 }
617
618 exc = dom_nodelist_get_length(nlist, &maybe_maps);
619 if (exc != DOM_NO_ERR) {
620 ret = NSERROR_DOM;
621 goto out_nlist;
622 }
623
624 for (mapnr = 0; mapnr < maybe_maps; ++mapnr) {
625 dom_node *node;
626 dom_string *name;
627 exc = dom_nodelist_item(nlist, mapnr, &node);
628 if (exc != DOM_NO_ERR) {
629 ret = NSERROR_DOM;
630 goto out_nlist;
631 }
632
633 exc = dom_element_get_attribute(node, corestring_dom_id,
634 &name);
635 if (exc != DOM_NO_ERR) {
636 dom_node_unref(node);
637 ret = NSERROR_DOM;
638 goto out_nlist;
639 }
640
641 if (name == NULL) {
642 exc = dom_element_get_attribute(node,
643 corestring_dom_name,
644 &name);
645 if (exc != DOM_NO_ERR) {
646 dom_node_unref(node);
647 ret = NSERROR_DOM;
648 goto out_nlist;
649 }
650 }
651
652 if (name != NULL) {
653 struct mapentry *entry = NULL;
654 if (imagemap_extract_map(node, c, &entry) == false) {
655 if (entry != NULL) {
656 imagemap_freelist(entry);
657 }
658
659 dom_string_unref(name);
660 dom_node_unref(node);
661 ret = NSERROR_NOMEM; /** @todo check this */
662 goto out_nlist;
663 }
664
665 /* imagemap_extract_map may not extract anything,
666 * so entry can still be NULL here. This isn't an
667 * error as it just means that we've encountered
668 * an incorrectly defined <map>...</map> block
669 */
670 if ((entry != NULL) &&
671 (imagemap_add(c, name, entry) == false)) {
672 imagemap_freelist(entry);
673
674 dom_string_unref(name);
675 dom_node_unref(node);
676 ret = NSERROR_NOMEM; /** @todo check this */
677 goto out_nlist;
678 }
679 }
680
681 dom_string_unref(name);
682 dom_node_unref(node);
683 }
684
685out_nlist:
686
687 dom_nodelist_unref(nlist);
688
689 return ret;
690}
691
692/**
693 * Test if a point lies within an arbitrary polygon
694 * Modified from comp.graphics.algorithms FAQ 2.03
695 *
696 * \param num Number of vertices
697 * \param xpt Array of x coordinates
698 * \param ypt Array of y coordinates
699 * \param x Left hand edge of containing box
700 * \param y Top edge of containing box
701 * \param click_x X coordinate of click
702 * \param click_y Y coordinate of click
703 * \return 1 if point is in polygon, 0 if outside. 0 or 1 if on boundary
704 */
705static int
706imagemap_point_in_poly(int num, float *xpt, float *ypt, unsigned long x,
707 unsigned long y, unsigned long click_x, unsigned long click_y)
708{
709 int i, j, c = 0;
710
711 assert(xpt != NULL);
712 assert(ypt != NULL);
713
714 for (i = 0, j = num - 1; i < num; j = i++) {
715 if ((((ypt[i] + y <= click_y) && (click_y < ypt[j] + y)) ||
716 ((ypt[j] + y <= click_y) && (click_y < ypt[i] + y))) &&
717 (click_x < (xpt[j] - xpt[i]) *
718 (click_y - (ypt[i] + y)) / (ypt[j] - ypt[i]) + xpt[i] + x))
719 c = !c;
720 }
721
722 return c;
723}
724
725/**
726 * Retrieve url associated with imagemap entry
727 *
728 * \param c The containing content
729 * \param key The map name to search for
730 * \param x The left edge of the containing box
731 * \param y The top edge of the containing box
732 * \param click_x The horizontal location of the click
733 * \param click_y The vertical location of the click
734 * \param target Pointer to location to receive target pointer (if any)
735 * \return The url associated with this area, or NULL if not found
736 */
737nsurl *imagemap_get(struct html_content *c, const char *key,
738 unsigned long x, unsigned long y,
739 unsigned long click_x, unsigned long click_y,
740 const char **target)
741{
742 unsigned int slot = 0;
743 struct imagemap *map;
744 struct mapentry *entry;
745 unsigned long cx, cy;
746
747 assert(c != NULL);
748
749 if (key == NULL)
750 return NULL;
751
752 if (c->imagemaps == NULL)
753 return NULL;
754
755 slot = imagemap_hash(key);
756
757 for (map = c->imagemaps[slot]; map != NULL; map = map->next) {
758 if (map->key != NULL && strcasecmp(map->key, key) == 0)
759 break;
760 }
761
762 if (map == NULL || map->list == NULL)
763 return NULL;
764
765 for (entry = map->list; entry; entry = entry->next) {
766 switch (entry->type) {
767 case IMAGEMAP_DEFAULT:
768 /* just return the URL. no checks required */
769 if (target)
770 *target = entry->target;
771 return entry->url;
772 break;
773 case IMAGEMAP_RECT:
774 if (click_x >= x + entry->bounds.rect.x0 &&
775 click_x <= x + entry->bounds.rect.x1 &&
776 click_y >= y + entry->bounds.rect.y0 &&
777 click_y <= y + entry->bounds.rect.y1) {
778 if (target)
779 *target = entry->target;
780 return entry->url;
781 }
782 break;
783 case IMAGEMAP_CIRCLE:
784 cx = x + entry->bounds.circle.x - click_x;
785 cy = y + entry->bounds.circle.y - click_y;
786 if ((cx * cx + cy * cy) <=
787 (unsigned long) (entry->bounds.circle.r *
788 entry->bounds.circle.r)) {
789 if (target)
790 *target = entry->target;
791 return entry->url;
792 }
793 break;
794 case IMAGEMAP_POLY:
796 entry->bounds.poly.xcoords,
797 entry->bounds.poly.ycoords, x, y,
798 click_x, click_y)) {
799 if (target)
800 *target = entry->target;
801 return entry->url;
802 }
803 break;
804 }
805 }
806
807 if (target)
808 *target = NULL;
809
810 return NULL;
811}
Box interface.
bool box_extract_link(const html_content *content, const dom_string *dsrel, nsurl *base, nsurl **result)
HTML Box tree construction interface.
Protected interface to Content handling.
Useful interned string pointers (interface).
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_DOM
DOM call returned error.
Definition: errors.h:52
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_OK
No error.
Definition: errors.h:30
High-level resource cache interface.
static bool imagemap_extract_map_entries(dom_node *node, html_content *c, struct mapentry **entry, dom_string *tname)
Extract an imagemap from html source.
Definition: imagemap.c:537
nsurl * imagemap_get(struct html_content *c, const char *key, unsigned long x, unsigned long y, unsigned long click_x, unsigned long click_y, const char **target)
Retrieve url associated with imagemap entry.
Definition: imagemap.c:737
void imagemap_dump(html_content *c)
Dump imagemap data to the log.
Definition: imagemap.c:231
static bool imagemap_extract_map(dom_node *node, html_content *c, struct mapentry **entry)
Extract an imagemap from html source.
Definition: imagemap.c:586
static unsigned int imagemap_hash(const char *key)
Hash function.
Definition: imagemap.c:109
static void imagemap_freelist(struct mapentry *list)
Free list of imagemap entries.
Definition: imagemap.c:169
static bool imagemap_add(html_content *c, dom_string *key, struct mapentry *list)
Add an imagemap to the hashtable, creating it if it doesn't exist.
Definition: imagemap.c:131
static bool imagemap_create(html_content *c)
Create hashtable of imagemaps.
Definition: imagemap.c:89
imagemap_entry_type
Definition: imagemap.c:45
@ IMAGEMAP_POLY
Definition: imagemap.c:49
@ IMAGEMAP_CIRCLE
Definition: imagemap.c:48
@ IMAGEMAP_DEFAULT
Definition: imagemap.c:46
@ IMAGEMAP_RECT
Definition: imagemap.c:47
void imagemap_destroy(html_content *c)
Destroy hashtable of imagemaps.
Definition: imagemap.c:200
nserror imagemap_extract(html_content *c)
Extract all imagemaps from a document tree.
Definition: imagemap.c:603
static bool imagemap_addtolist(const struct html_content *c, dom_node *n, nsurl *base_url, struct mapentry **entry, dom_string *tagtype)
Adds an imagemap entry to the list.
Definition: imagemap.c:303
#define HASH_SIZE
Definition: imagemap.c:43
static int imagemap_point_in_poly(int num, float *xpt, float *ypt, unsigned long x, unsigned long y, unsigned long click_x, unsigned long click_y)
Test if a point lies within an arbitrary polygon Modified from comp.graphics.algorithms FAQ 2....
Definition: imagemap.c:706
Interface to HTML imagemap.
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
Private data for text/html content.
Interface to utility string handling.
Data specific to CONTENT_HTML.
Definition: private.h:93
struct imagemap ** imagemaps
Hash table of imagemaps.
Definition: private.h:174
dom_document * document
Document tree.
Definition: private.h:101
struct nsurl * base_url
Base URL (may be a copy of content->url).
Definition: private.h:111
struct imagemap * next
next entry in this hash chain
Definition: imagemap.c:80
char * key
key for this entry
Definition: imagemap.c:78
struct mapentry * list
pointer to linked list of entries
Definition: imagemap.c:79
struct mapentry::@137::@138 circle
struct mapentry * next
next entry in list
Definition: imagemap.c:74
float * ycoords
y coordinates
Definition: imagemap.c:71
int num
number of points
Definition: imagemap.c:69
char * target
target frame (if any)
Definition: imagemap.c:55
int y0
top edge
Definition: imagemap.c:64
struct mapentry::@137::@139 rect
int y
y coordinate of center
Definition: imagemap.c:59
union mapentry::@137 bounds
int r
radius of circle
Definition: imagemap.c:60
float * xcoords
x coordinates
Definition: imagemap.c:70
imagemap_entry_type type
type of shape
Definition: imagemap.c:53
int x1
right hand edge
Definition: imagemap.c:65
nsurl * url
absolute url to go to
Definition: imagemap.c:54
struct mapentry::@137::@140 poly
int x
x coordinate of centre
Definition: imagemap.c:58
int y1
bottom edge
Definition: imagemap.c:66
int x0
left hand edge
Definition: imagemap.c:63