drawing-text.cpp revision 44985a70f73e2b441900574f6bad338ba39df5fd
/**
* @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;
}
/*
Make a bounding box for drawing 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.
The box is also a hair wider than the text, since the glyphs do not always start or end at
the left and right edges of the box defined in the font.
*/
float scale_bigbox = 1.0;
if (_transform) {
}
Geom::Rect bigbox(Geom::Point(-_width*scale_bigbox*0.1, _asc*scale_bigbox*1.1),Geom::Point(_width*scale_bigbox, -_dsc*scale_bigbox*1.1));
/*
The pick box matches the characters as best as it can, leaving no extra space above or below
for decorations. The pathvector may include spaces, and spaces have no drawable glyph.
Catch those and do not pass them to bounds_exact_transformed(), which crashes Inkscape if it
sees a nondrawable glyph. Instead mock up a pickbox for them using font characteristics.
There may also be some other similar white space characters in some other unforeseen context
which should be handled by this code as well..
*/
if(_drawable){
}
if(!pb){ // Fallback
}
#if 0
/* FIXME if this is commented out then not even an approximation of pick on decorations */
/* adjust the pick box up or down to include the decorations.
This is only approximate since at this point we don't know how wide that line is, if it has
an unusual offset, and so forth. The selection point is set at what is roughly the center of
the decoration (vertically) for the wide ones, like wavy and double line.
The text decorations are not actually selectable.
*/
double bot = 0;
}
#endif
// this expands the selection box for cases where the stroke is "thick"
if (_transform) {
}
}
// save bbox without miters for picking
if ( miterMax > 0.01 ) {
// grunt mode. we should compute the various miters instead
// (one for each point on the curve)
}
_bbox = b.roundOutwards();
} else {
_bbox = b.roundOutwards();
}
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
// FIXME, why expand by delta? When is the next line needed?
// expanded.expandBy(delta);
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 &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2, double thickness)
{
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.
*/
/* 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.
*/
// FIXME: Per spec, this should produce round dots.
while(1){
if(dots[i]>0){
// Last dot
break;
} else {
}
} else {
}
i = 0; // once in phase, it stays in phase
}
}
while(1){
if(dashes[i]>0){
// Last dash
break;
} else {
}
} else {
}
i = 0; // once in phase, it stays in phase
}
}
while(1){
i = ((i + 1) & 15);
x += step;
}
while(1){
i = ((i - 1) & 15);
x -= step;
}
}
else { // TEXT_DECORATION_STYLE_SOLID, also default in case it was not set for some reason
}
}
/* returns scaled line thickness */
{
if (_nrstyle.font_size < 1.0e-32)return; // would cause a divide by zero and nothing would be visible anyway
double final_underline_thickness = CLAMP(_nrstyle.underline_thickness, tsp_size_adj/30.0, tsp_size_adj/10.0);
double final_line_through_thickness = CLAMP(_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
double thickness = final_underline_thickness;
if( under ) {
}
p2 = Geom::Point(tsp_width_adj,tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
}
} else {
// Over
}
// Obviously this does not blink, but it does indicate which text has been set with that attribute
}
}
}
unsigned DrawingText::_renderItem(DrawingContext &dc, 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 differences are in path feeding
// and in applying text decorations.
// Do we have text decorations?
// prepareFill / prepareStroke need to be called with _ctm in effect.
// However, we might need to apply a different ctm for glyphs.
// Therefore, only apply this ctm temporarily.
bool has_stroke = false;
bool has_fill = false;
bool has_td_fill = false;
bool has_td_stroke = false;
{
// Avoid creating patterns if not needed
if( decorate ) {
}
}
// Determine order for fill and stroke.
// Text doesn't have markers, we can do paint-order quick and dirty.
bool fill_first = false;
fill_first = true;
} // Won't get "stroke fill stroke" but that isn't 'valid'
// Determine geometry of text decoration
double phase_length = 0.0;
if( decorate ) {
bool invset = false;
bool first_y = true;
double start_y = 0.0;
DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
if (!g) throw InvalidItemException();
if (!invset) {
invset = true;
}
phase_length = g->_pl;
}
// Check for text on a path. FIXME: This needs better test (and probably not here).
if (first_y) {
first_y = false;
}
// 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.
decorate = false;
}
}
}
// Draw text decorations that go UNDER the text (underline, over-line)
if( decorate ) {
{
}
{
if (has_td_fill && fill_first) {
dc.fillPreserve();
}
if (has_td_stroke) {
dc.strokePreserve();
}
if (has_td_fill && !fill_first) {
dc.fillPreserve();
}
}
}
// accumulate the path that represents the glyphs
DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
if (!g) throw InvalidItemException();
if (g->_ctm.isSingular()) continue;
if (g->_drawable) {
}
}
// Draw the glyphs.
{
if (has_fill && fill_first) {
dc.fillPreserve();
}
if (has_stroke) {
dc.strokePreserve();
}
if (has_fill && !fill_first) {
dc.fillPreserve();
}
}
// Draw text decorations that go OVER the text (line through, blink)
if (decorate) {
{
}
{
if (has_td_fill && fill_first) {
dc.fillPreserve();
}
if (has_td_stroke) {
dc.strokePreserve();
}
if (has_td_fill && !fill_first) {
dc.fillPreserve();
}
}
}
}
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 :