mirror of https://github.com/KLayout/klayout.git
WIP: preparations - introducing TextInfo
This commit is contained in:
parent
7b4ff5d823
commit
e8048d6686
|
|
@ -101,17 +101,22 @@ hershey_count_edges (const std::string &s, unsigned int f)
|
|||
HersheyFont *fp = fonts [f];
|
||||
size_t n = 0;
|
||||
|
||||
for (const char *cp = s.c_str (); *cp; ++cp) {
|
||||
for (const char *cp = s.c_str (); *cp; ) {
|
||||
|
||||
unsigned char c = (unsigned char) *cp;
|
||||
if (c == '\012' || c == '\015') {
|
||||
if (c == '\015' && cp[1] == '\012') {
|
||||
++cp;
|
||||
if (tl::skip_newline (cp)) {
|
||||
|
||||
// skip new line - they don't contribute edges
|
||||
|
||||
} else {
|
||||
|
||||
uint32_t c = tl::utf32_from_utf8 (cp);
|
||||
|
||||
if (c < fp->end_char && c >= fp->start_char) {
|
||||
n += fp->chars [c - fp->start_char].edge_end - fp->chars [c - fp->start_char].edge_start;
|
||||
} else if (invalid_char < fp->end_char && invalid_char >= fp->start_char) {
|
||||
n += fp->chars [invalid_char - fp->start_char].edge_end - fp->chars [invalid_char - fp->start_char].edge_start;
|
||||
}
|
||||
} else if (c < fp->end_char && c >= fp->start_char) {
|
||||
n += fp->chars [c - fp->start_char].edge_end - fp->chars [c - fp->start_char].edge_start;
|
||||
} else if (invalid_char < fp->end_char && invalid_char >= fp->start_char) {
|
||||
n += fp->chars [invalid_char - fp->start_char].edge_end - fp->chars [invalid_char - fp->start_char].edge_start;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -142,22 +147,27 @@ hershey_text_box (const std::string &s, unsigned int f)
|
|||
int w = 0;
|
||||
int h = fp->ymax;
|
||||
|
||||
for (const char *cp = s.c_str (); *cp; ++cp) {
|
||||
for (const char *cp = s.c_str (); *cp; ) {
|
||||
|
||||
if (tl::skip_newline (cp)) {
|
||||
|
||||
unsigned char c = (unsigned char) *cp;
|
||||
if (c == '\012' || c == '\015') {
|
||||
if (c == '\015' && cp[1] == '\012') {
|
||||
++cp;
|
||||
}
|
||||
if (w > wl) {
|
||||
wl = w;
|
||||
}
|
||||
|
||||
hl += line_spacing + h - fp->ymin;
|
||||
w = 0;
|
||||
} else if (c < fp->end_char && c >= fp->start_char) {
|
||||
w += fp->chars [c - fp->start_char].width;
|
||||
} else if (invalid_char < fp->end_char && invalid_char >= fp->start_char) {
|
||||
w += fp->chars [invalid_char - fp->start_char].width;
|
||||
|
||||
} else {
|
||||
|
||||
uint32_t c = tl::utf32_from_utf8 (cp);
|
||||
|
||||
if (c < fp->end_char && c >= fp->start_char) {
|
||||
w += fp->chars [c - fp->start_char].width;
|
||||
} else if (invalid_char < fp->end_char && invalid_char >= fp->start_char) {
|
||||
w += fp->chars [invalid_char - fp->start_char].width;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -170,7 +180,7 @@ hershey_text_box (const std::string &s, unsigned int f)
|
|||
return db::DBox (0, 0, wl, hl);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
hershey_justify (const std::string &s, unsigned int f, db::DBox bx, HAlign halign, VAlign valign, std::vector<db::DPoint> &linestarts)
|
||||
{
|
||||
HersheyFont *fp = fonts [f];
|
||||
|
|
@ -179,20 +189,24 @@ hershey_justify (const std::string &s, unsigned int f, db::DBox bx, HAlign halig
|
|||
int w = 0;
|
||||
int h = fp->ymax;
|
||||
|
||||
for (const char *cp = s.c_str (); *cp; ++cp) {
|
||||
for (const char *cp = s.c_str (); *cp; ) {
|
||||
|
||||
if (tl::skip_newline (cp)) {
|
||||
|
||||
unsigned char c = (unsigned char) *cp;
|
||||
if (c == '\012' || c == '\015') {
|
||||
if (c == '\015' && cp[1] == '\012') {
|
||||
++cp;
|
||||
}
|
||||
linestarts.push_back (db::DPoint (w, -hl));
|
||||
hl += line_spacing + h - fp->ymin;
|
||||
w = 0;
|
||||
} else if (c < fp->end_char && c >= fp->start_char) {
|
||||
w += fp->chars [c - fp->start_char].width;
|
||||
} else if (invalid_char < fp->end_char && invalid_char >= fp->start_char) {
|
||||
w += fp->chars [invalid_char - fp->start_char].width;
|
||||
|
||||
} else {
|
||||
|
||||
uint32_t c = tl::utf32_from_utf8 (cp);
|
||||
|
||||
if (c < fp->end_char && c >= fp->start_char) {
|
||||
w += fp->chars [c - fp->start_char].width;
|
||||
} else if (invalid_char < fp->end_char && invalid_char >= fp->start_char) {
|
||||
w += fp->chars [invalid_char - fp->start_char].width;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -221,20 +235,18 @@ hershey_justify (const std::string &s, unsigned int f, db::DBox bx, HAlign halig
|
|||
}
|
||||
*l = p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// basic_hershey_edge_iterator implementation
|
||||
|
||||
basic_hershey_edge_iterator::basic_hershey_edge_iterator (const std::string &s, unsigned int f, const std::vector<db::DPoint> &line_starts)
|
||||
: m_line (0), m_string (s), m_edge (0), m_edge_end (0), m_index (0), m_linestarts (line_starts)
|
||||
: m_line (0), m_string (s), m_edge (0), m_edge_end (0), m_linestarts (line_starts)
|
||||
{
|
||||
m_fp = fonts [f];
|
||||
m_end = (unsigned int) m_string.size ();
|
||||
m_new_char = true;
|
||||
mp_cp = m_string.c_str ();
|
||||
|
||||
if (m_linestarts.size () == 0) {
|
||||
if (m_linestarts.empty ()) {
|
||||
m_linestarts.push_back (db::DPoint (0.0, 0.0));
|
||||
}
|
||||
m_pos = m_linestarts [0];
|
||||
|
|
@ -243,66 +255,47 @@ basic_hershey_edge_iterator::basic_hershey_edge_iterator (const std::string &s,
|
|||
bool
|
||||
basic_hershey_edge_iterator::at_end () const
|
||||
{
|
||||
return m_index >= m_end;
|
||||
return *mp_cp == 0 && m_edge == m_edge_end;
|
||||
}
|
||||
|
||||
db::DEdge
|
||||
basic_hershey_edge_iterator::get ()
|
||||
{
|
||||
while (m_new_char && !at_end ()) {
|
||||
|
||||
unsigned char c = (unsigned char) (m_index < m_end ? m_string [m_index] : ' ');
|
||||
while (m_edge == m_edge_end && *mp_cp) {
|
||||
|
||||
m_pos += m_delta;
|
||||
|
||||
if (c < m_fp->end_char && c >= m_fp->start_char) {
|
||||
m_edge = m_edge_end = 0;
|
||||
m_delta = db::DVector ();
|
||||
|
||||
m_edge = m_fp->chars [c - m_fp->start_char].edge_start;
|
||||
m_edge_end = m_fp->chars [c - m_fp->start_char].edge_end;
|
||||
m_delta = db::DVector (m_fp->chars [c - m_fp->start_char].width, 0);
|
||||
if (tl::skip_newline (mp_cp)) {
|
||||
|
||||
} else if (c != '\012' && c != '\015'
|
||||
&& invalid_char < m_fp->end_char
|
||||
&& invalid_char >= m_fp->start_char) {
|
||||
++m_line;
|
||||
|
||||
m_edge = m_fp->chars [invalid_char - m_fp->start_char].edge_start;
|
||||
m_edge_end = m_fp->chars [invalid_char - m_fp->start_char].edge_end;
|
||||
m_delta = db::DVector (m_fp->chars [invalid_char - m_fp->start_char].width, 0);
|
||||
if (m_line >= m_linestarts.size ()) {
|
||||
db::DPoint last;
|
||||
last = m_linestarts.back ();
|
||||
last += db::DVector (0, -(m_fp->ymax - m_fp->ymin + line_spacing));
|
||||
m_linestarts.push_back (last);
|
||||
}
|
||||
m_pos = m_linestarts [m_line];
|
||||
|
||||
} else {
|
||||
|
||||
m_edge = m_edge_end = 0;
|
||||
m_delta = db::DVector ();
|
||||
uint32_t c = tl::utf32_from_utf8 (mp_cp);
|
||||
|
||||
}
|
||||
|
||||
if (m_edge == m_edge_end) {
|
||||
|
||||
if (c == '\012' || c == '\015') {
|
||||
if (c == '\015' && m_string.size () > m_index + 1 && m_string [m_index] == '\012') {
|
||||
++m_index;
|
||||
}
|
||||
++m_line;
|
||||
if (m_line >= m_linestarts.size ()) {
|
||||
m_linestarts.push_back (m_linestarts.back () + db::DVector (0.0, -(m_fp->ymax - m_fp->ymin + line_spacing)));
|
||||
}
|
||||
m_pos = m_linestarts [m_line];
|
||||
if (c < m_fp->start_char || c >= m_fp->end_char) {
|
||||
c = invalid_char;
|
||||
}
|
||||
|
||||
++m_index;
|
||||
if (c < m_fp->end_char && c >= m_fp->start_char) {
|
||||
m_edge = m_fp->chars [c - m_fp->start_char].edge_start;
|
||||
m_edge_end = m_fp->chars [c - m_fp->start_char].edge_end;
|
||||
m_delta = db::DVector (m_fp->chars [c - m_fp->start_char].width, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
m_new_char = false;
|
||||
}
|
||||
}
|
||||
|
||||
while (m_line >= m_linestarts.size ()) {
|
||||
db::DPoint last;
|
||||
if (m_linestarts.size () > 0) {
|
||||
last = m_linestarts.back ();
|
||||
last += db::DVector (0, -(m_fp->ymax - m_fp->ymin + line_spacing));
|
||||
}
|
||||
m_linestarts.push_back (last);
|
||||
}
|
||||
|
||||
if (!at_end ()) {
|
||||
|
|
@ -316,16 +309,9 @@ basic_hershey_edge_iterator::get ()
|
|||
void
|
||||
basic_hershey_edge_iterator::inc ()
|
||||
{
|
||||
if (m_new_char) {
|
||||
get ();
|
||||
}
|
||||
|
||||
if (! at_end ()) {
|
||||
++m_edge;
|
||||
if (m_edge == m_edge_end) {
|
||||
++m_index;
|
||||
m_new_char = true;
|
||||
}
|
||||
get ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,11 +51,10 @@ public:
|
|||
void inc ();
|
||||
|
||||
private:
|
||||
bool m_new_char;
|
||||
unsigned int m_line;
|
||||
const char *mp_cp;
|
||||
std::string m_string;
|
||||
unsigned int m_edge, m_edge_end;
|
||||
unsigned int m_index, m_end;
|
||||
std::vector<db::DPoint> m_linestarts;
|
||||
db::DPoint m_pos;
|
||||
db::DVector m_delta;
|
||||
|
|
@ -177,14 +176,16 @@ struct DB_PUBLIC_TEMPLATE hershey
|
|||
/**
|
||||
* @brief Obtain the size of the text
|
||||
*
|
||||
* @return The bounding box of the text with the scaling applied
|
||||
* @return The bounding box of the text with the scaling and justification applied
|
||||
*/
|
||||
box<C> bbox () const
|
||||
db::DBox bbox () const
|
||||
{
|
||||
db::DBox b = hershey_text_box (m_string, m_font);
|
||||
db::point<C> p1 (coord_traits::rounded (b.p1 ().x () / m_scale), coord_traits::rounded (b.p1 ().y () / m_scale));
|
||||
db::point<C> p2 (coord_traits::rounded (b.p2 ().x () / m_scale), coord_traits::rounded (b.p2 ().y () / m_scale));
|
||||
return box<C> (p1, p2);
|
||||
db::DBox b = hershey_text_box (m_string, m_font) * (1.0 / m_scale);
|
||||
if (! m_linestarts.empty ()) {
|
||||
return b.moved (m_linestarts.front () - db::DPoint ());
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -791,35 +791,6 @@ Bitmap::render_contour (std::vector<lay::RenderEdge> &edges)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned char next_char_latin1_from_utf8 (const char *&cp, const char *cpf = 0)
|
||||
{
|
||||
unsigned char c = *cp;
|
||||
if ((c & 0xe0) == 0xc0) {
|
||||
if ((cp[1] & 0xc0) == 0x80 && (! cpf || cpf > cp + 1)) {
|
||||
unsigned int x = ((unsigned int) ((unsigned char) c & 0x1f) << 6) | (unsigned int) (cp[1] & 0x3f);
|
||||
cp += 1;
|
||||
if (x < 255) {
|
||||
c = x;
|
||||
} else {
|
||||
c = '?';
|
||||
}
|
||||
} else {
|
||||
c = '?';
|
||||
}
|
||||
} else if ((c & 0xf0) == 0xe0) {
|
||||
if ((cp[1] & 0xc0) == 0x80 && (cp[2] & 0xc0) == 0x80 && (! cpf || cpf > cp + 2)) {
|
||||
cp += 2;
|
||||
}
|
||||
c = '?';
|
||||
} else if ((c & 0xf8) == 0xf0) {
|
||||
if ((cp[1] & 0xc0) == 0x80 && (cp[2] & 0xc0) == 0x80 && (cp[3] & 0xc0) == 0x80 && (! cpf || cpf > cp + 3)) {
|
||||
cp += 3;
|
||||
}
|
||||
c = '?';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
Bitmap::render_text (const lay::RenderText &text)
|
||||
{
|
||||
|
|
@ -830,12 +801,11 @@ Bitmap::render_text (const lay::RenderText &text)
|
|||
// count the lines and max. characters per line
|
||||
|
||||
unsigned int lines = 1;
|
||||
for (const char *cp = text.text.c_str (); *cp; ++cp) {
|
||||
if (*cp == '\012' || *cp == '\015') {
|
||||
if (*cp == '\015' && cp[1] == '\012') {
|
||||
++cp;
|
||||
}
|
||||
for (const char *cp = text.text.c_str (); *cp; ) {
|
||||
if (tl::skip_newline (cp)) {
|
||||
++lines;
|
||||
} else {
|
||||
++cp;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -858,10 +828,9 @@ Bitmap::render_text (const lay::RenderText &text)
|
|||
|
||||
unsigned int length = 0;
|
||||
const char *cp = cp1;
|
||||
while (*cp && *cp != '\012' && *cp != '\015') {
|
||||
next_char_latin1_from_utf8 (cp);
|
||||
while (*cp && !tl::is_newline (*cp)) {
|
||||
tl::utf32_from_utf8 (cp);
|
||||
++length;
|
||||
++cp;
|
||||
}
|
||||
|
||||
double xx;
|
||||
|
|
@ -880,11 +849,13 @@ Bitmap::render_text (const lay::RenderText &text)
|
|||
|
||||
for ( ; cp1 != cp; ++cp1) {
|
||||
|
||||
unsigned char c = next_char_latin1_from_utf8 (cp1, cp);
|
||||
uint32_t c = tl::utf32_from_utf8 (cp1, cp);
|
||||
if (c < uint32_t (ff.first_char ()) || c >= uint32_t (ff.n_chars ()) + ff.first_char ()) {
|
||||
// NOTE: '?' needs to be a valid character always
|
||||
c = uint32_t ('?');
|
||||
}
|
||||
|
||||
size_t cc = c; // to suppress a compiler warning ..
|
||||
if (c >= ff.first_char () && cc < size_t (ff.n_chars ()) + size_t (ff.first_char ())
|
||||
&& xx > -100.0 && xx < double (width ())) {
|
||||
if (xx > -100.0 && xx < double (width ())) {
|
||||
fill_pattern (int (y + 0.5), int (floor (xx)), ff.data () + (c - ff.first_char ()) * ff.height () * ff.stride (), ff.stride (), ff.height ());
|
||||
}
|
||||
|
||||
|
|
@ -897,11 +868,7 @@ Bitmap::render_text (const lay::RenderText &text)
|
|||
}
|
||||
|
||||
// next line
|
||||
if (*cp1 == '\012' || *cp1 == '\015') {
|
||||
if (*cp1 == '\015' && cp1[1] == '\012') {
|
||||
++cp1;
|
||||
}
|
||||
++cp1;
|
||||
if (tl::skip_newline (cp1)) {
|
||||
y -= double (ff.line_height ());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -894,5 +894,5 @@ InstFinder::visit_cell (const db::Cell &cell, const db::Box &search_box, const d
|
|||
|
||||
}
|
||||
|
||||
} // namespace edt
|
||||
} // namespace lay
|
||||
|
||||
|
|
|
|||
|
|
@ -320,6 +320,11 @@ public:
|
|||
return m_line_styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of ViewObjectCanvas: Resolution
|
||||
*/
|
||||
double resolution () const;
|
||||
|
||||
/**
|
||||
* @brief Reimplementation of ViewObjectCanvas: Background color
|
||||
*/
|
||||
|
|
@ -444,8 +449,6 @@ private:
|
|||
void do_redraw_all (bool force_redraw = true);
|
||||
|
||||
void prepare_drawing ();
|
||||
virtual double resolution () const;
|
||||
|
||||
const std::vector<ViewOp> &scaled_view_ops (unsigned int lw);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1721,6 +1721,14 @@ public:
|
|||
return mp_canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the canvas object (const version)
|
||||
*/
|
||||
const lay::LayoutCanvas *canvas () const
|
||||
{
|
||||
return mp_canvas;
|
||||
}
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
/**
|
||||
* @brief Gets the layer control panel
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2023 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "layTextInfo.h"
|
||||
#include "layFixedFont.h"
|
||||
#include "layLayoutViewBase.h"
|
||||
#include "layLayoutCanvas.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
TextInfo::TextInfo (const LayoutViewBase *view, const db::DCplxTrans &vp_trans)
|
||||
: m_default_text_size (view->default_text_size ()),
|
||||
m_default_font (db::Font (view->text_font ())),
|
||||
m_apply_text_trans (view->apply_text_trans ()),
|
||||
m_resolution (view->canvas ()->resolution ()),
|
||||
m_vp_trans (vp_trans)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
TextInfo::TextInfo (double default_text_size, const db::Font &default_font, bool apply_text_trans, double resolution, const db::DCplxTrans &vp_trans)
|
||||
: m_default_text_size (default_text_size),
|
||||
m_default_font (default_font),
|
||||
m_apply_text_trans (apply_text_trans),
|
||||
m_resolution (resolution),
|
||||
m_vp_trans (vp_trans)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
db::DBox
|
||||
TextInfo::get_bbox (const db::DText &text) const
|
||||
{
|
||||
// offset in pixels (space between origin and text)
|
||||
const double offset = 2.0;
|
||||
|
||||
db::DFTrans fp (db::DFTrans::r0);
|
||||
db::DCoord h;
|
||||
db::Font font = text.font () == db::NoFont ? m_default_font : text.font ();
|
||||
|
||||
if (m_apply_text_trans && font != db::NoFont && font != db::DefaultFont) {
|
||||
fp = db::DFTrans (m_vp_trans.fp_trans () * text.trans ().fp_trans ());
|
||||
h = m_vp_trans.ctrans (text.size () > 0 ? text.size () : m_default_text_size);
|
||||
} else {
|
||||
h = m_vp_trans.ctrans (m_default_text_size);
|
||||
}
|
||||
|
||||
db::HAlign halign = text.halign ();
|
||||
db::VAlign valign = text.valign ();
|
||||
|
||||
double fy = 0.0;
|
||||
if (valign == db::VAlignBottom || valign == db::NoVAlign) {
|
||||
fy = 1.0;
|
||||
} else if (valign == db::VAlignTop) {
|
||||
fy = -1.0;
|
||||
}
|
||||
|
||||
double fx = 0.0;
|
||||
if (halign == db::HAlignLeft || halign == db::NoHAlign) {
|
||||
fx = 1.0;
|
||||
} else if (halign == db::HAlignRight) {
|
||||
fx = -1.0;
|
||||
}
|
||||
|
||||
db::DVector tp1 (fx * offset, fy * offset + (fy - 1) * 0.5 * h);
|
||||
db::DVector tp2 (fx * offset, fy * offset + (fy + 1) * 0.5 * h);
|
||||
db::DPoint dp = db::DPoint () + text.trans ().disp ();
|
||||
|
||||
db::DBox b (dp + fp (tp1), dp + fp (tp2));
|
||||
|
||||
if (font == db::DefaultFont) {
|
||||
|
||||
const lay::FixedFont &ff = lay::FixedFont::get_font (m_resolution);
|
||||
|
||||
// count the lines
|
||||
|
||||
unsigned int lines = 1;
|
||||
for (const char *cp = text.string (); *cp; ) {
|
||||
if (tl::skip_newline (cp)) {
|
||||
++lines;
|
||||
} else {
|
||||
tl::utf32_from_utf8 (cp);
|
||||
}
|
||||
}
|
||||
|
||||
// compute the actual top left position
|
||||
double ytop;
|
||||
if (valign == db::VAlignBottom || valign == db::NoVAlign) {
|
||||
ytop = b.bottom ();
|
||||
ytop += double (ff.line_height () * (lines - 1) + ff.height ());
|
||||
} else if (valign == db::VAlignCenter) {
|
||||
ytop = b.center ().y ();
|
||||
ytop += double ((ff.line_height () * (lines - 1) + ff.height ()) / 2);
|
||||
} else {
|
||||
ytop = b.top ();
|
||||
}
|
||||
|
||||
// compute the bottom position
|
||||
double ybottom = ytop - ff.line_height () * (lines - 1);
|
||||
|
||||
// left and right position
|
||||
bool first = false;
|
||||
double xleft = 0.0, xright = 0.0;
|
||||
|
||||
const char *cp = text.string ();
|
||||
while (*cp) {
|
||||
|
||||
unsigned int length = 0;
|
||||
while (*cp && !tl::skip_newline (cp)) {
|
||||
tl::utf32_from_utf8 (cp);
|
||||
++length;
|
||||
}
|
||||
|
||||
double xl;
|
||||
if (halign == db::HAlignRight) {
|
||||
xl = b.right ();
|
||||
xl -= double (ff.width () * length);
|
||||
} else if (halign == db::HAlignCenter) {
|
||||
xl = b.center ().x ();
|
||||
xl -= double (ff.width () * length / 2);
|
||||
} else {
|
||||
xl = b.left ();
|
||||
}
|
||||
xl -= 0.5;
|
||||
|
||||
double xr = xl + double (ff.width () * length);
|
||||
|
||||
if (first || xl < xleft) {
|
||||
xleft = xl;
|
||||
}
|
||||
if (first || xr > xright) {
|
||||
xright = xr;
|
||||
}
|
||||
first = false;
|
||||
|
||||
}
|
||||
|
||||
return db::DBox (xleft, ybottom, xright, ytop).transformed (m_vp_trans.inverted ());
|
||||
|
||||
} else {
|
||||
|
||||
db::DHershey ht (text.string (), font);
|
||||
ht.justify (b.transformed (m_vp_trans.inverted ()), halign, valign);
|
||||
return ht.bbox ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2023 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HDR_layTextInfo
|
||||
#define HDR_layTextInfo
|
||||
|
||||
#include "laybasicCommon.h"
|
||||
|
||||
#include "dbText.h"
|
||||
#include "dbBox.h"
|
||||
|
||||
namespace lay
|
||||
{
|
||||
|
||||
class LayoutViewBase;
|
||||
|
||||
/**
|
||||
* @brief A class providing information about a text's visual bounding box
|
||||
*
|
||||
* The class can act as a BoxConverter.
|
||||
*/
|
||||
class LAYBASIC_PUBLIC TextInfo
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param view The LayoutView from which to take the text display parameters
|
||||
* @param vp_trans The effective micron-to-pixel transformation
|
||||
*/
|
||||
TextInfo (const LayoutViewBase *view, const db::DCplxTrans &vp_trans);
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param default_text_size The default text size in micron
|
||||
* @param default_font The default font
|
||||
* @param apply_text_trans True if text transformations are to be applied
|
||||
* @param resolution The resolution value (logical pixel size per physical unit pixel)
|
||||
* @param vp_trans The effective micron-to-pixel transformation
|
||||
*/
|
||||
TextInfo (double default_text_size, const db::Font &default_font, bool apply_text_trans, double resolution, const db::DCplxTrans &vp_trans);
|
||||
|
||||
/**
|
||||
* @brief Gets the visual bounding box of the given DText object
|
||||
*
|
||||
* The visual bounding box is returned in micrometer units.
|
||||
* It encloses the glyphs of the text, taking into account the
|
||||
* text view settings by the view.
|
||||
*/
|
||||
db::DBox operator() (const db::DText &text) const
|
||||
{
|
||||
return get_bbox (text);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_default_text_size;
|
||||
db::Font m_default_font;
|
||||
bool m_apply_text_trans;
|
||||
double m_resolution;
|
||||
db::DCplxTrans m_vp_trans;
|
||||
|
||||
db::DBox get_bbox (const db::DText &text) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -52,6 +52,7 @@ SOURCES += \
|
|||
layEditable.cc \
|
||||
layEditorServiceBase.cc \
|
||||
layFinder.cc \
|
||||
layTextInfo.cc \
|
||||
layFixedFont.cc \
|
||||
layLayoutCanvas.cc \
|
||||
layLineStylePalette.cc \
|
||||
|
|
@ -104,6 +105,7 @@ HEADERS += \
|
|||
layEditorServiceBase.h \
|
||||
layLayoutCanvas.h \
|
||||
layFinder.h \
|
||||
layTextInfo.h \
|
||||
layFixedFont.h \
|
||||
layLayoutViewBase.h \
|
||||
layLineStylePalette.h \
|
||||
|
|
|
|||
|
|
@ -210,6 +210,22 @@ inline bool safe_isspace (char c)
|
|||
return c != 0 && static_cast<unsigned char> (c) < 0x80 && isspace (c);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Utility: skip a newline
|
||||
|
||||
bool skip_newline (const char *&cp)
|
||||
{
|
||||
if (*cp == '\012' || *cp == '\015') {
|
||||
if (*cp == '\015' && cp[1] == '\012') {
|
||||
++cp;
|
||||
}
|
||||
++cp;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Utility: a strtod version that is independent of the locale
|
||||
|
||||
|
|
|
|||
|
|
@ -987,6 +987,37 @@ TL_PUBLIC uint32_t utf32_upcase (uint32_t c32);
|
|||
*/
|
||||
TL_PUBLIC uint32_t utf32_from_utf8 (const char *&cp, const char *cpe = 0);
|
||||
|
||||
/**
|
||||
* @brief Checks if the next characters are CR, LF or CR+LF and skips them
|
||||
*
|
||||
* This function returns true, if a line separated was found and skipped
|
||||
*/
|
||||
TL_PUBLIC bool skip_newline (const char *&cp);
|
||||
|
||||
/**
|
||||
* @brief checks if the given character is a CR character
|
||||
*/
|
||||
inline bool is_cr (char c)
|
||||
{
|
||||
return c == '\015';
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief checks if the given character is a LF character
|
||||
*/
|
||||
inline bool is_lf (char c)
|
||||
{
|
||||
return c == '\012';
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief checks if the given character is a CR or LF character
|
||||
*/
|
||||
inline bool is_newline (char c)
|
||||
{
|
||||
return is_cr (c) || is_lf (c);
|
||||
}
|
||||
|
||||
} // namespace tl
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue