drawing-text.cpp revision 65806999dc34e08507042b3801bd1542909910d0
/**
* @file
* Group belonging to an SVG drawing element.
*//*
* Authors:
* Krzysztof KosiĆski <tweenk.pl@gmail.com>
*
* Copyright (C) 2011 Authors
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "display/cairo-utils.h"
#include "display/canvas-bpath.h" // for SPWindRule (WTF!)
#include "display/drawing-context.h"
#include "display/drawing-surface.h"
#include "display/drawing-text.h"
#include "libnrtype/font-instance.h"
#include "style.h"
#include "2geom/pathvector.h"
namespace Inkscape {
, _glyph(0)
{}
{
if (_font) {
}
}
void
{
_markForUpdate(STATE_ALL, false);
}
unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext const &ctx, unsigned /*flags*/, unsigned /*reset*/)
{
if (!ggroup) {
throw InvalidItemException();
}
return STATE_ALL;
}
/* orignally it did the one line below,
but it did not handle ws characters at all, and it had problems with scaling for overline/underline.
Replaced with the section below, which seems to be much more stable.
b = bounds_exact_transformed(*_font->PathVector(_glyph), ctx.ctm);
*/
/* Make a bounding box that is a little taller and lower (currently 10% extra) than the font's drawing box. Extra space is
to hold overline or underline, if present. All characters in a font use the same ascent and descent,
but different widths. This lets leading and trailing spaces have text decorations. If it is not done
the bounding box is limited to the box surrounding the drawn parts of visible glyphs only, and draws outside are ignored.
*/
float scale = 1.0;
// this expands the selection box for cases where the stroke is "thick"
if (_transform) {
}
}
// save bbox without miters for picking
_pick_bbox = b->roundOutwards();
if ( miterMax > 0.01 ) {
// grunt mode. we should compute the various miters instead
// (one for each point on the curve)
}
_bbox = b->roundOutwards();
} else if (b) {
_bbox = b->roundOutwards();
_pick_bbox = *_bbox;
}
/*
std::cout << "DEBUG _bbox"
<< " { " << _bbox->min()[Geom::X] << " , " << _bbox->min()[Geom::Y]
<< " } , { " << _bbox->max()[Geom::X] << " , " << _bbox->max()[Geom::Y]
<< " }" << std::endl;
*/
return STATE_ALL;
}
{
if (!ggroup) {
throw InvalidItemException();
}
return NULL;
}
// With text we take a simple approach: pick if the point is in a character bbox
return NULL;
}
{}
{}
void
DrawingText::clear()
{
}
bool
{
/* original, did not save a glyph for white space characters, causes problems for text-decoration
if (!font || !font->PathVector(glyph)) {
return(false);
}
*/
if (!font)return(false);
return(true);
}
void
{
}
unsigned
DrawingText::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
{
}
void DrawingText::decorateStyle(DrawingContext &ct, double vextent, double xphase, Geom::Point p1, Geom::Point p2)
{
double wave[16]={
0.000000, 0.382499, 0.706825, 0.923651, 1.000000, 0.923651, 0.706825, 0.382499,
0.000000, -0.382499, -0.706825, -0.923651, -1.000000, -0.923651, -0.706825, -0.382499,
};
int dashes[16]={
8, 7, 6, 5,
4, 3, 2, 1,
-8, -7, -6, -5
-4, -3, -2, -1
};
int dots[16]={
4, 3, 2, 1,
-4, -3, -2, -1,
4, 3, 2, 1,
-4, -3, -2, -1
};
/* For most spans draw the last little bit right to p2 or even a little beyond.
This allows decoration continuity within the line, and does not step outside the clip box off the end
text is dragged it may "spray" pixels.
if(_nrstyle.tspan_line_end){ pf = p2 - Geom::Point(2*step, 0.0); }
else { pf = p2; }
if(_nrstyle.tspan_line_start){ ps = p1 + Geom::Point(2*step, 0.0);
i = 15 & (i + 2);
}
else { ps = p1; }
*/
/* snap to nearest step in X */
}
/* The next three have a problem in that they are phase dependent. The bits of a line are not
necessarily passing through this routine in order, so we have to use the xphase information
to figure where in each of their cycles to start. Only accurate to 1 part in 16.
Huge possitive offset should keep the phase calculation from ever being negative.
*/
while(1){
if(dots[i]>0){
break;
}
else {
}
}
else {
}
i = 0; // once in phase, it stays in phase
}
}
while(1){
if(dashes[i]>0){
break;
}
else {
}
}
else {
}
i = 0; // once in phase, it stays in phase
}
}
while(1){
i = ((i + 1) & 15);
x += step;
}
}
else { // TEXT_DECORATION_STYLE_SOLID, also default in case it was not set for some reason
// ct.revrectangle(Geom::Rect(ps,pf));
}
}
/* returns scaled line thickness */
{
double thickness;
#define VALTRUNC(A,B,C) (A < B ? B : ( A > C ? C : A ))
final_underline_thickness = VALTRUNC(_nrstyle.underline_thickness, tsp_size_adj/30.0, tsp_size_adj/10.0);
final_line_through_thickness = VALTRUNC(_nrstyle.line_through_thickness, tsp_size_adj/30.0, tsp_size_adj/10.0);
// All lines must be the same thickness, in combinations, line_through trumps underline
}
p2 = Geom::Point(tsp_width_adj,tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
}
}
// Obviously this does not blink, but it does indicate which text has been set with that attribute
}
return(thickness);
}
unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*area*/, unsigned /*flags*/, DrawingItem * /*stop_at*/)
{
DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
if (!g) throw InvalidItemException();
// skip glyphs with singular transforms
if (g->_ctm.isSingular()) continue;
if(g->_drawable){
}
}
return RENDER_OK;
}
// NOTE: this is very similar to drawing-shape.cpp; the only difference is in path feeding
double phase_length = 0.0;
bool firsty = true;
bool decorate = true;
double starty = 0.0;
bool has_stroke, has_fill;
using Geom::X;
using Geom::Y;
if (has_fill || has_stroke) {
bool invset=false;
DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
if (!g) throw InvalidItemException();
if(!invset){
invset = true;
}
if (g->_ctm.isSingular()) continue;
if(g->_drawable){
}
// get the leftmost affine transform (leftmost defined with respect to the x axis of the first transform).
// That way the decoration will work no matter what mix of L->R, R->L text is in the span.
phase_length = g->_pl;
}
/* If the text has been mapped onto a path, which causes y to vary, drop the text decorations.
To handle that properly would need a conformal map
*/
if(firsty){
firsty = false;
}
else {
}
}
}
if (has_fill) {
ct.fillPreserve();
}
if (has_stroke) {
ct.strokePreserve();
}
1.0);
}
else { // whatever the current fill color is
1.0);
}
ct.strokePreserve();
}
}
return RENDER_OK;
}
{
// handle clip-rule
if (_style) {
} else {
}
}
DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
if (!g) {
throw InvalidItemException();
}
if(g->_drawable){
}
}
}
{
if (picked) {
return this;
}
return NULL;
}
bool
{
return true;
}
} // end namespace Inkscape
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :