Example #1
0
// TODO performance: could avoid populating mCandidates if greedy only
void LineBreaker::addCandidate(Candidate cand) {
  const size_t candIndex = mCandidates.size();
  mCandidates.push_back(cand);

  // mLastBreak is the index of the last line break we decided to do in
  // mCandidates, and mPreBreak is its preBreak value. mBestBreak is the index
  // of the best line breaking candidate we have found since then, and
  // mBestScore is its penalty.
  if (cand.postBreak - mPreBreak > currentLineWidth()) {
    // This break would create an overfull line, pick the best break and break
    // there (greedy)
    if (mBestBreak == mLastBreak) {
      // No good break has been found since last break. Break here.
      mBestBreak = candIndex;
    }
    pushGreedyBreak();
  }

  while (mLastBreak != candIndex &&
         cand.postBreak - mPreBreak > currentLineWidth()) {
    // We should rarely come here. But if we are here, we have broken the line,
    // but the remaining part still doesn't fit. We now need to break at the
    // second best place after the last break, but we have not kept that
    // information, so we need to go back and find it.
    //
    // In some really rare cases, postBreak - preBreak of a candidate itself may
    // be over the current line width. We protect ourselves against an infinite
    // loop in that case by checking that we have not broken the line at this
    // candidate already.
    for (size_t i = mLastBreak + 1; i < candIndex; i++) {
      const float penalty = mCandidates[i].penalty;
      if (penalty <= mBestScore) {
        mBestBreak = i;
        mBestScore = penalty;
      }
    }
    if (mBestBreak == mLastBreak) {
      // We didn't find anything good. Break here.
      mBestBreak = candIndex;
    }
    pushGreedyBreak();
  }

  if (cand.penalty <= mBestScore) {
    mBestBreak = candIndex;
    mBestScore = cand.penalty;
  }
}
Example #2
0
void drvJAVA2::show_rectangle(const float llx, const float lly, const float urx, const float ury)
{
	if (numberOfElements > limitNumberOfElements)
		continue_page();
	outf << "    // Path # " << currentNr() << endl;
	outf << "    currentPage.add(new PSPathObject(new Color(";
	outf << currentR() << "f, " << currentG() << "f, " << currentB() << "f), ";
	outf << currentLineWidth() << "f";
	if ((currentLineJoin() != 0) || (currentShowType() != 0)) {
		outf << ", " << currentLineJoin();
		switch (currentShowType()) {
		case drvbase::stroke:
			outf << ", 0";
			break;
		case drvbase::fill:
			outf << ", 1";
			break;
		case drvbase::eofill:
			outf << ", 2";
			break;
		default:
			errf << "\t\tFatal: unexpected case for currentShowType() in drvjava2" << endl;	// cannot happen
			abort();
		}
	}
	if (currentLineType() != solid) {
		outf << "," << endl;
		show_dashPattern(outf, dashPattern());
	}
	outf << ", new Rectangle2D.Float(" << (llx +
										   x_offset) << "f, " <<
		(currentDeviceHeight - ury + y_offset) << "f";
	outf << ", " << (urx - llx) << "f, " << (ury - lly) << "f)));" << endl;
	numberOfElements++;
}
Example #3
0
// Set libplot's filling-and-edging style.  May set the line width to zero
// to turn off edging.  In libplot, a 0-width line is as narrow a line as
// can be drawn.
void drvplot::set_filling_and_edging_style()
{
	switch (currentShowType()) {
	case drvbase::stroke:
		(void)plotter->flinewidth(currentLineWidth());
		(void)plotter->pencolor(plotcolor(currentR()), plotcolor(currentG()), plotcolor(currentB()));
		(void)plotter->filltype(0);	// no filling
		break;

	case drvbase::fill:
		if (pathWasMerged()) {
			(void)plotter->flinewidth(currentLineWidth());
			(void)plotter->pencolor(plotcolor(edgeR()), plotcolor(edgeG()), plotcolor(edgeB()));
			(void)plotter->fillcolor(plotcolor(fillR()), plotcolor(fillG()), plotcolor(fillB()));
		} else {
			(void)plotter->flinewidth(0.0);	// little or no edging
			(void)plotter->pencolor(plotcolor(currentR()), plotcolor(currentG()), plotcolor(currentB()));
			(void)plotter->fillcolor(plotcolor(currentR()), plotcolor(currentG()), plotcolor(currentB()));
		}
		(void)plotter->filltype(1);
		(void)plotter->fillmod("winding");
		break;

	case drvbase::eofill:
		if (pathWasMerged()) {
			(void)plotter->flinewidth(currentLineWidth());
			(void)plotter->pencolor(plotcolor(edgeR()), plotcolor(edgeG()), plotcolor(edgeB()));
			(void)plotter->fillcolor(plotcolor(fillR()), plotcolor(fillG()), plotcolor(fillB()));
		} else {
			(void)plotter->flinewidth(0.0);	// little or no edging
			(void)plotter->pencolor(plotcolor(currentR()), plotcolor(currentG()), plotcolor(currentB()));
			(void)plotter->fillcolor(plotcolor(currentR()), plotcolor(currentG()), plotcolor(currentB()));
		}
		(void)plotter->filltype(1);
		(void)plotter->fillmod("even-odd");
		break;

	default:
		// cannot happen
		errf << "unexpected ShowType " << (int) currentShowType();
		break;
	}
}
Example #4
0
// add a word break (possibly for a hyphenated fragment), and add desperate
// breaks if needed (ie when word exceeds current line width)
void LineBreaker::addWordBreak(size_t offset,
                               ParaWidth preBreak,
                               ParaWidth postBreak,
                               size_t preSpaceCount,
                               size_t postSpaceCount,
                               float penalty,
                               HyphenationType hyph) {
  Candidate cand;
  ParaWidth width = mCandidates.back().preBreak;
  if (postBreak - width > currentLineWidth()) {
    // Add desperate breaks.
    // Note: these breaks are based on the shaping of the (non-broken) original
    // text; they are imprecise especially in the presence of kerning,
    // ligatures, and Arabic shaping.
    size_t i = mCandidates.back().offset;
    width += mCharWidths[i++];
    for (; i < offset; i++) {
      float w = mCharWidths[i];
      if (w > 0) {
        cand.offset = i;
        cand.preBreak = width;
        cand.postBreak = width;
        // postSpaceCount doesn't include trailing spaces
        cand.preSpaceCount = postSpaceCount;
        cand.postSpaceCount = postSpaceCount;
        cand.penalty = SCORE_DESPERATE;
        cand.hyphenType = HyphenationType::BREAK_AND_DONT_INSERT_HYPHEN;
#if VERBOSE_DEBUG
        ALOGD("desperate cand: %zd %g:%g", mCandidates.size(), cand.postBreak,
              cand.preBreak);
#endif
        addCandidate(cand);
        width += w;
      }
    }
  }

  cand.offset = offset;
  cand.preBreak = preBreak;
  cand.postBreak = postBreak;
  cand.penalty = penalty;
  cand.preSpaceCount = preSpaceCount;
  cand.postSpaceCount = postSpaceCount;
  cand.hyphenType = hyph;
#if VERBOSE_DEBUG
  ALOGD("cand: %zd %g:%g", mCandidates.size(), cand.postBreak, cand.preBreak);
#endif
  addCandidate(cand);
}
Example #5
0
void drvPDF::show_path()
{
	// add_to_page(); // is done in drvbase !! 
	endtext();					// close text if open
	const char *setrgbcolor = 0;
	const char *drawingop = 0;
	switch (currentShowType()) {
	case drvbase::stroke:
		// it's a stroke
		drawingop = "S";
		setrgbcolor = "RG";
		break;
	case drvbase::fill:
		drawingop = "f";
		setrgbcolor = "rg";
		break;
	case drvbase::eofill:
		drawingop = "f*";
		setrgbcolor = "rg";
		break;
	default:
		// cannot happen
		errf << "unexpected ShowType " << (int) currentShowType() << endl;
		exit(1);
		break;
	}
//    buffer.precision(3);
//    buffer.setf(ios::fixed);
//    buffer.width(0); // to force minimal width
//    buffer.unsetf(ios::showpoint);

	if (Verbose()) {
		buffer << "% path " << currentNr() << endl;
	}
	buffer << RND3(currentR()) << " " << RND3(currentG()) << " " <<
		RND3(currentB()) << " " << setrgbcolor << endl;
	buffer << currentLineWidth() << " w" << endl;
	buffer << currentLineCap() << " J" << endl;
	buffer << currentLineJoin() << " j" << endl;
	buffer << dashPattern() << " d" << endl;
	print_coords();
	buffer << drawingop << endl;
}
Example #6
0
void drvSAMPL::show_path()
{
	outf << "Path # " << currentNr();
	if (isPolygon())
		outf << " (polygon): " << endl;
	else
		outf << " (polyline): " << endl;
	outf << "\tcurrentShowType: ";
	switch (currentShowType()) {
	case drvbase::stroke:
		outf << "stroked";
		break;
	case drvbase::fill:
		outf << "filled";
		break;
	case drvbase::eofill:
		outf << "eofilled";
		break;
	default:
		// cannot happen
		outf << "unexpected ShowType " << (int) currentShowType();
		break;
	}
	outf << endl;
	outf << "\tcurrentLineWidth: " << currentLineWidth() << endl;
	outf << "\tcurrentR: " << currentR() << endl;
	outf << "\tcurrentG: " << currentG() << endl;
	outf << "\tcurrentB: " << currentB() << endl;
	outf << "\tedgeR:    " << edgeR() << endl;
	outf << "\tedgeG:    " << edgeG() << endl;
	outf << "\tedgeB:    " << edgeB() << endl;
	outf << "\tfillR:    " << fillR() << endl;
	outf << "\tfillG:    " << fillG() << endl;
	outf << "\tfillB:    " << fillB() << endl;
	outf << "\tcurrentLineCap: " << currentLineCap() << endl;
	outf << "\tdashPattern: " << dashPattern() << endl;
	outf << "\tPath Elements 0 to " << numberOfElementsInPath() - 1 << endl;
	print_coords();
}
Example #7
0
void drvJAVA2::show_path()
{
	outf << "    // Path # " << currentNr() << endl;
	outf << "    currentPath = new PSPathObject(new Color(";
	outf << currentR() << "f, " << currentG() << "f, " << currentB() << "f), ";
	outf << currentLineWidth() << "f";
	if ((currentLineCap() != 0) || (currentLineJoin() != 0)
		|| (currentShowType() != 0) || (currentLineType() != solid)) {
		outf << ", " << currentLineCap() << ", " << currentLineJoin() <<
			", " << currentMiterLimit() << "f, ";
		switch (currentShowType()) {
		case drvbase::stroke:
			outf << "0";
			break;
		case drvbase::fill:
			outf << "1";
			break;
		case drvbase::eofill:
			outf << "2";
			break;
		default:
			errf << "\t\tFatal: unexpected case for currentShowType() in drvjava2" << endl;	// cannot happen
			abort();
		}
		if (currentLineType() != solid) {
			outf << "," << endl;
			show_dashPattern(outf, dashPattern());
		}
	}
	if (isPolygon()) {
		outf << ", true";
	}
	outf << ");" << endl;
	numberOfElements++;
	print_coords();
	outf << "    currentPage.add(currentPath);" << endl;
	numberOfElements++;
}
Example #8
0
void drvTK::show_path()
{
	const int fillpat = (currentShowType() == drvbase::stroke) ? noFill : Fill;
	if (isPolygon()) {
		buffer << "set i [$Global(CurrentCanvas) create polygon ";
		print_coords();
		if (fillpat == 1) {
			buffer << " -fill \"" << colorstring(currentR(), currentG(), currentB())
				<< "\"";
		} else {
			buffer << " -fill \"\"";
		}
		buffer << " -outline \"" << colorstring(currentR(), currentG(), currentB())
			<< "\"" << " -width " << (currentLineWidth()? currentLineWidth() : 1)
			<< "p" << " -tags \"" << options->tagNames << "\" ]" << endl;
	} else {
		if (fillpat == 1) {
			buffer << "set i [$Global(CurrentCanvas) create polygon ";
			print_coords();
			buffer << " -fill \"" << colorstring(currentR(), currentG(), currentB())
				<< "\"";
			buffer << " -outline \"" << colorstring(currentR(), currentG(), currentB())
				<< "\"" << " -width " << (currentLineWidth()? currentLineWidth() : 1)
				<< "p" << " -tags \"" << options->tagNames << "\" ]" << endl;
		} else {
			buffer << "set i [$Global(CurrentCanvas) create line ";
			print_coords();
			buffer << " -fill \"" << colorstring(currentR(), currentG(), currentB())
				<< "\"" << " -width " << (currentLineWidth()? currentLineWidth() : 1)
				<< "p" << " -tags \"" << options->tagNames << "\" ]" << endl;
		}
	}
	if (strcmp(options->tagNames.value.value(), "") && !(options->noImPress)) {
		buffer << "set Group($Global(CurrentCanvas),$i) \"" << options->tagNames << "\"" << endl;
	}
}
Example #9
0
void drvFIG::show_path()
{
	float localLineWidth = currentLineWidth();
	localLineWidth *= 80.0f/72.0f; // xfig scales width differently - added in 3.50 - wogl
	// dont know whether this should be synchronized with -usecorrectfontsize option.



	/*
	3.50:
Originally, the resolution of Fig lines was 1/80 inch, and it was thought that the line width of "1" looked too thick, so it was reduced.
Therefore, the final width of lines in PostScript/EPS is:

Figwidth == 1: 7.5
Figwidth > 1: (Figwidth-1)*15

Regards,
Brian Smith

in reverse:

l < (15+7.5)/2 : f = 1
f = (l /15) + 1

	*/

	const float boundaryforOneCase = (((15.0f + 7.5f)/2.0f) / 15.0f);  // 0.75
	// if calculated linewidth is (without "+1 correction") > 0.75 
	// then apply correction by 1 
	// for the 0.75 case itself it means - map it to 1.75 and from there to 2
	// if it is < 0.75, then leave it so and create in fig a 1 ( (int) 0.75+0.5 )
	if (Verbose() ) {
		cerr << "localLineWidth " << localLineWidth  << " b " << boundaryforOneCase << endl;
	}
	if (localLineWidth > boundaryforOneCase) { 
		localLineWidth += 1.0f; // see above
	} else {
		// line width of 0 remain 0 - everything else is at least 1 
		if ((localLineWidth < 0.0) || ((localLineWidth > 0.0) && (localLineWidth <= 1.0))) {
			localLineWidth = 1.0;
		} 
	}

	unsigned int linestyle = 0;
	switch (currentLineType()) {
	case solid:
		linestyle = 0;
		break;
	case dashed:
		linestyle = 1;
		break;
	case dotted:
		linestyle = 2;
		break;
	case dashdot:
		linestyle = 3;
		break;
	case dashdotdot:
		linestyle = 4;
		break;
	}

	const unsigned int linecap = currentLineCap();
	const unsigned int linejoin = currentLineJoin();
	// Calculate BBox
	bbox_path();

	const unsigned int curvetos = nrOfCurvetos();
	if (curvetos == 0)			// polyline
	{
		buffer << "# polyline\n";
		buffer << "2 1 " << linestyle << " " << (int) (localLineWidth + 0.5f) << " ";
		const unsigned int color = registercolor(currentR(), currentG(), currentB());
		const int fill_or_nofill = (currentShowType() == drvbase::stroke) ? -1 : 20;
		if (objectId)
			objectId--;			// don't let it get < 0
		buffer << color << " " << color << " " << objectId << " 0 " <<
			fill_or_nofill << " " << "4.0" << 
			" " << linejoin << " " << linecap 
			//" 0 0"
			<< " 0 0 0 ";
		// 4.0 is the gap spec. we could also derive this from the input
		buffer << (int) (numberOfElementsInPath()) << "\n";
		print_polyline_coords();
	} else						// contains at least one curveto 
	{
		buffer << "# spline\n";
		// 3 2 means "open interpolated spline"
		buffer << "3 4 " << linestyle << " " << (int) (localLineWidth + 0.5f) << " ";
		const unsigned int color = registercolor(currentR(), currentG(), currentB());
		const int fill_or_nofill = (currentShowType() == drvbase::stroke) ? -1 : 20;
		if (objectId)
			objectId--;			// don't let it get < 0
		buffer << color << " " << color << " " << objectId << " 0 " <<
			fill_or_nofill << " " << "4.0" << //" 0"
			" " << linecap 
			<< " 0 0 ";
		// 4.0 is the gap spec. we could also derive this from the input

		// IJMP - change to quintic spline - 5 pnts per spline, not 3
		buffer << numberOfElementsInPath() + 5 * curvetos - curvetos << "\n";
		print_spline_coords1();
		print_spline_coords2();

	}
}
Example #10
0
void drvCAIRO::show_path()
{
  DashPattern dp(dashPattern());

  outf << endl;
  outf << "  /*" << endl;
  outf << "   * Path # " << currentNr() ;
  if (isPolygon())
    outf << " (polygon):" << endl;
  else
    outf << " (polyline):" << endl;
  outf << "   */" << endl;
  outf << endl;
  
  outf << "  cairo_save (cr);" << endl;
  outf << "  cairo_set_line_width (cr, " << currentLineWidth() << ");" << endl;

  // CAIRO_LINE_CAP_BUTT   - start(stop) the line exactly at the start(end) point
  // CAIRO_LINE_CAP_ROUND  - use a round ending, the center of the circle is the end point
  // CAIRO_LINE_CAP_SQUARE - use squared ending, the center of the square is the end point
  outf << "  cairo_set_line_cap (cr, ";
  switch( currentLineCap() ) {
  case 0:
    outf << "CAIRO_LINE_CAP_BUTT);" << endl;
    break;

  case 1:
    outf << "CAIRO_LINE_CAP_ROUND);" << endl;
    break;

  case 2:
    outf << "CAIRO_LINE_CAP_SQUARE);" << endl;
    break;

  default:
    errf << "Unexpected currentLineCap() in cairo driver:  " << currentLineCap() << endl;
    outf << "CAIRO_LINE_CAP_ROUND);" << endl;
    break;
  }
  // cairo_set_dash (cairo_t *cr, const double *dashes, int num_dashes, double offset);
  // dashes :
  //     an array specifying alternate lengths of on and off stroke portions
  //
  // num_dashes :
  //     the length of the dashes array
  //
  // offset :
  //     an offset into the dash pattern at which the stroke should start
  //
  // dashPattern:  has nrOfEntries, float *numbers, float offset

  if (dp.nrOfEntries > 0) {
    outf << "  {" << endl;
    outf << "    double pat[" << dp.nrOfEntries << "] = {" << endl;
    for (int i = 0; i < dp.nrOfEntries; i++) {
      outf << "                      " << dp.numbers[i] << ", " << endl;
    }
    outf << "                   };" << endl;
    outf << endl;
    outf << "    cairo_set_dash (cr, pat, " << dp.nrOfEntries << ", " << dp.offset << ");" << endl;
    outf << "   }" << endl;
  } else {
    outf << "  cairo_set_dash (cr, NULL, 0, 0.0);" << endl;
  }

  // cairo_move_to (cr, 0.25, 0.25);
  // cairo_line_to (cr, 0.5, 0.375);
  outf << "  /* Path Elements 0 to " << numberOfElementsInPath() - 1 << " */" << endl;
  print_coords();



  switch (currentShowType()) {
  case drvbase::stroke:
    outf << "  cairo_set_source_rgb (cr, " << edgeR() << "," << edgeG() << "," << edgeB() << ");" << endl;
    outf << "  cairo_stroke (cr);" << endl;
    break;
	  
  case drvbase::eofill:
    outf << "  cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);" << endl;
    evenoddmode = true;

  case drvbase::fill:
	  
    outf << "  cairo_set_source_rgb (cr, " << fillR() << "," << fillG() << "," << fillB() << ");" << endl;
    outf << "  cairo_fill_preserve (cr);" << endl;
    if (evenoddmode) {
      outf << "  cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);" << endl;
      evenoddmode = false;
    }
    outf << "  cairo_set_source_rgb (cr, " << edgeR() << "," << edgeG() << "," << edgeB() << ");" << endl;
    outf << "  cairo_stroke (cr);" << endl;
    break;
	  
  default:
    // cannot happen
    outf << "  // unexpected ShowType " << (int) currentShowType();
    break;
  }
  outf << "  cairo_restore (cr);" << endl;

}