static Position create_position(int size, int offset) { Position new_position; new_position.A4 = add_marker(offset,120,size,8); new_position.A3 = add_marker(offset,129,size,8); new_position.A2 = add_marker(offset,138,size,8); new_position.A1 = add_marker(offset,147,size,8); new_position.A0 = add_marker(offset,156,size,8); new_position.B4 = add_marker(offset + size,120,size,8); new_position.B3 = add_marker(offset + size,129,size,8); new_position.B2 = add_marker(offset + size,138,size,8); new_position.B1 = add_marker(offset + size,147,size,8); new_position.B0 = add_marker(offset + size,156,size,8); return new_position; }
void decoration_formatter::format_preamble( std::ostream& s, const comment_styles& single_line_cs, const comment_styles& multi_line_cs, const decoration_properties& dc) const { bool is_top(false); const auto top(modeline_locations::top); bool has_modeline(dc.modeline()); std::list<std::string> content; if (has_modeline) { is_top = dc.modeline()->location() == top; if (is_top) add_modeline(content, *dc.modeline()); } add_marker(content, dc.code_generation_marker()); if (dc.licence()) add_licence(content, *dc.licence()); if (content.empty()) return; if (has_modeline && is_top && content.size() == 1) { comment_formatter cf( start_on_first_line, !use_documentation_tool_markup, !documenting_previous_identifier, single_line_cs, !last_line_is_blank); cf.format(s, content, !line_between_blocks); } else { comment_formatter cf( is_top ? start_on_first_line : !start_on_first_line, !use_documentation_tool_markup, !documenting_previous_identifier, multi_line_cs, last_line_is_blank); cf.format(s, content, line_between_blocks); } }
static GtkTreeIter add_placemark (PlacemarksPlugin *plugin, const gchar *id, const gchar *name, gfloat lat, gfloat lon, gint zoom) { gchar *lat_str, *lon_str, *zoom_str; GtkTreeIter iter; PlacemarksPluginPrivate *priv; ChamplainMarker *marker; priv = PLACEMARKS_PLUGIN (plugin)->priv; lat_str = g_strdup_printf ("%f", lat); lon_str = g_strdup_printf ("%f", lon); zoom_str = g_strdup_printf ("%d", zoom); marker = add_marker (plugin, name, lat, lon); gtk_list_store_append (GTK_LIST_STORE (priv->model), &iter); gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter, COL_ID, id, COL_NAME, name, COL_LAT, lat, COL_LAT_STR, lat_str, COL_LON, lon, COL_LON_STR, lon_str, COL_ZOOM, zoom, COL_ZOOM_STR, zoom_str, COL_MARKER, marker, -1); g_free (lat_str); g_free (lon_str); g_free (zoom_str); priv->placemark_count++; return iter; }
void HaiQTextEdit::toggle_marker(int marker_type,QString path) { bool markers_changed=false; QTextCursor cursor=textCursor(); QTextBlock block=cursor.block(); defaultedit_blockdata *block_data=(defaultedit_blockdata *)block.userData(); if (!block_data) { block_data=new defaultedit_blockdata; block.setUserData(block_data); } if (block_data->has_marker(marker_type)) { block_data->remove_markers_of_type(marker_type); markers_changed=true; } else { haiq_marker marker; marker.path=path; marker.marker_type=marker_type; marker.line_number=textCursor().blockNumber()+1; set_random_id(marker); add_marker(marker); } do_marker_highlighting(cursor); if (markers_changed) emit markersChanged(); }
bool placement_finder::find_point_placement(pixel_position const& pos) { glyph_positions_ptr glyphs = std::make_shared<glyph_positions>(); std::vector<box2d<double> > bboxes; glyphs->reserve(layouts_.glyphs_count()); bboxes.reserve(layouts_.size()); bool base_point_set = false; for (auto const& layout_ptr : layouts_) { text_layout const& layout = *layout_ptr; rotation const& orientation = layout.orientation(); // Find text origin. pixel_position layout_center = pos + layout.displacement(); if (!base_point_set) { glyphs->set_base_point(layout_center); base_point_set = true; } box2d<double> bbox = layout.bounds(); bbox.re_center(layout_center.x, layout_center.y); /* For point placements it is faster to just check the bounding box. */ if (collision(bbox, layouts_.text(), false)) return false; if (layout.num_lines()) bboxes.push_back(std::move(bbox)); pixel_position layout_offset = layout_center - glyphs->get_base_point(); layout_offset.y = -layout_offset.y; // IMPORTANT NOTE: // x and y are relative to the center of the text // coordinate system: // x: grows from left to right // y: grows from bottom to top (opposite of normal computer graphics) double x, y; // set for upper left corner of text envelope for the first line, top left of first character y = layout.height() / 2.0; for ( auto const& line : layout) { y -= line.height(); //Automatically handles first line differently x = layout.jalign_offset(line.width()); for (auto const& glyph : line) { // place the character relative to the center of the string envelope glyphs->emplace_back(glyph, (pixel_position(x, y).rotate(orientation)) + layout_offset, orientation); if (glyph.advance()) { //Only advance if glyph is not part of a multiple glyph sequence x += glyph.advance() + glyph.format->character_spacing * scale_factor_; } } } } // add_marker first checks for collision and then updates the detector. if (has_marker_ && !add_marker(glyphs, pos)) return false; for (box2d<double> const& bbox : bboxes) { detector_.insert(bbox, layouts_.text()); } placements_.push_back(glyphs); return true; }
pulsesequence() { /* declaration of SGL kernel structures */ SGL_KERNEL_INFO_T read, phase, slice, ss_pre, ss_post; /* declaration of internal variables */ double freqlist[MAXNSLICE]; double pe_steps; int shapelist1, table; double xtime, grad_duration, ror_pad,rod_pad; double temp_tr; double readAmp, phaseAmp, sliceAmp; double tepad, tepad2, temin2, htrmin, delayToRF, delayRFToAcq, delayAcqToRF; double rof_pad, delRof; double sliceRephTrim, sliceDephTrim; double readRephTrim, readDephTrim; int rfPhase[2] = {0,2}; /* declaration of realtime variables */ int vpe_steps = v1; int vpe_ctr = v2; int vms_slices = v3; int vms_ctr = v4; int vpe_offset = v5; int vpe_index = v6; int vss = v7; int vssc = v8; int vacquire = v9; int vphase = v10; settable(t2,2,rfPhase); /* setup phase encoding order */ table = set_pe_order(); init_mri(); if( (sliceRephTrim = getvalnwarn("sliceRephTrim")) == 0.0 ) { sliceRephTrim = 1.0; } if( (sliceDephTrim = getvalnwarn("sliceDephTrim")) == 0.0 ) { sliceDephTrim = 1.0; } if( (readRephTrim = getvalnwarn("readRephTrim")) == 0.0 ) { readRephTrim = 1.0; } if( (readDephTrim = getvalnwarn("readDephTrim")) == 0.0 ) { readDephTrim = 1.0; } shape_rf( &p1_rf, "p1", p1pat, p1, flip1, rof1, rof2 ); // excitation pulse init_slice( &ss_grad, "ss", thk ); // slice gradient init_slice_refocus( &ssr_grad, "ssr" ); // slice refocus init_slice_refocus( &ssd_grad, "ssd" ); // slice refocus init_readout( &ro_grad, "ro", lro, np, sw ); // read gradient init_readout_refocus( &ror_grad, "ror" ); // read dephase init_readout_refocus( &rod_grad, "ror" ); // read dephase init_phase( &pe_grad, "pe", lpe, nv ); // phase gradient ss_grad.maxGrad = gmax * 0.57; ssr_grad.maxGrad = gmax * 0.57; ssd_grad.maxGrad = gmax * 0.57; ro_grad.maxGrad = gmax * 0.57; ror_grad.maxGrad = gmax * 0.57; rod_grad.maxGrad = gmax * 0.57; pe_grad.maxGrad = glimpe < 0.57? gmax*glimpe : gmax * 0.57; /* calculate the RF pulses, gradient pulses and their interdependencies */ calc_rf( &p1_rf, "tpwr1", "tpwr1f" ); calc_slice( &ss_grad, &p1_rf, NOWRITE, "gss" ); ssr_grad.amp = ss_grad.amp; ssr_grad.gmult = sliceRephTrim; ssr_grad.calcFlag = DURATION_FROM_MOMENT_AMPLITUDE; calc_slice_refocus( &ssr_grad, &ss_grad, NOWRITE, "gssr" ); ssd_grad.amp = ss_grad.amp; ssd_grad.gmult = sliceDephTrim; ssd_grad.calcFlag = DURATION_FROM_MOMENT_AMPLITUDE; calc_slice_dephase( &ssd_grad, &ss_grad, NOWRITE, "gssd" ); calc_readout( &ro_grad, NOWRITE, "gro", "sw", "at" ); ror_grad.amp = ro_grad.amp; ror_grad.calcFlag = DURATION_FROM_MOMENT_AMPLITUDE; rod_grad.amp = ro_grad.amp; rod_grad.calcFlag = DURATION_FROM_MOMENT_AMPLITUDE; ror_grad.gmult = readRephTrim; calc_readout_refocus( &ror_grad, &ro_grad, NOWRITE, "gror" ); rod_grad.gmult = readDephTrim; calc_readout_rephase( &rod_grad, &ro_grad, NOWRITE, "grod" ); calc_phase( &pe_grad, NOWRITE, "gpe", "tpe" ); /* work out the position of the markers */ /* markerA */ /* ss_grad.rfDelayFront indicates the starting point of the RF pulse measured from the start of the slice gradient ( rof1:pulse length:rof2 ) */ double granulatedRFDelayFront = granularity( ss_grad.rfDelayFront, GRADIENT_RES ); if( granulatedRFDelayFront > ss_grad.rfDelayFront ) { granulatedRFDelayFront -= GRADIENT_RES; } /* ss_grad.rfDelayBack indicates the end point of the RF pulse measured to the end of the slice gradient ( rof1:pulse length:rof2 ) */ double granulatedRFDelayBack = granularity( ss_grad.rfDelayBack, GRADIENT_RES ); if( granulatedRFDelayBack > ss_grad.rfDelayBack ) { granulatedRFDelayBack -= GRADIENT_RES; } double granulatedRFDelay = granulatedRFDelayFront < granulatedRFDelayBack ? granulatedRFDelayFront : granulatedRFDelayBack; double markerADelay = granulatedRFDelay; /* read and phase gradients can overlap the start or end of the slice gradient by max of granulatedRFDElay */ double granulatedATDelayFront = granularity(ro_grad.atDelayFront, GRADIENT_RES); if( granulatedATDelayFront > ro_grad.atDelayFront ) { granulatedATDelayFront -= GRADIENT_RES; } double granulatedATDelayBack = granularity(ro_grad.atDelayBack, GRADIENT_RES); if( granulatedATDelayBack > ro_grad.atDelayBack ) { granulatedATDelayBack -= GRADIENT_RES; } double granulatedATDelay = granulatedATDelayFront < granulatedATDelayBack ? granulatedATDelayFront : granulatedATDelayBack; /* longest gradient between RF pulse and acquire dominates */ xtime = ssr_grad.duration + granulatedRFDelay; xtime = xtime > ssd_grad.duration + granulatedRFDelay ? xtime : ssd_grad.duration + granulatedRFDelay; xtime = xtime > ror_grad.duration + granulatedATDelay ? xtime : ror_grad.duration + granulatedATDelay; xtime = xtime > rod_grad.duration + granulatedATDelay ? xtime : rod_grad.duration + granulatedATDelay; xtime = xtime > pe_grad.duration ? xtime : pe_grad.duration; ror_pad = xtime - ror_grad.duration - granulatedATDelay; rod_pad = xtime - rod_grad.duration - granulatedATDelay; /* make a gradient list */ start_kernel( &sk ); add_gradient( (void*)&ss_grad, "slice", SLICE, START_TIME, "", 0.0, PRESERVE ); add_gradient( (void*)&ssr_grad, "sliceReph", SLICE, BEHIND, "slice", 0.0, INVERT ); add_gradient( (void*)&ror_grad, "readDeph", READ, BEHIND, "slice", -granulatedRFDelay + ror_pad, INVERT ); add_gradient( (void*)&ro_grad, "read", READ, BEHIND, "readDeph", 0.0, PRESERVE ); add_gradient( (void*)&pe_grad, "phase", PHASE, SAME_START, "readDeph", 0.0, PRESERVE ); add_gradient( (void*)&rod_grad, "readReph", READ, BEHIND, "read", 0.0, INVERT ); add_gradient( (void*)&pe_grad, "rewind", PHASE, SAME_END, "readReph", 0.0, INVERT ); add_gradient( (void*)&ss_grad, "nextSlice", SLICE, BEHIND, "readReph", rod_pad - granulatedRFDelay, PRESERVE ); add_gradient( (void*)&ssd_grad, "sliceDeph", SLICE, BEFORE, "nextSlice", 0, INVERT ); add_marker( "markerA", SAME_START, "slice", granulatedRFDelay ); add_marker( "markerB", SAME_START, "nextSlice", granulatedRFDelay ); /* get the minimum echo time */ temin = get_timing( FROM_RF_CENTER_OF, "slice", TO_ECHO_OF, "read" ); temin2 = get_timing( FROM_ECHO_OF, "read", TO_RF_CENTER_OF, "nextSlice" ); htrmin = MAX( temin, temin2 ); if( minte[0] == 'y' ){ te = htrmin; } tepad = granularity( te - temin, GRADIENT_RES ); tepad2 = granularity( te - temin2, GRADIENT_RES ); te = temin + tepad; putCmd("setvalue('te', %f, 'current')\n", te ); if( tepad>0.0 ) change_timing( "readDeph", tepad ); if( tepad2>0.0 ) change_timing( "nextSlice", tepad2 ); tr = get_timing( FROM_START_OF, "slice", TO_START_OF, "nextSlice" ); putvalue("tr", tr ); delayRFToAcq = get_timing( FROM_RF_PULSE_OF, "slice", TO_ACQ_OF, "read" ); delayAcqToRF = get_timing( FROM_ACQ_OF, "read", TO_RF_PULSE_OF, "nextSlice" ); set_comp_info( &ss_pre, "ss_pre" ); write_comp_grads_snippet( NULL, NULL, &ss_pre, "START_OF_KERNEL", "markerA" ); set_comp_info( &read, "ro" ); set_comp_info( &phase, "pe" ); set_comp_info( &slice, "ss" ); write_comp_grads_snippet( &read, &phase, &slice, "markerA", "markerB" ); set_comp_info( &ss_post, "ss_post" ); write_comp_grads_snippet( NULL, NULL, &ss_post, "markerB", "END_OF_KERNEL" ); /* Set up frequency offset pulse shape list ********/ offsetlist(pss,ss_grad.ssamp,0,freqlist,ns,seqcon[1]); shapelist1 = shapelist(p1_rf.pulseName,ss_grad.rfDuration,freqlist,ns,ss_grad.rfFraction, seqcon[1]); /* Set pe_steps for profile or full image **********/ pe_steps = prep_profile(profile[0],nv,&pe_grad,&pe_grad);/* profile[0] is n y or r */ F_initval(pe_steps/2.0,vpe_offset); g_setExpTime(trmean*(ntmean*pe_steps*arraydim + (1+fabs(ssc))*arraydim)); /* Shift DDR for pro *******************************/ roff = -poffset(pro,ro_grad.roamp); /* PULSE SEQUENCE */ status( A ); rotate(); triggerSelect(trigger); obsoffset( resto ); delay( GRADIENT_RES ); initval( 1+fabs( ssc ), vss ); obspower( p1_rf.powerCoarse ); obspwrf( p1_rf.powerFine ); delay( GRADIENT_RES ); assign(one,vacquire); // real-time acquire flag setacqvar(vacquire); // Turn on acquire when vacquire is zero obl_shapedgradient(ss_pre.name,ss_pre.dur,0,0,ss_pre.amp,NOWAIT); sp1on(); delay(GRADIENT_RES); sp1off(); delay(ss_pre.dur-GRADIENT_RES ); msloop( seqcon[1], ns, vms_slices, vms_ctr ); assign(vss,vssc); peloop( seqcon[2], pe_steps, vpe_steps, vpe_ctr ); sub(vpe_ctr,vssc,vpe_ctr); // vpe_ctr counts up from -ssc assign(zero,vssc); if (seqcon[2] == 's') assign(zero,vacquire); // Always acquire for non-compressed loop else { ifzero(vpe_ctr); assign(zero,vacquire); // Start acquiring when vpe_ctr reaches zero endif(vpe_ctr); } if (table) getelem(t1,vpe_ctr,vpe_index); else { ifzero(vacquire); sub(vpe_ctr,vpe_offset,vpe_index); elsenz(vacquire); sub(zero,vpe_offset,vpe_index); endif(vacquire); } pe_shaped3gradient( read.name, phase.name, slice.name, read.dur, read.amp, 0, slice.amp, -pe_grad.increment, vpe_index, NOWAIT ); delay(ss_grad.rfDelayFront - granulatedRFDelay); shapedpulselist( shapelist1, ss_grad.rfDuration, oph, rof1, rof2, seqcon[1], vms_ctr ); delay( delayRFToAcq - alfa ); startacq(alfa); acquire( np, 1/ro_grad.bandwidth ); endacq(); delay( delayAcqToRF - ss_grad.rfDelayFront + granulatedRFDelay - GRADIENT_RES ); sp1on(); delay(GRADIENT_RES); sp1off(); endpeloop( seqcon[2], vpe_ctr ); endmsloop( seqcon[1], vms_ctr ); obl_shapedgradient(ss_post.name,ss_post.dur,0,0,ss_post.amp,WAIT); }
static void item_added_cb (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) { add_marker (tree_model, path, iter, user_data); }
bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e orientation) { // // IMPORTANT NOTE: See note about coordinate systems in find_point_placement()! // vertex_cache::scoped_state begin(pp); text_upright_e real_orientation = simplify_upright(orientation, pp.angle()); glyph_positions_ptr glyphs = std::make_shared<glyph_positions>(); std::vector<box2d<double> > bboxes_all; glyphs->reserve(layouts_.glyphs_count()); bboxes_all.reserve(layouts_.glyphs_count()); unsigned upside_down_glyph_count = 0; marker_placement_finder_ptr marker_placement_ptr; for (auto const& layout_ptr : layouts_) { text_layout const& layout = *layout_ptr; if(has_marker_ && layout.shield_layout()) { marker_placement_ptr = std::make_shared<marker_placement_finder>(layout_ptr); } pixel_position align_offset = layout.alignment_offset(); pixel_position const& layout_displacement = layout.displacement(); double sign = (real_orientation == UPRIGHT_LEFT) ? -1 : 1; double offset = layout_displacement.y + 0.5 * sign * layout.height(); double adjust_character_spacing = .0; double layout_width = layout.width(); bool adjust = layout.horizontal_alignment() == H_ADJUST; if (adjust) { text_layout::const_iterator longest_line = layout.longest_line(); if (longest_line != layout.end()) { adjust_character_spacing = (pp.length() - longest_line->glyphs_width()) / longest_line->space_count(); layout_width = longest_line->glyphs_width() + longest_line->space_count() * adjust_character_spacing; } } //find the proper center line int line_count = layout.num_lines() % 2 == 0 ? layout.num_lines() : layout.num_lines() - 1; int centre_line_index = line_count/2; int line_index = -1; for (auto const& line : layout) { line_index++; if(has_marker_ && marker_placement_ptr && (line_index == centre_line_index)) { marker_placement_ptr->line_size(line.size()); } // Only subtract half the line height here and half at the end because text is automatically // centered on the line if (layout.num_lines() == 1 || (layout.num_lines() > 1 && line_index != 0)) { offset -= sign * line.height()/2; } vertex_cache & off_pp = pp.get_offseted(offset, sign * layout_width); vertex_cache::scoped_state off_state(off_pp); // TODO: Remove this when a clean implementation in vertex_cache::get_offseted is done double line_width = adjust ? (line.glyphs_width() + line.space_count() * adjust_character_spacing) : line.width(); if (!off_pp.move(sign * layout.jalign_offset(line_width) - align_offset.x)) return false; double last_cluster_angle = 999; int current_cluster = -1; pixel_position cluster_offset; double angle = 0.0; rotation rot; double last_glyph_spacing = 0.; for (auto const& glyph : line) { if (current_cluster != static_cast<int>(glyph.char_index)) { if (adjust) { if (!off_pp.move(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing))) return false; last_glyph_spacing = adjust_character_spacing; } else { if (!off_pp.move_to_distance(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing))) return false; last_glyph_spacing = glyph.format->character_spacing * scale_factor_; } current_cluster = glyph.char_index; // Only calculate new angle at the start of each cluster! angle = normalize_angle(off_pp.angle(sign * layout.cluster_width(current_cluster))); rot.init(angle); if ((text_props_->max_char_angle_delta > 0) && (last_cluster_angle != 999) && std::fabs(normalize_angle(angle-last_cluster_angle)) > text_props_->max_char_angle_delta) { return false; } cluster_offset.clear(); last_cluster_angle = angle; } if (std::abs(angle) > M_PI/2) ++upside_down_glyph_count; pixel_position pos = off_pp.current_position() + cluster_offset; // Center the text on the line double char_height = line.max_char_height(); pos.y = -pos.y - char_height/2.0*rot.cos; pos.x = pos.x + char_height/2.0*rot.sin; cluster_offset.x += rot.cos * glyph.advance(); cluster_offset.y -= rot.sin * glyph.advance(); box2d<double> bbox = get_bbox(layout, glyph, pos, rot); if (collision(bbox, layouts_.text(), true)) return false; //Whitespace glyphs have 0 height - sadly, there is no other easily // accessible data in a glyph to indicate that it is whitespace. bool glyph_is_empty = (0 == glyph.height()); //Collect all glyphs and angles for the centre line, in the case a // marker position needs to be calculated later if(has_marker_ && marker_placement_ptr && layout.shield_layout() && (line_index == centre_line_index)) { marker_placement_ptr->add_angle(angle); marker_placement_ptr->add_bbox(bbox); } //If the glyph is empty, don't draw it, and don't include it in the // overall bounding box. This means that leading and trailing // whitespace characters don't take up extra space where other // symbols could be placed on a map. if(!glyph_is_empty) { bboxes_all.push_back(std::move(bbox)); glyphs->emplace_back(glyph, pos, rot); } } // See comment above offset -= sign * line.height()/2; } if(marker_placement_ptr) { marker_placement_ptr->align_offset(align_offset); } } if (upside_down_glyph_count > static_cast<unsigned>(layouts_.text().length() / 2)) { if (orientation == UPRIGHT_AUTO) { // Try again with opposite orientation begin.restore(); return single_line_placement(pp, real_orientation == UPRIGHT_RIGHT ? UPRIGHT_LEFT : UPRIGHT_RIGHT); } // upright==left_only or right_only and more than 50% of characters upside down => no placement else if (orientation == UPRIGHT_LEFT_ONLY || orientation == UPRIGHT_RIGHT_ONLY) { return false; } } //NOTE: Because of the glyph_is_empty check above, whitespace characters // don't factor in to the bounding box. This way, whitespace used for // layout adjustment purposes don't artificially increase the size of // the bounding box and reduce the density of possible mapnik symbols. box2d<double> overall_bbox; bool overall_bbox_initialized = false; for(box2d<double> const& bbox : bboxes_all) { detector_.insert(bbox, layouts_.text()); if(overall_bbox_initialized) { overall_bbox.expand_to_include(bbox); } else { overall_bbox = bbox; } } //WI: loop over marker_placements and place the markers for each layout if(has_marker_ && marker_placement_ptr ) { pixel_position marker_pos; double marker_cw_angle = 0.0; marker_placement_ptr->find_marker_placement(scale_factor_, marker_pos, marker_cw_angle); agg::trans_affine placement_tr; placement_tr.rotate( marker_cw_angle ); add_marker(glyphs, marker_pos, true, placement_tr); detector_.insert(overall_bbox, layouts_.text()); } placements_.push_back(glyphs); return true; }
bool placement_finder::find_point_placement(pixel_position const& pos) { glyph_positions_ptr glyphs = std::make_shared<glyph_positions>(); std::vector<box2d<double> > bboxes; glyphs->reserve(layouts_.glyphs_count()); bboxes.reserve(layouts_.size()); box2d<double> bbox; double max_line_width = 0.0; double first_line_height = -1.0; bool base_point_set = false; for (auto const& layout_ptr : layouts_) { text_layout const& layout = *layout_ptr; rotation const& orientation = layout.orientation(); // Find text origin. pixel_position layout_center = pos + layout.displacement(); if (!base_point_set) { glyphs->set_base_point(layout_center); base_point_set = true; } bbox = layout.bounds(); bbox.re_center(layout_center.x, layout_center.y); /* For point placements it is faster to just check the bounding box. */ if (collision(bbox, layouts_.text(), false)) return false; if (layout.num_lines()) bboxes.push_back(std::move(bbox)); pixel_position layout_offset = layout_center - glyphs->get_base_point(); layout_offset.y = -layout_offset.y; // IMPORTANT NOTE: // x and y are relative to the center of the text // coordinate system: // x: grows from left to right // y: grows from bottom to top (opposite of normal computer graphics) double x, y; // set for upper left corner of text envelope for the first line, top left of first character y = layout.height() / 2.0; for ( auto const& line : layout) { y -= line.height(); //Automatically handles first line differently x = layout.jalign_offset(line.width()); if(line.width() > max_line_width) { max_line_width = line.width(); } if(first_line_height <= 0.0 ) { first_line_height = line.line_height() / scale_factor_; } for (auto const& glyph : line) { // place the character relative to the center of the string envelope glyphs->emplace_back(glyph, (pixel_position(x, y).rotate(orientation)) + layout_offset, orientation); if (glyph.advance()) { //Only advance if glyph is not part of a multiple glyph sequence x += glyph.advance() + glyph.format->character_spacing * scale_factor_; } } } } // add_marker first checks for collision and then updates the detector. if (has_marker_ ) { agg::trans_affine placement_tr; if(text_props_->fit_marker && glyphs->size() > 0) { double padding = 0.1; double width_scale = bbox.width() / marker_box_.width() + 2*padding; // 2 because the text is being padded on both sides. double heigh_scale = bbox.height() / marker_box_.height() + 2*padding; // 2 because the text is being padded on both sides. placement_tr.scale(width_scale, heigh_scale); //now we will need to shift the bbox it will fit the padding placement_tr.translate(- padding, - padding ); } if(!add_marker(glyphs, pos, false, placement_tr)) { return false; } } for (box2d<double> const& bbox : bboxes) { detector_.insert(bbox, layouts_.text()); } placements_.push_back(glyphs); return true; }