/* ...draw multiline string - hmm; need to put that stuff into display */ static inline void draw_string(cairo_t *cr, const char *fmt, ...) { char buffer[4096], *p, *end; cairo_text_extents_t text_extents; cairo_font_extents_t font_extents; va_list argp; cairo_save(cr); cairo_select_font_face(cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, 40); cairo_font_extents(cr, &font_extents); va_start(argp, fmt); vsnprintf(buffer, sizeof(buffer), fmt, argp); va_end(argp); for (p = buffer; *p; p = end + 1) { /* ...output single line */ ((end = strchr(p, '\n')) != NULL ? *end = 0 : 0); cairo_show_text(cr, p); cairo_text_extents (cr, p, &text_extents); cairo_rel_move_to (cr, -text_extents.x_advance, font_extents.height); TRACE(0, _b("print text-line: <%f,%f>"), text_extents.x_advance, font_extents.height); /* ...stop when last line processes */ if (!end) break; } /* ...restore drawing context */ cairo_restore(cr); }
void shoes_plot_draw_label(cairo_t *cr, shoes_plot *plot, int x, int y, char *str, int where) { // TODO: Font was previously set to Helvetica 12 and color was setup // keep them for now cairo_font_extents_t ft; // TODO: pangocairo way cairo_font_extents(cr, &ft); int str_h = (int) ceil(ft.height); PangoLayout *layout = pango_cairo_create_layout (cr); pango_layout_set_font_description (layout , plot->label_pfd); pango_layout_set_text (layout, str, -1); PangoRectangle ct; pango_layout_get_pixel_extents (layout, NULL, &ct); int str_w = ct.width; int newx = 0; int newy = 0; if (where == LEFT) { // left side y-axis newx = x - (str_w + 3) - 1 ; newy = y - (str_h / 2); } else if (where == RIGHT) { // right side y-axis newx = x; newy = y - (str_h / 2); //printf("lbl rightx: %i, y: %i, %s\n", (int)newx, (int)newy, str); } else if (where == BELOW) { // bottom side x axis newx = x - (str_w / 2); newy = y + (str_h / 2); } else { printf("FAIL: shoes_plot_draw_label 'where ?'\n"); } cairo_move_to(cr, newx, newy); pango_cairo_show_layout(cr, layout); g_object_unref(layout); // printf("TODO: shoes_plot_draw_label called\n"); }
static void gst_cairo_time_overlay_update_font_height (GstCairoTimeOverlay * timeoverlay) { gint width, height; cairo_surface_t *font_surface; cairo_t *font_cairo; cairo_font_extents_t font_extents; width = timeoverlay->width; height = timeoverlay->height; font_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); font_cairo = cairo_create (font_surface); cairo_surface_destroy (font_surface); font_surface = NULL; cairo_select_font_face (font_cairo, "monospace", 0, 0); cairo_set_font_size (font_cairo, 20); cairo_font_extents (font_cairo, &font_extents); timeoverlay->text_height = font_extents.height; GST_DEBUG_OBJECT (timeoverlay, "font height is %f", font_extents.height); cairo_destroy (font_cairo); font_cairo = NULL; }
static void draw (GtkWidget *drawing_area, cairo_t *cr, FT_Face face) { cairo_font_extents_t font_extents; gint *sizes = NULL, n_sizes, alpha_size, pos_y, i; const gchar *text; cairo_font_face_t *font; text = get_sample_string (face); sizes = build_sizes_table (face, &n_sizes, &alpha_size); font = cairo_ft_font_face_create_for_ft_face (face, 0); cairo_set_font_face (cr, font); cairo_font_extents (cr, &font_extents); cairo_font_face_destroy (font); /* draw text */ pos_y = MAX (font_extents.height, 32) + 4; cairo_set_font_size (cr, alpha_size); draw_string (cr, lowercase_text, &pos_y); draw_string (cr, uppercase_text, &pos_y); draw_string (cr, punctuation_text, &pos_y); pos_y += 8; for (i = 0; i < n_sizes; i++) { cairo_set_font_size (cr, sizes[i]); draw_string (cr, text, &pos_y); } g_free (sizes); }
static int ui_font_extents(lua_State *L) { struct context *c = lua_touserdata(L, 1); const char *str = lua_tostring(L, 2); cairo_font_extents_t te; cairo_font_extents(c->cr, &te); lua_newtable(L); lua_pushnumber(L, te.ascent); lua_setfield(L, -2, "ascent"); lua_pushnumber(L, te.descent); lua_setfield(L, -2, "descent"); lua_pushnumber(L, te.height); lua_setfield(L, -2, "height"); lua_pushnumber(L, te.max_x_advance); lua_setfield(L, -2, "max_x_advance"); lua_pushnumber(L, te.max_y_advance); lua_setfield(L, -2, "max_y_advance"); return 1; }
static void draw (cairo_t *cr, struct options *options) { cairo_text_extents_t extents; cairo_font_extents_t font_extents; cairo_select_font_face (cr, options->family, options->slant, options->weight); cairo_set_font_size (cr, options->size); cairo_text_extents (cr, options->text, &extents); cairo_translate (cr, options->PAD - extents.x_bearing, options->PAD - extents.y_bearing); cairo_font_extents (cr, &font_extents); cairo_rectangle (cr, 0, -font_extents.ascent, extents.x_advance, font_extents.height); cairo_move_to (cr, -options->PAD, 0); cairo_line_to (cr, extents.width + options->PAD, 0); cairo_set_source_rgba (cr, 1, 0, 0, .7); cairo_stroke (cr); cairo_rectangle (cr, extents.x_bearing, extents.y_bearing, extents.width, extents.height); cairo_set_source_rgba (cr, 0, 1, 0, .7); cairo_stroke (cr); cairo_move_to (cr, 0, 0); cairo_set_source_rgb (cr, 0, 0, 1); cairo_show_text (cr, options->text); cairo_fill (cr); }
static VALUE cr_font_extents (VALUE self) { cairo_font_extents_t extents; cairo_font_extents (_SELF, &extents); cr_check_status (_SELF); return CRFONTEXTENTS2RVAL (&extents); }
CAMLprim value ml_cairo_font_extents (value cr) { cairo_font_extents_t e; cairo_font_extents (cairo_t_val (cr), &e); check_cairo_status (cr); return Val_cairo_font_extents (&e); }
static int cr_font_extents (lua_State *L) { cairo_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_CONTEXT); cairo_font_extents_t extents; cairo_font_extents(*obj, &extents); create_lua_font_extents(L, &extents); return 1; }
double gt_graphics_cairo_get_text_height(GtGraphics *gg) { GtGraphicsCairo *g = gt_graphics_cairo_cast(gg); cairo_font_extents_t ext; gt_assert(g); cairo_font_extents(g->cr, &ext); return ext.height; }
static PyObject * pycairo_font_extents (PycairoContext *o) { cairo_font_extents_t e; cairo_font_extents (o->ctx, &e); RETURN_NULL_IF_CAIRO_CONTEXT_ERROR(o->ctx); return Py_BuildValue("(ddddd)", e.ascent, e.descent, e.height, e.max_x_advance, e.max_y_advance); }
static PyObject * pycairo_font_extents (PycairoContext *o) { cairo_font_extents_t e; cairo_font_extents (o->ctx, &e); if (Pycairo_Check_Status (cairo_status (o->ctx))) return NULL; return Py_BuildValue("(ddddd)", e.ascent, e.descent, e.height, e.max_x_advance, e.max_y_advance); }
static PyObject * _cairo_font_height(PyObject *self, PyObject *args) { cairo_t *cairo; cairo_font_extents_t fe; if (!PyArg_ParseTuple(args, "l", &cairo)) return NULL; cairo_font_extents(cairo, &fe); return Py_BuildValue("dd", fe.ascent, fe.descent); return Py_BuildValue("ii", (int)fe.ascent, (int)fe.descent); }
static void draw_coordinates(cairo_t *cr, double ox, double oy, GLfloat *x, GLfloat *y, int n) { char str[64]; int i; cairo_font_extents_t ext; cairo_font_extents(cr, &ext); for (i = 0; i < n; i++) { snprintf(str, 64, "%d: %14.9f, %14.9f", i, x[i], y[i]); cairo_move_to(cr, ox, oy + ext.height * (i + 1)); cairo_show_text(cr, str); } }
static int cairo_font_extents_l( lua_State* L ) { cairo_font_extents_t extents = {0}; lua_cairo_t* lc = lua_cairo_check( L, 1 ); cairo_font_extents( lc->cairo, &extents ); lua_pushnumber( L, extents.ascent ); lua_pushnumber( L, extents.descent ); lua_pushnumber( L, extents.height ); lua_pushnumber( L, extents.max_x_advance ); lua_pushnumber( L, extents.max_y_advance ); return( 5 ); }
OBFontMetrics CairoPainter::GetFontMetrics(const std::string &text) { cairo_font_extents_t fe; cairo_font_extents(m_cairo, &fe); cairo_text_extents_t te; cairo_text_extents(m_cairo, text.c_str(), &te); OBFontMetrics metrics; metrics.fontSize = m_fontPointSize; metrics.ascent = fe.ascent; metrics.descent = -fe.descent; metrics.width = te.x_advance;//te.width; metrics.height = te.height; return metrics; }
/** * Render an CairoFontTexture using this font. * **/ void CairoFont::RenderText(string s, IFontTextureResourcePtr texr, int x, int y) { CairoFontTexture* tex = dynamic_cast<CairoFontTexture*>(texr.get()); if (!tex) throw Exception("Font Texture not compatible with SDLFontResource."); cairo_t *tcr = tex->cr; cairo_text_extents_t te; cairo_font_extents_t fe; cairo_font_extents (tcr, &fe); cairo_set_operator (tcr, CAIRO_OPERATOR_OVER); cairo_set_source_rgb (tcr, colr[0], colr[1], colr[2]); cairo_select_font_face (tcr, filename.c_str(), slant, weight); cairo_set_font_size (tcr, ptsize); cairo_text_extents (tcr, s.c_str(), &te); cairo_move_to (tcr, x-te.x_bearing, y-te.y_bearing - fe.descent+fe.height/2); cairo_show_text (tcr, s.c_str()); tex->FireChangedEvent(0, 0, tex->width, tex->height); }
static cairo_status_t test_scaled_font_init (cairo_scaled_font_t *scaled_font, cairo_t *cr, cairo_font_extents_t *extents) { cairo_set_font_face (cr, cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font), &fallback_font_key)); cairo_scaled_font_set_user_data (scaled_font, &fallback_font_key, cairo_scaled_font_reference (cairo_get_scaled_font (cr)), (cairo_destroy_func_t) cairo_scaled_font_destroy); cairo_font_extents (cr, extents); return CAIRO_STATUS_SUCCESS; }
static void draw_string(cairo_t *cr, const char *fmt, ...) { char buffer[4096]; char *p, *end; va_list argp; cairo_text_extents_t text_extents; cairo_font_extents_t font_extents; cairo_save(cr); cairo_select_font_face(cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, 14); cairo_font_extents (cr, &font_extents); va_start(argp, fmt); vsnprintf(buffer, sizeof(buffer), fmt, argp); p = buffer; while (*p) { end = strchr(p, '\n'); if (end) *end = 0; cairo_show_text(cr, p); cairo_text_extents (cr, p, &text_extents); cairo_rel_move_to (cr, -text_extents.x_advance, font_extents.height); if (end) p = end + 1; else break; } va_end(argp); cairo_restore(cr); }
/* adapted from gnome-utils:font-viewer/font-view.c * * Copyright (C) 2002-2003 James Henstridge <*****@*****.**> * Copyright (C) 2010 Cosimo Cecchi <*****@*****.**> * * License: GPLv2+ */ static void draw_string (SushiFontWidget *self, cairo_t *cr, GtkBorder padding, const gchar *text, gint *pos_y) { cairo_font_extents_t font_extents; cairo_text_extents_t extents; cairo_glyph_t *glyphs; GtkTextDirection text_dir; gint pos_x; gint num_glyphs; gint i; text_dir = gtk_widget_get_direction (GTK_WIDGET (self)); text_to_glyphs (cr, text, &glyphs, &num_glyphs); cairo_font_extents (cr, &font_extents); cairo_glyph_extents (cr, glyphs, num_glyphs, &extents); if (pos_y != NULL) *pos_y += font_extents.ascent + font_extents.descent + extents.y_advance + LINE_SPACING / 2; if (text_dir == GTK_TEXT_DIR_LTR) pos_x = padding.left; else { pos_x = gtk_widget_get_allocated_width (GTK_WIDGET (self)) - extents.x_advance - padding.right; } for (i = 0; i < num_glyphs; i++) { glyphs[i].x += pos_x; glyphs[i].y += *pos_y; } cairo_move_to (cr, pos_x, *pos_y); cairo_show_glyphs (cr, glyphs, num_glyphs); g_free (glyphs); *pos_y += LINE_SPACING / 2; }
static void * draw_thread (void *arg) { const char *text = "Hello world. "; thread_data_t *thread_data = arg; cairo_surface_t *surface; cairo_font_extents_t extents; cairo_t *cr; int i; cr = cairo_create (thread_data->target); cairo_surface_destroy (thread_data->target); cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); cairo_set_source_rgb (cr, 0, 0, 0); cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, NUM_ITERATIONS); cairo_font_extents (cr, &extents); cairo_move_to (cr, 1, HEIGHT - extents.descent - 1); for (i = 0; i < NUM_ITERATIONS; i++) { char buf[2]; cairo_select_font_face (cr, CAIRO_TEST_FONT_FAMILY " Serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size (cr, i); buf[0] = text[i%strlen(text)]; buf[1] = '\0'; cairo_show_text (cr, buf); } surface = cairo_surface_reference (cairo_get_target (cr)); cairo_destroy (cr); return surface; }
/* Experimental - Currently messes up the display if larger then 12 point Monospace */ void set_cairo_font_size(cairo_t *cr, font_info *font) { double size; cairo_font_extents_t extents; cairo_text_extents_t text_extents; cairo_select_font_face(cr, font->family, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); size = font->size * (96.0/72.0); cairo_set_font_size(cr, size); cairo_font_extents(cr, &extents); cairo_text_extents(cr, "@", &text_extents); font->w = extents.max_x_advance; font->h = extents.height; font->descent = extents.descent; }
/** * Convert a unit array to a C array of doubles representing NPC values. */ static void unit_array_to_npc(double *result, grid_context_t *gr, char dim, const unit_array_t *u) { grid_viewport_node_t *node = gr->current_node; double dev_x_per_npc, dev_y_per_npc; dev_x_per_npc = dev_y_per_npc = 1.0; cairo_matrix_transform_distance(node->npc_to_dev, &dev_x_per_npc, &dev_y_per_npc); double x_ntv, y_ntv, w_ntv, h_ntv; x_ntv = y_ntv = 0.0; w_ntv = h_ntv = 1.0; cairo_matrix_transform_point(node->npc_to_ntv, &x_ntv, &y_ntv); cairo_matrix_transform_distance(node->npc_to_ntv, &w_ntv, &h_ntv); cairo_font_extents_t font_extents; cairo_font_extents(gr->cr, &font_extents); cairo_text_extents_t em_extents; cairo_text_extents(gr->cr, "m", &em_extents); double dev_per_npc, o_ntv, size_ntv; dev_per_npc = o_ntv = size_ntv = 0.0; if (dim == 'x') { dev_per_npc = dev_x_per_npc; o_ntv = x_ntv; size_ntv = w_ntv; } else if (dim == 'y') { dev_per_npc = dev_y_per_npc; o_ntv = y_ntv; size_ntv = h_ntv; } else { fprintf(stderr, "Warning: unknown dimension '%c'\n", dim); } unit_array_to_npc_helper(result, dev_per_npc, font_extents.height, em_extents.width, o_ntv, size_ntv, unit_array_size(u), u); }
void StringSizeWithContextReal(cairo_t * c, const char *str, int* w, int* h) { if (!str || str[0] == 0) { if (w) *w = 0; if (h) *h = 0; return; } if (!fcitx_utf8_check_string(str)) { if (w) *w = 0; if (h) *h = 0; return; } cairo_text_extents_t extents; cairo_font_extents_t fontextents; cairo_text_extents(c, str, &extents); cairo_font_extents(c, &fontextents); if (w) *w = extents.x_advance; if (h) *h = fontextents.height; }
static cairo_test_status_t check_font_extents (const cairo_test_context_t *ctx, cairo_t *cr, const char *comment) { cairo_font_extents_t font_extents, ref_font_extents = {11, 2, 13, 6, 0}; cairo_status_t status; memset (&font_extents, 0xff, sizeof (cairo_font_extents_t)); cairo_font_extents (cr, &font_extents); status = cairo_status (cr); if (status) return cairo_test_status_from_status (ctx, status); if (! font_extents_equal (&font_extents, &ref_font_extents)) { cairo_test_log (ctx, "Error: %s: cairo_font_extents(); extents (%g, %g, %g, %g, %g)\n", comment, font_extents.ascent, font_extents.descent, font_extents.height, font_extents.max_x_advance, font_extents.max_y_advance); return CAIRO_TEST_FAILURE; } return CAIRO_TEST_SUCCESS; }
int tasklist_paint_task(wtk_widget_t *w, cairo_t *context, clara_wndlist_e_t *wnd, int x) { cairo_font_face_t *face = wtk_get_normal_font(); cairo_font_extents_t fe; cairo_text_extents_t te; int t_x, t_y, t_h, t_w; t_w = w->rect.w; t_h = w->rect.h; cairo_set_font_face(context, face); cairo_set_font_size(context, 16); cairo_font_extents (context, &fe); cairo_text_extents (context, wnd->title, &te); t_x = x + 5; t_y = (t_h / 2) - (te.height / 2); if (wnd->focused) { cairo_rectangle(context, x, 2, te.width + 10, t_h - 4); cairo_set_source_rgb(context, 0.3, 0.3, 1); cairo_fill(context); } cairo_move_to (context, te.x_bearing + t_x + 1, t_y - te.y_bearing + 1); cairo_set_source_rgb (context, 0, 0, 0); cairo_show_text (context, wnd->title); cairo_move_to (context, te.x_bearing + t_x, t_y - te.y_bearing); cairo_set_source_rgb (context, 1, 1, 1); cairo_show_text (context, wnd->title); return te.width + 10; }
/* Set 'width' and 'height' (either can be NULL), and set values for other constants */ static void timing_dia_get_size(struct vgpu_compute_unit_t *compute_unit, int *width, int *height) { GdkWindow *window; cairo_t *cr; int widget_width; int widget_height; widget_width = gtk_widget_get_allocated_width(compute_unit->timing_dia_area); widget_height = gtk_widget_get_allocated_height(compute_unit->timing_dia_area); window = gtk_widget_get_window(compute_unit->timing_dia_area); cr = gdk_cairo_create(window); cairo_font_extents(cr, &timing_dia_font_extents); timing_dia_col_width = timing_dia_font_extents.max_x_advance * 4; timing_dia_row_height = timing_dia_font_extents.ascent + timing_dia_font_extents.descent; if (height) *height = widget_height / timing_dia_row_height + 2; if (width) *width = widget_width / timing_dia_col_width + 2; cairo_destroy(cr); }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); FcPattern *pattern; cairo_font_face_t *font_face; cairo_font_extents_t font_extents; cairo_font_options_t *font_options; cairo_status_t status; char *filename; int face_count; struct stat stat_buf; xasprintf (&filename, "%s/%s", ctx->srcdir, FONT); if (stat (filename, &stat_buf) || ! S_ISREG (stat_buf.st_mode)) { cairo_test_log (ctx, "Error finding font: %s: file not found?\n", filename); return CAIRO_TEST_FAILURE; } pattern = FcFreeTypeQuery ((unsigned char *)filename, 0, NULL, &face_count); free (filename); if (! pattern) { cairo_test_log (ctx, "FcFreeTypeQuery failed.\n"); return cairo_test_status_from_status (ctx, CAIRO_STATUS_NO_MEMORY); } font_face = cairo_ft_font_face_create_for_pattern (pattern); FcPatternDestroy (pattern); status = cairo_font_face_status (font_face); if (status) { cairo_test_log (ctx, "Error creating font face for %s: %s\n", filename, cairo_status_to_string (status)); return cairo_test_status_from_status (ctx, status); } if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_FT) { cairo_test_log (ctx, "Unexpected value from cairo_font_face_get_type: %d (expected %d)\n", cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_FT); cairo_font_face_destroy (font_face); return CAIRO_TEST_FAILURE; } cairo_set_font_face (cr, font_face); cairo_font_face_destroy (font_face); font_options = cairo_font_options_create (); #define CHECK_FONT_EXTENTS(comment) do {\ cairo_test_status_t test_status; \ test_status = check_font_extents (ctx, cr, (comment)); \ if (test_status != CAIRO_TEST_SUCCESS) { \ cairo_font_options_destroy (font_options); \ return test_status; \ } \ } while (0) cairo_font_extents (cr, &font_extents); CHECK_FONT_EXTENTS ("default"); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON"); cairo_move_to (cr, 1, font_extents.ascent - 1); cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */ cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_NONE"); cairo_show_text (cr, "the "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_SLIGHT"); cairo_show_text (cr, "quick "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_MEDIUM"); cairo_show_text (cr, "brown"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_ON HINT_STYLE_FULL"); cairo_show_text (cr, " fox"); /* Switch from show_text to text_path/fill to exercise bug #7889 */ cairo_text_path (cr, " jumps over a lazy dog"); cairo_fill (cr); /* And test it rotated as well for the sake of bug #7888 */ cairo_translate (cr, width, height); cairo_rotate (cr, M_PI); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_DEFAULT); cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF"); cairo_move_to (cr, 1, font_extents.height - font_extents.descent - 1); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_NONE"); cairo_show_text (cr, "the "); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_SLIGHT); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_SLIGHT"); cairo_show_text (cr, "quick"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_MEDIUM); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_MEDIUM"); cairo_show_text (cr, " brown"); cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_FULL); cairo_set_font_options (cr, font_options); CHECK_FONT_EXTENTS ("HINT_METRICS_OFF HINT_STYLE_FULL"); cairo_show_text (cr, " fox"); cairo_text_path (cr, " jumps over"); cairo_text_path (cr, " a lazy dog"); cairo_fill (cr); cairo_font_options_destroy (font_options); return CAIRO_TEST_SUCCESS; }
/*================================================================================== pstext - subroutine to output text strings. x, y - coordinates of the label's reference point, in real coordinates (but see valign and halign, below) text - character string to be output jchar - length of meaningful character string, 0 if unknown. textlen - automatic argument supplied by fortran, gives allocated length of string valign: integer alignment code for vertical (from possibly rotated character standpoint) alignment. 0 = top-aligned 1 = middle-aligned 2 = bottom-aligned 10-12 = y should be considered a number of lines from top margin of page, then alignment=valign-10 100-902 = valign is given by the final digit. The y-coordinate should be calculated based upon the given y, but then add a number of lines to move down the page from there given by this code/100 (e.g., 1-9 lines) 1000-9002 = valign is given by the final digit. The y-coordinate should be calculated based upon the given y, but then add a number of lines to move up the page from there given by this code/1000 (e.g., 1-9 lines) (e.g., 202 would mean that the text should be bottom-aligned to the reference point, and the y coordinate is two lines below the supplied y coordinate halign: integer alignment code for horizontal (from possibly rotated character standpoint) alignment. 0 = left-aligned 1 = center-aligned 2 = right-aligned 10-12 = x should be considered a number of lines from left margin of page, then alignment=halign-10 100-9002 = halign is given by the final digit. The x coordinate should be calculated based upon the given x, but add a number of points given by this code / 100 (e.g., 1-90). REFERENCE_TO_TRACKED_MIN_X - REFERENCE_TO_TRACKED_MIN_X+2 = halign is given by the final digit. The x coordinate to be used is the tracked minimum x. ==================================================================================*/ void pstext_ (double *x, double *y, char *text, int *jchar, int *valign, int *halign, int textlen) { cairo_text_extents_t te; cairo_font_extents_t fe; cairo_matrix_t curMatrix; double userX, userY; double tempX, tempY; int valignCode, halignCode; int linesToMove = 0; double pointsToMove = 0; double xOffset = 0; double yOffset = 0; char *temptext=malloc(255 * sizeof(char)); char *mytext; strncpy(temptext, text, 254); /* copy only as many characters as will fit in value */ if (*jchar == 0) { temptext[textlen]='\0'; } else { temptext[*jchar]='\0'; } mytext = trim(temptext); compressSpaces(mytext); completeRelativeOperation(); DEBUGPRINT(("In pstext. Pt=(%f, %f), DevPoint=(%f, %f), Text=%s, jchar=%i, textlen=%i, valign=%i, halign=%i.\n", *x, *y, deviceX(*x), deviceY(*y), mytext, *jchar, textlen, *valign, *halign)); cairo_text_extents(dmh_cr,mytext,&te); cairo_font_extents (dmh_cr, &fe); cairo_set_source_rgb (dmh_cr, 0, 0, 0); /* black */ userX = deviceX(*x); /* change coordinates from real to device */ userY = deviceY(*y); if (dmh_debug) { tempX = userX; tempY = userY; cairo_device_to_user(dmh_cr, &tempX, &tempY); /* need this to deal with possibly rotated transform */ cairo_rectangle(dmh_cr, tempX-4, tempY-4, 8, 8); cairo_set_source_rgb (dmh_cr, 1, 0.5, 0); cairo_fill(dmh_cr); cairo_set_source_rgb (dmh_cr, 0, 0, 0); cairo_move_to(dmh_cr, tempX, tempY); } DEBUGPRINT(("In pstext. UserPt=(%f, %f) tempPt=(%f, %f).\n", userX, userY, tempX, tempY)); if (*valign > 9 && *valign < 100) { /* y should be considered a number of lines from top of page. Note that cairo thinks the origin is at top-left */ userY = TOPMARGIN + ((int)*y * fe.height); } else if (*valign > 99 && *valign < 1000) { linesToMove = *valign / 100; } else if (*valign > 990 && *valign < 10000) { linesToMove = -(*valign / 1000); } DEBUGPRINT(("In pstext. LinesToMove=%i.\n", linesToMove)); if (*halign > 9 && *halign < 100) { /* x should be considered a number of lines from top of page. Note that cairo thinks the origin is at top-left */ userX = LEFTMARGIN + ((int)*x * fe.height); } else if (*halign > 99 && *halign < 10000) { pointsToMove = (*halign)/100; } else if (*halign >= REFERENCE_TO_TRACKED_MIN_X && *halign <= REFERENCE_TO_TRACKED_MIN_X+2) { userX = dmh_min_tracked_x; dmh_min_tracked_x = DBL_MAX; /* Now turn off tracking */ dmh_track_min_x = 0; } DEBUGPRINT(("In pstext. UserPt=(%f, %f).\n", userX, userY)); cairo_device_to_user(dmh_cr, &userX, &userY); /* need this to deal with possibly rotated transform */ cairo_move_to(dmh_cr, userX, userY); if (linesToMove != 0) { cairo_rel_move_to(dmh_cr, 0, linesToMove * fe.height); } if (pointsToMove != 0) { cairo_rel_move_to(dmh_cr, pointsToMove, 0); } if (dmh_debug) { cairo_get_current_point(dmh_cr, &tempX, &tempY); cairo_rectangle(dmh_cr, tempX-2, tempY-2, 4, 4); cairo_set_source_rgb (dmh_cr, 0, 0.5, 1); cairo_fill(dmh_cr); cairo_set_source_rgb (dmh_cr, 0, 0, 0); cairo_move_to(dmh_cr, tempX, tempY); } valignCode = *valign % 10; halignCode = *halign % 10; switch (valignCode) { case 0: /* Top-aligned */ yOffset = te.height + EXTRASPACEPTS; break; case 1: /* Middle-aligned */ yOffset = te.height * 0.5; break; case 2: /* Bottom-aligned */ yOffset = -EXTRASPACEPTS; break; } switch (halignCode) { case 0: /* Left-aligned */ xOffset = EXTRASPACEPTS; break; case 1: /* Center-aligned */ xOffset = -te.width * 0.5; break; case 2: /* Right-aligned */ xOffset = -te.width - EXTRASPACEPTS; break; } DEBUGPRINT(("In pstext. Offset=(%f, %f).\n", xOffset, yOffset)); cairo_rel_move_to(dmh_cr, xOffset, yOffset); if (dmh_debug) { cairo_get_current_point(dmh_cr, &tempX, &tempY); cairo_rectangle(dmh_cr, tempX-2, tempY-2, 4, 4); cairo_set_source_rgb (dmh_cr, 1, 0, 0.5); cairo_fill(dmh_cr); cairo_set_source_rgb (dmh_cr, 0, 0, 0); cairo_move_to(dmh_cr, tempX, tempY); } cairo_get_matrix(dmh_cr, &curMatrix); DEBUGPRINT(("Current matrix: %f, %f, %f, %f, %f, %f.\n", curMatrix.xx, curMatrix.yx, curMatrix.xy, curMatrix.yy, curMatrix.x0, curMatrix.y0)); if (dmh_track_min_x) { cairo_get_current_point(dmh_cr, &tempX, &tempY); if (tempX < dmh_min_tracked_x) { dmh_min_tracked_x = tempX; } } cairo_show_text (dmh_cr, mytext); DEBUGPRINT(("Status:%s\n",cairo_status_to_string(cairo_status(dmh_cr)))); free(temptext); }
int main(int argc, char** args) { int c; char* wcsfn = NULL; char* outfn = NULL; char* infn = NULL; sip_t sip; double scale = 1.0; anbool pngformat = TRUE; char* hdpath = NULL; anbool HD = FALSE; cairos_t thecairos; cairos_t* cairos = &thecairos; cairo_surface_t* target = NULL; cairo_t* cairot = NULL; cairo_surface_t* surfbg = NULL; cairo_t* cairobg = NULL; cairo_surface_t* surfshapes = NULL; cairo_t* cairoshapes = NULL; cairo_surface_t* surfshapesmask = NULL; cairo_t* cairoshapesmask = NULL; cairo_surface_t* surffg = NULL; cairo_t* cairo = NULL; double lw = 2.0; // circle linewidth. double cw = 2.0; double ngc_fraction = 0.02; // NGC linewidth double nw = 2.0; // leave a gap short of connecting the points. double endgap = 5.0; // circle radius. double crad = endgap; double fontsize = 14.0; double label_offset = 15.0; int W = 0, H = 0; unsigned char* img = NULL; anbool NGC = FALSE, constell = FALSE; anbool bright = FALSE; anbool common_only = FALSE; anbool print_common_only = FALSE; int Nbright = 0; double ra, dec, px, py; int i, N; anbool justlist = FALSE; anbool only_messier = FALSE; anbool grid = FALSE; double gridspacing = 0.0; double gridcolor[3] = { 0.2, 0.2, 0.2 }; int loglvl = LOG_MSG; char halign = 'L'; char valign = 'C'; sl* json = NULL; anbool whitetext = FALSE; while ((c = getopt(argc, args, OPTIONS)) != -1) { switch (c) { case 'V': valign = optarg[0]; break; case 'O': halign = optarg[0]; break; case 'F': ngc_fraction = atof(optarg); break; case 'h': print_help(args[0]); exit(0); case 'J': json = sl_new(4); break; case 'G': gridspacing = atof(optarg); break; case 'g': { char *tail = NULL; gridcolor[0] = strtod(optarg,&tail); if (*tail) { tail++; gridcolor[1] = strtod(tail,&tail); } if (*tail) { tail++; gridcolor[2] = strtod(tail,&tail); } } break; case 'D': HD = TRUE; break; case 'd': hdpath = optarg; break; case 'M': only_messier = TRUE; break; case 'n': nw = atof(optarg); break; case 'f': fontsize = atof(optarg); break; case 'L': justlist = TRUE; outfn = NULL; break; case 'x': whitetext = TRUE; break; case 'v': loglvl++; break; break; case 'j': print_common_only = TRUE; break; case 'c': common_only = TRUE; break; case 'b': Nbright = atoi(optarg); break; case 'B': bright = TRUE; break; case 'N': NGC = TRUE; break; case 'C': constell = TRUE; break; case 'p': pngformat = FALSE; break; case 's': scale = atof(optarg); break; case 'o': outfn = optarg; break; case 'i': infn = optarg; break; case 'w': wcsfn = optarg; break; case 'W': W = atoi(optarg); break; case 'H': H = atoi(optarg); break; } } log_init(loglvl); log_to(stderr); fits_use_error_system(); if (optind != argc) { print_help(args[0]); exit(-1); } if (!(outfn || justlist) || !wcsfn) { logerr("Need (-o or -L) and -w args.\n"); print_help(args[0]); exit(-1); } // read WCS. logverb("Trying to parse SIP/TAN header from %s...\n", wcsfn); if (!file_exists(wcsfn)) { ERROR("No such file: \"%s\"", wcsfn); exit(-1); } if (sip_read_header_file(wcsfn, &sip)) { logverb("Got SIP header.\n"); } else { ERROR("Failed to parse SIP/TAN header from %s", wcsfn); exit(-1); } if (!(NGC || constell || bright || HD || grid)) { logerr("Neither constellations, bright stars, HD nor NGC/IC overlays selected!\n"); print_help(args[0]); exit(-1); } if (gridspacing > 0.0) grid = TRUE; // adjust for scaling... lw /= scale; cw /= scale; nw /= scale; crad /= scale; endgap /= scale; fontsize /= scale; label_offset /= scale; if (!W || !H) { W = sip.wcstan.imagew; H = sip.wcstan.imageh; } if (!(infn || (W && H))) { logerr("Image width/height unspecified, and no input image given.\n"); exit(-1); } if (infn) { cairoutils_fake_ppm_init(); img = cairoutils_read_ppm(infn, &W, &H); if (!img) { ERROR("Failed to read input image %s", infn); exit(-1); } cairoutils_rgba_to_argb32(img, W, H); } else if (!justlist) { // Allocate a black image. img = calloc(4 * W * H, 1); if (!img) { SYSERROR("Failed to allocate a blank image on which to plot!"); exit(-1); } } if (HD && !hdpath) { logerr("If you specify -D (plot Henry Draper objs), you also have to give -d (path to Henry Draper catalog)\n"); exit(-1); } if (!justlist) { /* Cairo layers: -background: surfbg / cairobg --> gets drawn first, in black, masked by surfshapesmask -shapes: surfshapes / cairoshapes --> gets drawn second, masked by surfshapesmask -foreground/text: surffg / cairo --> gets drawn last. */ surffg = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, W, H); cairo = cairo_create(surffg); cairo_set_line_join(cairo, CAIRO_LINE_JOIN_BEVEL); cairo_set_antialias(cairo, CAIRO_ANTIALIAS_GRAY); cairo_set_source_rgba(cairo, 1.0, 1.0, 1.0, 1.0); cairo_scale(cairo, scale, scale); //cairo_select_font_face(cairo, "helvetica", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_select_font_face(cairo, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(cairo, fontsize); surfshapes = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, W, H); cairoshapes = cairo_create(surfshapes); cairo_set_line_join(cairoshapes, CAIRO_LINE_JOIN_BEVEL); cairo_set_antialias(cairoshapes, CAIRO_ANTIALIAS_GRAY); cairo_set_source_rgba(cairoshapes, 1.0, 1.0, 1.0, 1.0); cairo_scale(cairoshapes, scale, scale); cairo_select_font_face(cairoshapes, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(cairoshapes, fontsize); surfshapesmask = cairo_image_surface_create(CAIRO_FORMAT_A8, W, H); cairoshapesmask = cairo_create(surfshapesmask); cairo_set_line_join(cairoshapesmask, CAIRO_LINE_JOIN_BEVEL); cairo_set_antialias(cairoshapesmask, CAIRO_ANTIALIAS_GRAY); cairo_set_source_rgba(cairoshapesmask, 1.0, 1.0, 1.0, 1.0); cairo_scale(cairoshapesmask, scale, scale); cairo_select_font_face(cairoshapesmask, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(cairoshapesmask, fontsize); cairo_paint(cairoshapesmask); cairo_stroke(cairoshapesmask); surfbg = cairo_image_surface_create(CAIRO_FORMAT_A8, W, H); cairobg = cairo_create(surfbg); cairo_set_line_join(cairobg, CAIRO_LINE_JOIN_BEVEL); cairo_set_antialias(cairobg, CAIRO_ANTIALIAS_GRAY); cairo_set_source_rgba(cairobg, 0, 0, 0, 1); cairo_scale(cairobg, scale, scale); cairo_select_font_face(cairobg, "DejaVu Sans Mono Book", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size(cairobg, fontsize); cairos->bg = cairobg; cairos->fg = cairo; cairos->shapes = cairoshapes; cairos->shapesmask = cairoshapesmask; cairos->imgW = (float)W/scale; cairos->imgH = (float)H/scale; // } if (grid) { double ramin, ramax, decmin, decmax; double ra, dec; double rastep = gridspacing / 60.0; double decstep = gridspacing / 60.0; // how many line segments int N = 10; double px, py; int i; cairo_set_source_rgba(cairo, gridcolor[0], gridcolor[1], gridcolor[2], 1.0); sip_get_radec_bounds(&sip, 100, &ramin, &ramax, &decmin, &decmax); logverb("Plotting grid lines from RA=%g to %g in steps of %g; Dec=%g to %g in steps of %g\n", ramin, ramax, rastep, decmin, decmax, decstep); for (dec = decstep * floor(decmin / decstep); dec<=decmax; dec+=decstep) { logverb(" dec=%g\n", dec); for (i=0; i<=N; i++) { ra = ramin + ((double)i / (double)N) * (ramax - ramin); if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py)) continue; // first time, move_to; else line_to ((ra == ramin) ? cairo_move_to : cairo_line_to)(cairo, px, py); } cairo_stroke(cairo); } for (ra = rastep * floor(ramin / rastep); ra <= ramax; ra += rastep) { //for (dec=decmin; dec<=decmax; dec += (decmax - decmin)/(double)N) { logverb(" ra=%g\n", ra); for (i=0; i<=N; i++) { dec = decmin + ((double)i / (double)N) * (decmax - decmin); if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py)) continue; // first time, move_to; else line_to ((dec == decmin) ? cairo_move_to : cairo_line_to)(cairo, px, py); } cairo_stroke(cairo); } cairo_set_source_rgba(cairo, 1.0, 1.0, 1.0, 1.0); } } if (constell) { N = constellations_n(); logverb("Checking %i constellations.\n", N); for (c=0; c<N; c++) { const char* shortname = NULL; const char* longname; il* lines; il* uniqstars; il* inboundstars; float r,g,b; int Ninbounds; int Nunique; cairo_text_extents_t textents; double cmass[3]; uniqstars = constellations_get_unique_stars(c); inboundstars = il_new(16); Nunique = il_size(uniqstars); debug("%s: %zu unique stars.\n", shortname, il_size(uniqstars)); // Count the number of unique stars belonging to this contellation // that are within the image bounds Ninbounds = 0; for (i=0; i<il_size(uniqstars); i++) { int star; star = il_get(uniqstars, i); constellations_get_star_radec(star, &ra, &dec); debug("star %i: ra,dec (%g,%g)\n", il_get(uniqstars, i), ra, dec); if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py)) continue; if (px < 0 || py < 0 || px*scale > W || py*scale > H) continue; Ninbounds++; il_append(inboundstars, star); } il_free(uniqstars); debug("%i are in-bounds.\n", Ninbounds); // Only draw this constellation if at least 2 of its stars // are within the image bounds. if (Ninbounds < 2) { il_free(inboundstars); continue; } // Set the color based on the location of the first in-bounds star. // This is a hack -- we have two different constellation // definitions with different numbering schemes! if (!justlist && (il_size(inboundstars) > 0)) { // This is helpful for videos: ensuring that the same // color is chosen for a constellation in each frame. int star = il_get(inboundstars, 0); constellations_get_star_radec(star, &ra, &dec); if (whitetext) { r = g = b = 1; } else { color_for_radec(ra, dec, &r, &g, &b); } cairo_set_source_rgba(cairoshapes, r,g,b,0.8); cairo_set_line_width(cairoshapes, cw); cairo_set_source_rgba(cairo, r,g,b,0.8); cairo_set_line_width(cairo, cw); } // Draw circles around each star. // Find center of mass (of the in-bounds stars) cmass[0] = cmass[1] = cmass[2] = 0.0; for (i=0; i<il_size(inboundstars); i++) { double xyz[3]; int star = il_get(inboundstars, i); constellations_get_star_radec(star, &ra, &dec); if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py)) continue; if (px < 0 || py < 0 || px*scale > W || py*scale > H) continue; if (!justlist) { cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI); cairo_stroke(cairobg); cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI); cairo_stroke(cairoshapes); } radecdeg2xyzarr(ra, dec, xyz); cmass[0] += xyz[0]; cmass[1] += xyz[1]; cmass[2] += xyz[2]; } cmass[0] /= il_size(inboundstars); cmass[1] /= il_size(inboundstars); cmass[2] /= il_size(inboundstars); xyzarr2radecdeg(cmass, &ra, &dec); il_free(inboundstars); if (!sip_radec2pixelxy(&sip, ra, dec, &px, &py)) continue; shortname = constellations_get_shortname(c); longname = constellations_get_longname(c); assert(shortname && longname); logverb("%s at (%g, %g)\n", longname, px, py); if (Ninbounds == Nunique) { printf("The constellation %s (%s)\n", longname, shortname); } else { printf("Part of the constellation %s (%s)\n", longname, shortname); } if (justlist) continue; // If the label will be off-screen, move it back on. cairo_text_extents(cairo, shortname, &textents); if (px < 0) px = 0; if (py < textents.height) py = textents.height; if ((px + textents.width)*scale > W) px = W/scale - textents.width; if ((py+textents.height)*scale > H) py = H/scale - textents.height; logverb("%s at (%g, %g)\n", shortname, px, py); add_text(cairos, longname, px, py, halign, valign); // Draw the lines. cairo_set_line_width(cairo, lw); lines = constellations_get_lines(c); for (i=0; i<il_size(lines)/2; i++) { int star1, star2; double ra1, dec1, ra2, dec2; double px1, px2, py1, py2; double dx, dy; double dist; double gapfrac; star1 = il_get(lines, i*2+0); star2 = il_get(lines, i*2+1); constellations_get_star_radec(star1, &ra1, &dec1); constellations_get_star_radec(star2, &ra2, &dec2); if (!sip_radec2pixelxy(&sip, ra1, dec1, &px1, &py1) || !sip_radec2pixelxy(&sip, ra2, dec2, &px2, &py2)) continue; dx = px2 - px1; dy = py2 - py1; dist = hypot(dx, dy); gapfrac = endgap / dist; cairo_move_to(cairoshapes, px1 + dx*gapfrac, py1 + dy*gapfrac); cairo_line_to(cairoshapes, px1 + dx*(1.0-gapfrac), py1 + dy*(1.0-gapfrac)); cairo_stroke(cairoshapes); } il_free(lines); } logverb("done constellations.\n"); } if (bright) { double dy = 0; cairo_font_extents_t extents; pl* brightstars = pl_new(16); if (!justlist) { cairo_set_source_rgba(cairoshapes, 0.75, 0.75, 0.75, 0.8); cairo_font_extents(cairo, &extents); dy = extents.ascent * 0.5; cairo_set_line_width(cairoshapes, cw); } N = bright_stars_n(); logverb("Checking %i bright stars.\n", N); for (i=0; i<N; i++) { const brightstar_t* bs = bright_stars_get(i); if (!sip_radec2pixelxy(&sip, bs->ra, bs->dec, &px, &py)) continue; if (px < 0 || py < 0 || px*scale > W || py*scale > H) continue; if (!(bs->name && strlen(bs->name))) continue; if (common_only && !(bs->common_name && strlen(bs->common_name))) continue; if (strcmp(bs->common_name, "Maia") == 0) continue; pl_append(brightstars, bs); } // keep only the Nbright brightest? if (Nbright && (pl_size(brightstars) > Nbright)) { pl_sort(brightstars, sort_by_mag); pl_remove_index_range(brightstars, Nbright, pl_size(brightstars)-Nbright); } for (i=0; i<pl_size(brightstars); i++) { char* text; const brightstar_t* bs = pl_get(brightstars, i); if (!sip_radec2pixelxy(&sip, bs->ra, bs->dec, &px, &py)) continue; if (bs->common_name && strlen(bs->common_name)) if (print_common_only || common_only) text = strdup(bs->common_name); else asprintf_safe(&text, "%s (%s)", bs->common_name, bs->name); else text = strdup(bs->name); logverb("%s at (%g, %g)\n", text, px, py); if (json) { sl* names = sl_new(4); char* namearr; if (bs->common_name && strlen(bs->common_name)) sl_append(names, bs->common_name); if (bs->name) sl_append(names, bs->name); namearr = sl_join(names, "\", \""); sl_appendf(json, "{ \"type\" : \"star\", " " \"pixelx\": %g, " " \"pixely\": %g, " " \"name\" : \"%s\", " " \"names\" : [ \"%s\" ] } " , px, py, (bs->common_name && strlen(bs->common_name)) ? bs->common_name : bs->name, namearr); free(namearr); sl_free2(names); } if (bs->common_name && strlen(bs->common_name)) printf("The star %s (%s)\n", bs->common_name, bs->name); else printf("The star %s\n", bs->name); if (!justlist) { float r,g,b; // set color based on RA,Dec to match constellations above. if (whitetext) { r = g = b = 1; } else { color_for_radec(bs->ra, bs->dec, &r, &g, &b); } cairo_set_source_rgba(cairoshapes, r,g,b,0.8); cairo_set_source_rgba(cairo, r,g,b, 0.8); } if (!justlist) add_text(cairos, text, px + label_offset, py + dy, halign, valign); free(text); if (!justlist) { // plot a black circle behind the light circle... cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI); cairo_stroke(cairobg); cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI); cairo_stroke(cairoshapes); } } pl_free(brightstars); } if (NGC) { double imscale; double imsize; double dy = 0; cairo_font_extents_t extents; if (!justlist) { cairo_set_source_rgb(cairoshapes, 1.0, 1.0, 1.0); cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0); cairo_set_line_width(cairo, nw); cairo_font_extents(cairo, &extents); dy = extents.ascent * 0.5; } // arcsec/pixel imscale = sip_pixel_scale(&sip); // arcmin imsize = imscale * (imin(W, H) / scale) / 60.0; N = ngc_num_entries(); logverb("Checking %i NGC/IC objects.\n", N); for (i=0; i<N; i++) { ngc_entry* ngc = ngc_get_entry(i); sl* str; sl* names; double pixsize; float ara, adec; char* text; if (!ngc) break; if (ngc->size < imsize * ngc_fraction) continue; if (ngcic_accurate_get_radec(ngc->is_ngc, ngc->id, &ara, &adec) == 0) { ngc->ra = ara; ngc->dec = adec; } if (!sip_radec2pixelxy(&sip, ngc->ra, ngc->dec, &px, &py)) continue; if (px < 0 || py < 0 || px*scale > W || py*scale > H) continue; str = sl_new(4); //sl_appendf(str, "%s %i", (ngc->is_ngc ? "NGC" : "IC"), ngc->id); names = ngc_get_names(ngc, NULL); if (names) { int n; for (n=0; n<sl_size(names); n++) { if (only_messier && strncmp(sl_get(names, n), "M ", 2)) continue; sl_append(str, sl_get(names, n)); } } sl_free2(names); text = sl_implode(str, " / "); printf("%s\n", text); pixsize = ngc->size * 60.0 / imscale; if (!justlist) { // black circle behind the white one... cairo_arc(cairobg, px, py, pixsize/2.0+1.0, 0.0, 2.0*M_PI); cairo_stroke(cairobg); cairo_move_to(cairoshapes, px + pixsize/2.0, py); cairo_arc(cairoshapes, px, py, pixsize/2.0, 0.0, 2.0*M_PI); debug("size: %f arcsec, pixsize: %f pixels\n", ngc->size, pixsize); cairo_stroke(cairoshapes); add_text(cairos, text, px + label_offset, py + dy, halign, valign); } if (json) { char* namelist = sl_implode(str, "\", \""); sl_appendf(json, "{ \"type\" : \"ngc\", " " \"names\" : [ \"%s\" ], " " \"pixelx\" : %g, " " \"pixely\" : %g, " " \"radius\" : %g }" , namelist, px, py, pixsize/2.0); free(namelist); } free(text); sl_free2(str); } } if (HD) { double rac, decc, ra2, dec2; double arcsec; hd_catalog_t* hdcat; bl* hdlist; int i; if (!justlist) cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0); logverb("Reading HD catalog: %s\n", hdpath); hdcat = henry_draper_open(hdpath); if (!hdcat) { ERROR("Failed to open HD catalog"); exit(-1); } logverb("Got %i HD stars\n", henry_draper_n(hdcat)); sip_pixelxy2radec(&sip, W/(2.0*scale), H/(2.0*scale), &rac, &decc); sip_pixelxy2radec(&sip, 0.0, 0.0, &ra2, &dec2); arcsec = arcsec_between_radecdeg(rac, decc, ra2, dec2); // Fudge arcsec *= 1.1; hdlist = henry_draper_get(hdcat, rac, decc, arcsec); logverb("Found %zu HD stars within range (%g arcsec of RA,Dec %g,%g)\n", bl_size(hdlist), arcsec, rac, decc); for (i=0; i<bl_size(hdlist); i++) { double px, py; char* txt; hd_entry_t* hd = bl_access(hdlist, i); if (!sip_radec2pixelxy(&sip, hd->ra, hd->dec, &px, &py)) { continue; } if (px < 0 || py < 0 || px*scale > W || py*scale > H) { logverb(" HD %i at RA,Dec (%g, %g) -> pixel (%.1f, %.1f) is out of bounds\n", hd->hd, hd->ra, hd->dec, px, py); continue; } asprintf_safe(&txt, "HD %i", hd->hd); if (!justlist) { cairo_text_extents_t textents; cairo_text_extents(cairo, txt, &textents); cairo_arc(cairobg, px, py, crad+1.0, 0.0, 2.0*M_PI); cairo_stroke(cairobg); cairo_arc(cairoshapes, px, py, crad, 0.0, 2.0*M_PI); cairo_stroke(cairoshapes); px -= (textents.width * 0.5); py -= (crad + 4.0); add_text(cairos, txt, px, py, halign, valign); } if (json) sl_appendf(json, "{ \"type\" : \"hd\"," " \"pixelx\": %g, " " \"pixely\": %g, " " \"name\" : \"HD %i\" }" , px, py, hd->hd); printf("%s\n", txt); free(txt); } bl_free(hdlist); henry_draper_close(hdcat); } if (json) { FILE* fout = stderr; char* annstr = sl_implode(json, ",\n"); fprintf(fout, "{ \n"); fprintf(fout, " \"status\": \"solved\",\n"); fprintf(fout, " \"git-revision\": %s,\n", AN_GIT_REVISION); fprintf(fout, " \"git-date\": \"%s\",\n", AN_GIT_DATE); fprintf(fout, " \"annotations\": [\n%s\n]\n", annstr); fprintf(fout, "}\n"); free(annstr); } sl_free2(json); json = NULL; if (justlist) return 0; target = cairo_image_surface_create_for_data(img, CAIRO_FORMAT_ARGB32, W, H, W*4); cairot = cairo_create(target); cairo_set_source_rgba(cairot, 0, 0, 0, 1); // Here's where you set the background surface's properties... cairo_set_source_surface(cairot, surfbg, 0, 0); cairo_mask_surface(cairot, surfshapesmask, 0, 0); cairo_stroke(cairot); // Add on the shapes. cairo_set_source_surface(cairot, surfshapes, 0, 0); //cairo_mask_surface(cairot, surfshapes, 0, 0); cairo_mask_surface(cairot, surfshapesmask, 0, 0); cairo_stroke(cairot); // Add on the foreground. cairo_set_source_surface(cairot, surffg, 0, 0); cairo_mask_surface(cairot, surffg, 0, 0); cairo_stroke(cairot); // Convert image for output... cairoutils_argb32_to_rgba(img, W, H); if (pngformat) { if (cairoutils_write_png(outfn, img, W, H)) { ERROR("Failed to write PNG"); exit(-1); } } else { if (cairoutils_write_ppm(outfn, img, W, H)) { ERROR("Failed to write PPM"); exit(-1); } } cairo_surface_destroy(target); cairo_surface_destroy(surfshapesmask); cairo_surface_destroy(surffg); cairo_surface_destroy(surfbg); cairo_surface_destroy(surfshapes); cairo_destroy(cairo); cairo_destroy(cairot); cairo_destroy(cairobg); cairo_destroy(cairoshapes); cairo_destroy(cairoshapesmask); free(img); return 0; }