boost::optional<Geom::Point> Line::intersection_with_viewbox (SPDesktop *desktop) { Geom::Rect vb = desktop->get_display_area(); /* remaining viewbox corners */ Geom::Point ul (vb.min()[Geom::X], vb.max()[Geom::Y]); Geom::Point lr (vb.max()[Geom::X], vb.min()[Geom::Y]); std::pair <Geom::Point, Geom::Point> e = side_of_intersection (vb.min(), lr, vb.max(), ul, this->pt, this->v_dir); if (e.first == e.second) { // perspective line lies outside the canvas return boost::optional<Geom::Point>(); } Line line (e.first, e.second); return this->intersect (line); }
std::vector<Geom::Point> Layout::createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Affine const &transform) const { std::vector<Geom::Point> quads; unsigned char_index; unsigned end_char_index; if (it_start._char_index < it_end._char_index) { char_index = it_start._char_index; end_char_index = it_end._char_index; } else { char_index = it_end._char_index; end_char_index = it_start._char_index; } for ( ; char_index < end_char_index ; ) { if (_characters[char_index].in_glyph == -1) { char_index++; continue; } double char_rotation = _glyphs[_characters[char_index].in_glyph].rotation; unsigned span_index = _characters[char_index].in_span; Geom::Point top_left, bottom_right; if (_path_fitted || char_rotation != 0.0) { Geom::Rect box = characterBoundingBox(iterator(this, char_index), &char_rotation); top_left = box.min(); bottom_right = box.max(); char_index++; } else { // for straight text we can be faster by combining all the character boxes in a span into one box double span_x = _spans[span_index].x_start + _spans[span_index].chunk(this).left_x; top_left[Geom::X] = span_x + _characters[char_index].x; while (char_index < end_char_index && _characters[char_index].in_span == span_index) char_index++; if (char_index == _characters.size() || _characters[char_index].in_span != span_index) bottom_right[Geom::X] = _spans[span_index].x_end + _spans[span_index].chunk(this).left_x; else bottom_right[Geom::X] = span_x + _characters[char_index].x; double baseline_y = _spans[span_index].line(this).baseline_y + _spans[span_index].baseline_shift; double vertical_scale = _glyphs.back().vertical_scale; if (_directions_are_orthogonal(_blockProgression(), TOP_TO_BOTTOM)) { double span_height = vertical_scale * (_spans[span_index].line_height.ascent + _spans[span_index].line_height.descent); top_left[Geom::Y] = top_left[Geom::X]; top_left[Geom::X] = baseline_y - span_height * 0.5; bottom_right[Geom::Y] = bottom_right[Geom::X]; bottom_right[Geom::X] = baseline_y + span_height * 0.5; } else { top_left[Geom::Y] = baseline_y - vertical_scale * _spans[span_index].line_height.ascent; bottom_right[Geom::Y] = baseline_y + vertical_scale * _spans[span_index].line_height.descent; } } Geom::Rect char_box(top_left, bottom_right); if (char_box.dimensions()[Geom::X] == 0.0 || char_box.dimensions()[Geom::Y] == 0.0) continue; Geom::Point center_of_rotation((top_left[Geom::X] + bottom_right[Geom::X]) * 0.5, top_left[Geom::Y] + _spans[span_index].line_height.ascent); Geom::Affine total_transform = Geom::Translate(-center_of_rotation) * Geom::Rotate(char_rotation) * Geom::Translate(center_of_rotation) * transform; for(int i = 0; i < 4; i ++) quads.push_back(char_box.corner(i) * total_transform); } return quads; }
int main(int argc, char **argv) { char const *const filename = (argc >= 2 ? argv[1] : "toy.svgd"); FILE* f = fopen(filename, "r"); if (!f) { perror(filename); return 1; } display_path = read_svgd(f); Geom::Rect r = display_path.bbox(); display_path = display_path*Geom::translate(-r.min()); Geom::scale sc(r.max() - r.min()); display_path = display_path*(sc.inverse()*Geom::scale(500,500)); gtk_init (&argc, &argv); gdk_rgb_init(); GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "text toy"); gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, TRUE); gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event_cb), NULL); gtk_widget_push_visual(gdk_rgb_get_visual()); gtk_widget_push_colormap(gdk_rgb_get_cmap()); canvas = gtk_drawing_area_new(); gtk_signal_connect(GTK_OBJECT (canvas), "expose_event", GTK_SIGNAL_FUNC(expose_event), 0); gtk_widget_add_events(canvas, (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_POINTER_MOTION_MASK)); gtk_signal_connect(GTK_OBJECT (canvas), "button_press_event", GTK_SIGNAL_FUNC(mouse_event), 0); gtk_signal_connect(GTK_OBJECT (canvas), "button_release_event", GTK_SIGNAL_FUNC(mouse_release_event), 0); gtk_signal_connect(GTK_OBJECT (canvas), "motion_notify_event", GTK_SIGNAL_FUNC(mouse_motion_event), 0); gtk_signal_connect(GTK_OBJECT(canvas), "key_press_event", GTK_SIGNAL_FUNC(key_release_event), 0); gtk_widget_pop_colormap(); gtk_widget_pop_visual(); GtkWidget *vb = gtk_vbox_new(0, 0); gtk_container_add(GTK_CONTAINER(window), vb); gtk_box_pack_start(GTK_BOX(vb), canvas, TRUE, TRUE, 0); gtk_window_set_default_size(GTK_WINDOW(window), 600, 600); gtk_widget_show_all(window); dash_gc = gdk_gc_new(canvas->window); gint8 dash_list[] = {4, 4}; gdk_gc_set_dashes(dash_gc, 0, dash_list, 2); GdkColor colour; colour.red = 0xffff; colour.green = 0xffff; colour.blue = 0xffff; plain_gc = gdk_gc_new(canvas->window); //gdk_gc_set_rgb_fg_color(dash_gc, &colour); gdk_rgb_find_color(gtk_widget_get_colormap(canvas), &colour); gdk_window_set_background(canvas->window, &colour); gdk_gc_set_line_attributes(dash_gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT,GDK_JOIN_MITER); /* Make sure the canvas can receive key press events. */ GTK_WIDGET_SET_FLAGS(canvas, GTK_CAN_FOCUS); assert(GTK_WIDGET_CAN_FOCUS(canvas)); gtk_widget_grab_focus(canvas); assert(gtk_widget_is_focus(canvas)); gtk_main(); return 0; }