Esempio n. 1
0
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;
}
Esempio n. 2
0
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);
    }
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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();
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
static void item_added_cb (GtkTreeModel *tree_model, GtkTreePath  *path, GtkTreeIter *iter, gpointer user_data)
{
	add_marker (tree_model, path, iter, user_data);
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}