Merge lp:~cern-kicad/kicad/bugfix_1256302 into lp:kicad/product
- bugfix_1256302
- Merge into product
Status: | Merged |
---|---|
Merged at revision: | 4522 |
Proposed branch: | lp:~cern-kicad/kicad/bugfix_1256302 |
Merge into: | lp:kicad/product |
Diff against target: |
608 lines (+199/-142) 5 files modified
common/gal/stroke_font.cpp (+141/-111) common/worksheet_viewitem.cpp (+1/-1) include/gal/graphics_abstraction_layer.h (+1/-1) include/gal/stroke_font.h (+50/-22) pcbnew/pcb_painter.cpp (+6/-7) |
To merge this branch: | bzr merge lp:~cern-kicad/kicad/bugfix_1256302 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Maciej Suminski | Needs Resubmitting | ||
KiCad Lead Developers | Pending | ||
Review via email: mp+197860@code.launchpad.net |
Commit message
Description of the change
Dick Hollenbeck (dickelbeck) wrote : | # |
- 4520. By Maciej Suminski
-
Changed std::wstring to wxString.
- 4521. By Maciej Suminski
-
Glyphs and their bounding boxes are held in vectors instead of deque.
Moved scaling of font glyphs to the moment when they are created (eliminated a few multiplications unnecessary variables).
Changed some magic numbers into constants. - 4522. By Maciej Suminski
-
Tilda handling for STROKE_FONT class.
- 4523. By Maciej Suminski
-
DIfferent handling of italic texts, depending on the mirroring setting.
Maciej Suminski (orsonmmz) wrote : | # |
A lesson was learned, I modified the STROKE_TEXT functions to handle wxStrings, as it was the easiest solution and added some other missing features.
I guess that a specialized class for handling strings could save some pain. It could be particularly helpful now, when it is no more only wx2.8 & wx2.9.4, but also evolving wx3.0.
Dick Hollenbeck (dickelbeck) wrote : | # |
was it just an oversight or is there some reason that you are passing wxString to the STROKE_TEXT API functions by value rather than by const reference?
Maciej Suminski (orsonmmz) wrote : | # |
It was an oversight, in the previous implementation the string was split in place and the Draw() function was called recursively, but it is not the case anymore.
Thanks for noting, it is fixed in the last commit. I also did some reformatting and I hope I will not touch that part for a long time.
Dick Hollenbeck (dickelbeck) wrote : | # |
On 12/05/2013 01:48 PM, Maciej Sumiński wrote:
> It was an oversight, in the previous implementation the string was split in place and the Draw() function was called recursively, but it is not the case anymore.
> Thanks for noting, it is fixed in the last commit. I also did some reformatting and I hope I will not touch that part for a long time.
>
Sorry, I already committed the branch.
Maciej Suminski (orsonmmz) wrote : | # |
The most important change was introduced by you, so it is fine.
Preview Diff
1 | === modified file 'common/gal/stroke_font.cpp' |
2 | --- common/gal/stroke_font.cpp 2013-10-30 20:07:52 +0000 |
3 | +++ common/gal/stroke_font.cpp 2013-12-05 16:07:56 +0000 |
4 | @@ -3,6 +3,8 @@ |
5 | * |
6 | * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de |
7 | * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. |
8 | + * Copyright (C) 2013 CERN |
9 | + * @author Maciej Suminski <maciej.suminski@cern.ch> |
10 | * |
11 | * Stroke font class |
12 | * |
13 | @@ -26,12 +28,13 @@ |
14 | |
15 | #include <gal/stroke_font.h> |
16 | #include <gal/graphics_abstraction_layer.h> |
17 | +#include <wx/string.h> |
18 | |
19 | using namespace KIGFX; |
20 | |
21 | - |
22 | -const double STROKE_FONT::LINE_HEIGHT_RATIO = 1.6; |
23 | - |
24 | +const double STROKE_FONT::OVERBAR_HEIGHT = 0.45; |
25 | +const double STROKE_FONT::BOLD_FACTOR = 1.3; |
26 | +const double STROKE_FONT::HERSHEY_SCALE = 1.0 / 21.0; |
27 | |
28 | STROKE_FONT::STROKE_FONT( GAL* aGal ) : |
29 | m_gal( aGal ), |
30 | @@ -40,22 +43,18 @@ |
31 | m_mirrored( false ) |
32 | { |
33 | // Default values |
34 | - m_scaleFactor = 1.0 / 21.0; |
35 | m_glyphSize = VECTOR2D( 10.0, 10.0 ); |
36 | m_verticalJustify = GR_TEXT_VJUSTIFY_BOTTOM; |
37 | m_horizontalJustify = GR_TEXT_HJUSTIFY_LEFT; |
38 | } |
39 | |
40 | |
41 | -STROKE_FONT::~STROKE_FONT() |
42 | -{ |
43 | -} |
44 | - |
45 | - |
46 | bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNewStrokeFontSize ) |
47 | { |
48 | m_glyphs.clear(); |
49 | m_glyphBoundingBoxes.clear(); |
50 | + m_glyphs.resize( aNewStrokeFontSize ); |
51 | + m_glyphBoundingBoxes.resize( aNewStrokeFontSize ); |
52 | |
53 | for( int j = 0; j < aNewStrokeFontSize; j++ ) |
54 | { |
55 | @@ -81,8 +80,8 @@ |
56 | if( i < 2 ) |
57 | { |
58 | // The first two values contain the width of the char |
59 | - glyphStartX = coordinate[0] - 'R'; |
60 | - glyphEndX = coordinate[1] - 'R'; |
61 | + glyphStartX = ( coordinate[0] - 'R' ) * HERSHEY_SCALE; |
62 | + glyphEndX = ( coordinate[1] - 'R' ) * HERSHEY_SCALE; |
63 | glyphBoundingX = VECTOR2D( 0, glyphEndX - glyphStartX ); |
64 | } |
65 | else if( ( coordinate[0] == ' ' ) && ( coordinate[1] == 'R' ) ) |
66 | @@ -97,8 +96,8 @@ |
67 | { |
68 | // Every coordinate description of the Hershey format has an offset, |
69 | // it has to be subtracted |
70 | - point.x = (double) ( coordinate[0] - 'R' ) - glyphStartX; |
71 | - point.y = (double) ( coordinate[1] - 'R' ) - 11.0; |
72 | + point.x = (double) ( coordinate[0] - 'R' ) * HERSHEY_SCALE - glyphStartX; |
73 | + point.y = (double) ( coordinate[1] - 'R' ) * HERSHEY_SCALE; |
74 | pointList.push_back( point ); |
75 | } |
76 | |
77 | @@ -108,16 +107,22 @@ |
78 | if( pointList.size() > 0 ) |
79 | glyph.push_back( pointList ); |
80 | |
81 | - m_glyphs.push_back( glyph ); |
82 | + m_glyphs[j] = glyph; |
83 | |
84 | // Compute the bounding box of the glyph |
85 | - m_glyphBoundingBoxes.push_back( computeBoundingBox( glyph, glyphBoundingX ) ); |
86 | + m_glyphBoundingBoxes[j] = computeBoundingBox( glyph, glyphBoundingX ); |
87 | } |
88 | |
89 | return true; |
90 | } |
91 | |
92 | |
93 | +int STROKE_FONT::getInterline() const |
94 | +{ |
95 | + return ( m_glyphSize.y * 14 ) / 10 + m_gal->GetLineWidth(); |
96 | +} |
97 | + |
98 | + |
99 | BOX2D STROKE_FONT::computeBoundingBox( const GLYPH& aGLYPH, const VECTOR2D& aGLYPHBoundingX ) const |
100 | { |
101 | BOX2D boundingBox; |
102 | @@ -142,133 +147,160 @@ |
103 | } |
104 | |
105 | |
106 | -void STROKE_FONT::Draw( std::string aText, const VECTOR2D& aPosition, double aRotationAngle ) |
107 | +void STROKE_FONT::Draw( wxString aText, const VECTOR2D& aPosition, double aRotationAngle ) |
108 | { |
109 | - // By default overbar is turned off |
110 | - m_overbar = false; |
111 | - |
112 | // Context needs to be saved before any transformations |
113 | m_gal->Save(); |
114 | |
115 | m_gal->Translate( aPosition ); |
116 | + |
117 | + // Single line height |
118 | + int lineHeight = getInterline(); |
119 | + |
120 | + // The overall height of all lines of text |
121 | + double textBlockHeight = lineHeight * ( linesCount( aText ) - 1 ); |
122 | + |
123 | + switch( m_verticalJustify ) |
124 | + { |
125 | + case GR_TEXT_VJUSTIFY_CENTER: |
126 | + m_gal->Translate( VECTOR2D( 0, -textBlockHeight / 2.0 ) ); |
127 | + break; |
128 | + |
129 | + case GR_TEXT_VJUSTIFY_BOTTOM: |
130 | + m_gal->Translate( VECTOR2D( 0, -textBlockHeight ) ); |
131 | + break; |
132 | + |
133 | + case GR_TEXT_VJUSTIFY_TOP: |
134 | + break; |
135 | + |
136 | + default: |
137 | + break; |
138 | + } |
139 | + |
140 | m_gal->Rotate( -aRotationAngle ); |
141 | |
142 | + m_gal->SetIsStroke( true ); |
143 | + m_gal->SetIsFill( false ); |
144 | + |
145 | + if( m_bold ) |
146 | + m_gal->SetLineWidth( m_gal->GetLineWidth() * BOLD_FACTOR ); |
147 | + |
148 | // Split multiline strings into separate ones and draw them line by line |
149 | - size_t newlinePos = aText.find( '\n' ); |
150 | + int begin = 0; |
151 | + int newlinePos = aText.Find( '\n' ); |
152 | |
153 | - if( newlinePos != std::string::npos ) |
154 | + while( newlinePos != wxNOT_FOUND ) |
155 | { |
156 | - VECTOR2D nextlinePosition = VECTOR2D( 0.0, m_glyphSize.y * LINE_HEIGHT_RATIO ); |
157 | + size_t length = newlinePos - begin; |
158 | + drawSingleLineText( aText.Mid( begin, length ) ); |
159 | + m_gal->Translate( VECTOR2D( 0.0, lineHeight ) ); |
160 | |
161 | - Draw( aText.substr( newlinePos + 1 ), nextlinePosition, 0.0 ); |
162 | - aText = aText.substr( 0, newlinePos ); |
163 | + begin = newlinePos + 1; |
164 | + newlinePos = aText.find( '\n', begin + 1 ); |
165 | } |
166 | |
167 | + // Draw the last (or the only one) line |
168 | + if( !aText.IsEmpty() ) |
169 | + drawSingleLineText( aText.Mid( begin ) ); |
170 | + |
171 | + m_gal->Restore(); |
172 | +} |
173 | + |
174 | + |
175 | +void STROKE_FONT::drawSingleLineText( const wxString& aText ) |
176 | +{ |
177 | + // By default the overbar is turned off |
178 | + m_overbar = false; |
179 | + |
180 | + double xOffset; |
181 | + VECTOR2D glyphSize( m_glyphSize ); |
182 | + |
183 | // Compute the text size |
184 | - VECTOR2D textsize = computeTextSize( aText ); |
185 | + VECTOR2D textSize = computeTextSize( aText ); |
186 | + |
187 | + m_gal->Save(); |
188 | |
189 | // Adjust the text position to the given alignment |
190 | switch( m_horizontalJustify ) |
191 | { |
192 | case GR_TEXT_HJUSTIFY_CENTER: |
193 | - m_gal->Translate( VECTOR2D( -textsize.x / 2.0, 0 ) ); |
194 | + m_gal->Translate( VECTOR2D( -textSize.x / 2.0, 0 ) ); |
195 | break; |
196 | |
197 | case GR_TEXT_HJUSTIFY_RIGHT: |
198 | if( !m_mirrored ) |
199 | - m_gal->Translate( VECTOR2D( -textsize.x, 0 ) ); |
200 | - |
201 | + m_gal->Translate( VECTOR2D( -textSize.x, 0 ) ); |
202 | break; |
203 | |
204 | case GR_TEXT_HJUSTIFY_LEFT: |
205 | if( m_mirrored ) |
206 | - m_gal->Translate( VECTOR2D( -textsize.x, 0 ) ); |
207 | - |
208 | - break; |
209 | - |
210 | - default: |
211 | - break; |
212 | - } |
213 | - |
214 | - switch( m_verticalJustify ) |
215 | - { |
216 | - case GR_TEXT_VJUSTIFY_CENTER: |
217 | - m_gal->Translate( VECTOR2D( 0, textsize.y / 2.0 ) ); |
218 | - break; |
219 | - |
220 | - case GR_TEXT_VJUSTIFY_TOP: |
221 | - m_gal->Translate( VECTOR2D( 0, textsize.y ) ); |
222 | - break; |
223 | - |
224 | - case GR_TEXT_VJUSTIFY_BOTTOM: |
225 | - break; |
226 | - |
227 | - default: |
228 | - break; |
229 | - } |
230 | - |
231 | - double xOffset, glyphSizeX; |
232 | + m_gal->Translate( VECTOR2D( -textSize.x, 0 ) ); |
233 | + break; |
234 | + |
235 | + default: |
236 | + break; |
237 | + } |
238 | |
239 | if( m_mirrored ) |
240 | { |
241 | // In case of mirrored text invert the X scale of points and their X direction |
242 | // (m_glyphSize.x) and start drawing from the position where text normally should end |
243 | - // (textsize.x) |
244 | - xOffset = textsize.x; |
245 | - glyphSizeX = -m_glyphSize.x; |
246 | - } |
247 | - else |
248 | - { |
249 | - xOffset = 0.0; |
250 | - glyphSizeX = m_glyphSize.x; |
251 | - } |
252 | - double scaleY = m_scaleFactor * m_glyphSize.y; |
253 | - double scaleX = m_scaleFactor * glyphSizeX; |
254 | - |
255 | - m_gal->SetIsStroke( true ); |
256 | - m_gal->SetIsFill( false ); |
257 | - |
258 | - if( m_bold ) |
259 | - { |
260 | - m_gal->SetLineWidth( m_gal->GetLineWidth() * 1.3 ); |
261 | - } |
262 | - |
263 | - for( std::string::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) |
264 | - { |
265 | + // (textSize.x) |
266 | + xOffset = textSize.x; |
267 | + glyphSize.x = -m_glyphSize.x; |
268 | + } else |
269 | + { |
270 | + xOffset = 0.0; |
271 | + } |
272 | + |
273 | + for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); ++chIt ) |
274 | + { |
275 | + // Toggle overbar |
276 | if( *chIt == '~' ) |
277 | { |
278 | - m_overbar = !m_overbar; |
279 | - continue; |
280 | + if( ++chIt == aText.end() ) |
281 | + break; |
282 | + |
283 | + if( *chIt != '~' ) // It was a single tilda, it toggles overbar |
284 | + m_overbar = !m_overbar; |
285 | + |
286 | + // If it is a double tilda, just process the second one |
287 | } |
288 | |
289 | - GLYPH_LIST::iterator glyphIt = m_glyphs.begin(); |
290 | - std::deque<BOX2D>::iterator bbIt = m_glyphBoundingBoxes.begin(); |
291 | - |
292 | - unsigned dd = (unsigned) ((unsigned char) *chIt ) - (unsigned) ' '; |
293 | - |
294 | - if( dd >= m_glyphBoundingBoxes.size() ) |
295 | + unsigned dd = *chIt - ' '; |
296 | + |
297 | + if( dd >= m_glyphBoundingBoxes.size() || dd < 0 ) |
298 | dd = '?' - ' '; |
299 | |
300 | - advance( glyphIt, dd ); |
301 | - advance( bbIt, dd ); |
302 | + GLYPH& glyph = m_glyphs[dd]; |
303 | + BOX2D& bbox = m_glyphBoundingBoxes[dd]; |
304 | |
305 | - GLYPH glyph = *glyphIt; |
306 | + if( m_overbar ) |
307 | + { |
308 | + VECTOR2D startOverbar( xOffset, -getInterline() * OVERBAR_HEIGHT ); |
309 | + VECTOR2D endOverbar( xOffset + glyphSize.x * bbox.GetEnd().x, |
310 | + -getInterline() * OVERBAR_HEIGHT ); |
311 | + m_gal->DrawLine( startOverbar, endOverbar ); |
312 | + } |
313 | |
314 | for( GLYPH::iterator pointListIt = glyph.begin(); pointListIt != glyph.end(); |
315 | - pointListIt++ ) |
316 | + ++pointListIt ) |
317 | { |
318 | std::deque<VECTOR2D> pointListScaled; |
319 | |
320 | for( std::deque<VECTOR2D>::iterator pointIt = pointListIt->begin(); |
321 | - pointIt != pointListIt->end(); pointIt++ ) |
322 | + pointIt != pointListIt->end(); ++pointIt ) |
323 | { |
324 | - VECTOR2D pointPos( pointIt->x * scaleX + xOffset, pointIt->y * scaleY ); |
325 | + VECTOR2D pointPos( pointIt->x * glyphSize.x + xOffset, pointIt->y * glyphSize.y ); |
326 | |
327 | if( m_italic ) |
328 | { |
329 | // FIXME should be done other way - referring to the lowest Y value of point |
330 | // because now italic fonts are translated a bit |
331 | - pointPos.x += pointPos.y * 0.1; |
332 | + if( m_mirrored ) |
333 | + pointPos.x += pointPos.y * 0.1; |
334 | + else |
335 | + pointPos.x -= pointPos.y * 0.1; |
336 | } |
337 | |
338 | pointListScaled.push_back( pointPos ); |
339 | @@ -277,39 +309,37 @@ |
340 | m_gal->DrawPolyline( pointListScaled ); |
341 | } |
342 | |
343 | - if( m_overbar ) |
344 | - { |
345 | - VECTOR2D startOverbar( xOffset, -textsize.y * 1.2 ); |
346 | - VECTOR2D endOverbar( xOffset + m_scaleFactor * glyphSizeX * bbIt->GetEnd().x, |
347 | - -textsize.y * 1.2 ); |
348 | - m_gal->DrawLine( startOverbar, endOverbar ); |
349 | - } |
350 | - |
351 | - xOffset += m_scaleFactor * glyphSizeX * bbIt->GetEnd().x; |
352 | + xOffset += glyphSize.x * bbox.GetEnd().x; |
353 | } |
354 | |
355 | m_gal->Restore(); |
356 | } |
357 | |
358 | |
359 | -VECTOR2D STROKE_FONT::computeTextSize( const std::string& aText ) const |
360 | +VECTOR2D STROKE_FONT::computeTextSize( const wxString& aText ) const |
361 | { |
362 | VECTOR2D result = VECTOR2D( 0.0, m_glyphSize.y ); |
363 | |
364 | - for( std::string::const_iterator chIt = aText.begin(); chIt != aText.end(); chIt++ ) |
365 | + for( wxString::const_iterator chIt = aText.begin(); chIt != aText.end(); ++chIt ) |
366 | { |
367 | + wxASSERT_MSG( *chIt != '\n', |
368 | + wxT( "This function is intended to work with single line strings" ) ); |
369 | + |
370 | + // If it is double tilda, then it is displayed as a single tilda |
371 | + // If it is single tilda, then it is toggling overbar, so we need to skip it |
372 | if( *chIt == '~' ) |
373 | - continue; |
374 | - |
375 | - std::deque<BOX2D>::const_iterator bbIt = m_glyphBoundingBoxes.begin(); |
376 | - unsigned dd = (unsigned) ((unsigned char)*chIt) - (unsigned) ' '; |
377 | - |
378 | - if( dd >= m_glyphBoundingBoxes.size() ) |
379 | + { |
380 | + if( ++chIt == aText.end() ) |
381 | + break; |
382 | + } |
383 | + |
384 | + // Index in the bounding boxes table |
385 | + unsigned dd = *chIt - ' '; |
386 | + |
387 | + if( dd >= m_glyphBoundingBoxes.size() || dd < 0 ) |
388 | dd = '?' - ' '; |
389 | |
390 | - advance( bbIt, dd ); |
391 | - |
392 | - result.x += m_scaleFactor * m_glyphSize.x * bbIt->GetEnd().x; |
393 | + result.x += m_glyphSize.x * m_glyphBoundingBoxes[dd].GetEnd().x; |
394 | } |
395 | |
396 | return result; |
397 | |
398 | === modified file 'common/worksheet_viewitem.cpp' |
399 | --- common/worksheet_viewitem.cpp 2013-10-31 21:30:57 +0000 |
400 | +++ common/worksheet_viewitem.cpp 2013-12-05 16:07:56 +0000 |
401 | @@ -191,7 +191,7 @@ |
402 | aGal->SetStrokeColor( COLOR4D( aItem->GetColor() ) ); |
403 | aGal->SetLineWidth( aItem->GetThickness() ); |
404 | aGal->SetTextAttributes( aItem ); |
405 | - aGal->StrokeText( std::string( aItem->GetText().mb_str() ), position, 0.0 ); |
406 | + aGal->StrokeText( std::wstring( aItem->GetText().wc_str() ), position, 0.0 ); |
407 | } |
408 | |
409 | |
410 | |
411 | === modified file 'include/gal/graphics_abstraction_layer.h' |
412 | --- include/gal/graphics_abstraction_layer.h 2013-10-14 18:40:36 +0000 |
413 | +++ include/gal/graphics_abstraction_layer.h 2013-12-05 16:07:56 +0000 |
414 | @@ -277,7 +277,7 @@ |
415 | * @param aPosition is the text position in world coordinates. |
416 | * @param aRotationAngle is the text rotation angle. |
417 | */ |
418 | - inline virtual void StrokeText( const std::string& aText, const VECTOR2D& aPosition, |
419 | + inline virtual void StrokeText( const wxString& aText, const VECTOR2D& aPosition, |
420 | double aRotationAngle ) |
421 | { |
422 | strokeFont.Draw( aText, aPosition, aRotationAngle ); |
423 | |
424 | === modified file 'include/gal/stroke_font.h' |
425 | --- include/gal/stroke_font.h 2013-10-14 18:40:36 +0000 |
426 | +++ include/gal/stroke_font.h 2013-12-05 16:07:56 +0000 |
427 | @@ -3,6 +3,8 @@ |
428 | * |
429 | * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de |
430 | * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. |
431 | + * Copyright (C) 2013 CERN |
432 | + * @author Maciej Suminski <maciej.suminski@cern.ch> |
433 | * |
434 | * Stroke font class |
435 | * |
436 | @@ -39,7 +41,7 @@ |
437 | class GAL; |
438 | |
439 | typedef std::deque< std::deque<VECTOR2D> > GLYPH; |
440 | -typedef std::deque<GLYPH> GLYPH_LIST; |
441 | +typedef std::vector<GLYPH> GLYPH_LIST; |
442 | |
443 | /** |
444 | * @brief Class STROKE_FONT implements stroke font drawing. |
445 | @@ -52,11 +54,6 @@ |
446 | /// Constructor |
447 | STROKE_FONT( GAL* aGal ); |
448 | |
449 | - /// Destructor |
450 | - ~STROKE_FONT(); |
451 | - |
452 | - // TODO Load font from a text file |
453 | - |
454 | /** |
455 | * @brief Load the new stroke font. |
456 | * |
457 | @@ -73,17 +70,7 @@ |
458 | * @param aPosition is the text position in world coordinates. |
459 | * @param aRotationAngle is the text rotation angle. |
460 | */ |
461 | - void Draw( std::string aText, const VECTOR2D& aPosition, double aRotationAngle ); |
462 | - |
463 | - /** |
464 | - * @brief Set the scale factor of the font for the glyph size. |
465 | - * |
466 | - * @param aScaleFactor is the scale factor of the font. |
467 | - */ |
468 | - inline void SetScaleFactor( const double aScaleFactor ) |
469 | - { |
470 | - m_scaleFactor = aScaleFactor; |
471 | - } |
472 | + void Draw( wxString aText, const VECTOR2D& aPosition, double aRotationAngle ); |
473 | |
474 | /** |
475 | * @brief Set the glyph size. |
476 | @@ -158,14 +145,20 @@ |
477 | private: |
478 | GAL* m_gal; ///< Pointer to the GAL |
479 | GLYPH_LIST m_glyphs; ///< Glyph list |
480 | - std::deque<BOX2D> m_glyphBoundingBoxes; ///< Bounding boxes of the glyphs |
481 | - double m_scaleFactor; ///< Scale factor for the glyph |
482 | + std::vector<BOX2D> m_glyphBoundingBoxes; ///< Bounding boxes of the glyphs |
483 | VECTOR2D m_glyphSize; ///< Size of the glyphs |
484 | EDA_TEXT_HJUSTIFY_T m_horizontalJustify; ///< Horizontal justification |
485 | EDA_TEXT_VJUSTIFY_T m_verticalJustify; ///< Vertical justification |
486 | bool m_bold, m_italic, m_mirrored, m_overbar; ///< Properties of text |
487 | |
488 | /** |
489 | + * @brief Returns a single line height using current settings. |
490 | + * |
491 | + * @return The line height. |
492 | + */ |
493 | + int getInterline() const; |
494 | + |
495 | + /** |
496 | * @brief Compute the bounding box of a given glyph. |
497 | * |
498 | * @param aGlyph is the glyph. |
499 | @@ -175,14 +168,49 @@ |
500 | BOX2D computeBoundingBox( const GLYPH& aGlyph, const VECTOR2D& aGlyphBoundingX ) const; |
501 | |
502 | /** |
503 | + * @brief Draws a single line of text. Multiline texts should be split before using the |
504 | + * function. |
505 | + * |
506 | + * @param aText is the text to be drawn. |
507 | + */ |
508 | + void drawSingleLineText( const wxString& aText ); |
509 | + |
510 | + /** |
511 | * @brief Compute the size of a given text. |
512 | * |
513 | * @param aText is the text string. |
514 | * @return is the text size. |
515 | */ |
516 | - VECTOR2D computeTextSize( const std::string& aText ) const; |
517 | - |
518 | - static const double LINE_HEIGHT_RATIO; |
519 | + VECTOR2D computeTextSize( const wxString& aText ) const; |
520 | + |
521 | + /** |
522 | + * @brief Returns number of lines for a given text. |
523 | + * |
524 | + * @param aText is the text to be checked. |
525 | + * @return Number of lines of aText. |
526 | + */ |
527 | + unsigned int linesCount( const wxString& aText ) const |
528 | + { |
529 | + wxString::const_iterator it, itEnd; |
530 | + unsigned int lines = 1; |
531 | + |
532 | + for( it = aText.begin(), itEnd = aText.end(); it != itEnd; ++it ) |
533 | + { |
534 | + if( *it == '\n' ) |
535 | + ++lines; |
536 | + } |
537 | + |
538 | + return lines; |
539 | + } |
540 | + |
541 | + ///> Factor that determines relative height of overbar. |
542 | + static const double OVERBAR_HEIGHT; |
543 | + |
544 | + ///> Factor that determines relative line width for bold text. |
545 | + static const double BOLD_FACTOR; |
546 | + |
547 | + ///> Scale factor for the glyph |
548 | + static const double HERSHEY_SCALE; |
549 | }; |
550 | } // namespace KIGFX |
551 | |
552 | |
553 | === modified file 'pcbnew/pcb_painter.cpp' |
554 | --- pcbnew/pcb_painter.cpp 2013-11-06 17:17:42 +0000 |
555 | +++ pcbnew/pcb_painter.cpp 2013-12-05 16:07:56 +0000 |
556 | @@ -280,7 +280,7 @@ |
557 | if( !net ) |
558 | return; |
559 | |
560 | - std::string netName = std::string( net->GetShortNetname().mb_str() ); |
561 | + std::wstring netName = std::wstring( net->GetShortNetname().wc_str() ); |
562 | VECTOR2D textPosition = start + line / 2.0; // center of the track |
563 | double textOrientation = -atan( line.y / line.x ); |
564 | double textSize = std::min( static_cast<double>( width ), length / netName.length() ); |
565 | @@ -456,7 +456,7 @@ |
566 | VECTOR2D namesize( tsize, tsize ); |
567 | m_gal->SetGlyphSize( namesize ); |
568 | m_gal->SetLineWidth( namesize.x / 12.0 ); |
569 | - m_gal->StrokeText( std::string( aPad->GetShortNetname().mb_str() ), |
570 | + m_gal->StrokeText( std::wstring( aPad->GetShortNetname().wc_str() ), |
571 | textpos, 0.0 ); |
572 | } |
573 | |
574 | @@ -474,8 +474,7 @@ |
575 | |
576 | m_gal->SetGlyphSize( numsize ); |
577 | m_gal->SetLineWidth( numsize.x / 12.0 ); |
578 | - m_gal->StrokeText( std::string( aPad->GetPadName().mb_str() ), |
579 | - textpos, 0.0 ); |
580 | + m_gal->StrokeText( std::wstring( aPad->GetPadName().wc_str() ), textpos, 0.0 ); |
581 | } |
582 | |
583 | m_gal->Restore(); |
584 | @@ -720,7 +719,7 @@ |
585 | m_gal->SetStrokeColor( strokeColor ); |
586 | m_gal->SetLineWidth( aText->GetThickness() ); |
587 | m_gal->SetTextAttributes( aText ); |
588 | - m_gal->StrokeText( std::string( aText->GetText().mb_str() ), position, orientation ); |
589 | + m_gal->StrokeText( aText->GetText(), position, orientation ); |
590 | } |
591 | |
592 | |
593 | @@ -736,7 +735,7 @@ |
594 | m_gal->SetStrokeColor( strokeColor ); |
595 | m_gal->SetLineWidth( aText->GetThickness() ); |
596 | m_gal->SetTextAttributes( aText ); |
597 | - m_gal->StrokeText( std::string( aText->GetText().mb_str() ), position, orientation ); |
598 | + m_gal->StrokeText( aText->GetText(), position, orientation ); |
599 | } |
600 | |
601 | |
602 | @@ -836,7 +835,7 @@ |
603 | |
604 | m_gal->SetLineWidth( text.GetThickness() ); |
605 | m_gal->SetTextAttributes( &text ); |
606 | - m_gal->StrokeText( std::string( text.GetText().mb_str() ), position, orientation ); |
607 | + m_gal->StrokeText( std::wstring( text.GetText().wc_str() ), position, orientation ); |
608 | } |
609 | |
610 |
I don't think we've used std::wstring before. It's use brings two problems:
a) The width of its characters is platform dependent, because wchar_t is not certainly a given size.
b) It adds more code, since the basic_string<> template is instantiated for this new datatype, yet again.
Certainly b) would be worth it for a string design which met all our needs, but because of a), std::wstring does not.
A simpler, less costly fix is to just use wxString. At some point in the future, wxString datatype could be globally replaced with one of the project's own, but I don't think std:wstring is it.
More likely a derivative of basic_string< uint32_ t> could be crafted to better solve the project's needs, with constructors taking utf8 byte sequences, and conversion operators back to wxString. But that is a topic for a another thread.
For the patch at hand, I'm advocating using wxString with an iterator, which will give you the proper a unicode value as you iterate through the wxString. Then, as long as the unicode value is OK for the vectorizer, this is less code overall, since it makes use of stuff already being linked in.
If you find that usage of wxString in this context is too slow, then you could consider encoding an 8 bit string using an ecoding that the vectorizer is assuming, one that matches unicode encoding in its first 256 positions. This might be LATIN1 or something.
But since we start with wxString, I don't think its a problem to take that as the argument to the STROKE support.