1 //------------------------------------------------------------------------------
2 // emPainter.h
3 //
4 // Copyright (C) 2001,2003-2010,2014,2016-2017,2020 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #ifndef emPainter_h
22 #define emPainter_h
23 
24 #ifndef emModel_h
25 #include <emCore/emModel.h>
26 #endif
27 
28 #ifndef emTexture_h
29 #include <emCore/emTexture.h>
30 #endif
31 
32 #ifndef emThread_h
33 #include <emCore/emThread.h>
34 #endif
35 
36 class emCoreConfig;
37 class emFontCache;
38 
39 
40 //==============================================================================
41 //================================= emPainter ==================================
42 //==============================================================================
43 
44 class emPainter {
45 
46 public:
47 
48 	// Class with methods for painting pixel graphics with full
49 	// anti-aliasing and alpha blending. The anti-aliasing has been driven
50 	// very far here. Therefore the interface looks like for painting vector
51 	// graphics. But there is one topic a programmer should know about:
52 	//
53 	// "Canvas Color"
54 	// ==============
55 	//
56 	// Every paint method has an argument called canvasColor. For getting
57 	// best results, this argument has to be set carefully:
58 	//
59 	// Quick instructions
60 	// ------------------
61 	//
62 	// Whenever painting something over a uni-colored area, and if that
63 	// color is known, it should be given as the argument canvasColor.
64 	// Otherwise a non-opaque color should be given (e.g. 0).
65 	//
66 	// When wondering whether an area is uni-colored or not, you should not
67 	// care about rasterization by pixels. Just imagine all paint operations
68 	// would go to infinite pixel resolution.
69 	//
70 	// More details
71 	// ------------
72 	//
73 	// With a non-opaque canvas color, the classic formula for blending is
74 	// used:
75 	//
76 	//   targetNew = targetOld * (100% - alpha) + source * alpha
77 	//
78 	// Clearly: For anti-aliasing, the intersection of the area of the
79 	// painted object and the area of each pixel is calculated. This results
80 	// in an additional alpha value for each individual pixel. This
81 	// anti-alias-alpha-value is simply multiplied with the general alpha
82 	// value of the operation.
83 	//
84 	// Now, the problem is when painting two objects which are cutting the
85 	// same pixel. The resulting pixel value will not be correct. Here is an
86 	// example: Lets paint two white rectangles on black background. The
87 	// rectangles are not overlapping, but they have a common edge, which
88 	// runs through the center of a pixel (each rectangle gets 50% of the
89 	// pixel). When painting the first rectangle, the formula says for that
90 	// pixel: black * (100% - 50%) + white * 50%, which results "50% white".
91 	// That is correct. But when painting the second rectangle, we have:
92 	// 50% white * (100% - 50%) + white * 50%, which results 75% white. But
93 	// it should be 100%!
94 	//
95 	// With an opaque canvas color, the formula for blending is:
96 	//
97 	//   targetNew = targetOld + (source - canvasColor) * alpha
98 	//
99 	// This is faster, because it allows some pretty optimizations. But the
100 	// main advantage is that this formula does not make the error described
101 	// above. In our example, the first rectangle would result equal for the
102 	// considered pixel: black + (white - black) * 50% = 50% white. And when
103 	// painting the second rectangle, the formula says: 50% white + (white -
104 	// black) * 50% = 100% white, which is correct now. The formula is even
105 	// correct when working with other colors than just black and white,
106 	// when having alpha blending by the source, and when many painted
107 	// objects fall into a pixel.
108 	//
109 	// Of course, there are a lot of situation where the canvas color
110 	// technique cannot be used, because the painted areas are not
111 	// uni-colored, or their color is not known. But these are often
112 	// situations where the errors are not so spectacular. However, a last
113 	// chance could be the method PaintEdgeCorrection (read there).
114 
115 	emPainter();
116 		// Construct a painter which paints nowhere.
117 
118 	emPainter(const emPainter & painter);
119 		// Construct a painter by copying all the settings from another
120 		// painter.
121 		// Arguments:
122 		//   painter - A painter whose settings are to be copied.
123 
124 	emPainter(const emPainter & painter, double clipX1, double clipY1,
125 	          double clipX2, double clipY2);
126 		// Construct a painter by copying all the settings from another
127 		// painter, but intersect the clipping rectangle with a given
128 		// clipping rectangle.
129 		// Arguments:
130 		//   painter   - A painter whose settings are to be copied.
131 		//   clipX1,clipY1,clipX2,clipY2 - The clipping rectangle in
132 		//               pixel coordinates. It will be intersected with
133 		//               the clipping rectangle from the source painter.
134 
135 	emPainter(const emPainter & painter, double clipX1, double clipY1,
136 	          double clipX2, double clipY2, double originX,
137 	          double originY, double scaleX,double scaleY);
138 		// Construct a painter by copying all the settings from another
139 		// painter, but intersect the clipping rectangle with a given
140 		// clipping rectangle, and set another transformation.
141 		// Arguments:
142 		//   painter         - A painter whose settings are to be
143 		//                     copied.
144 		//   clipX1,clipY1,clipX2,clipY2 - The clipping rectangle in
145 		//                     pixel coordinates. It will be intersected
146 		//                     with the clipping rectangle from the
147 		//                     source painter.
148 		//   originX,originY - The new origin (see SetOrigin).
149 		//   scaleX,scaleY   - The new scale factors (see SetScaling).
150 
151 	emPainter(emRootContext & rootContext, void * map, int bytesPerRow,
152 	          int bytesPerPixel, emUInt32 redMask, emUInt32 greenMask,
153 	          emUInt32 blueMask, double clipX1, double clipY1,
154 	          double clipX2, double clipY2, double originX=0,
155 	          double originY=0, double scaleX=1, double scaleY=1,
156 	          emThreadMiniMutex * userSpaceMutex=NULL,
157 	          bool * usmLockedByThisThread=NULL);
158 		// Construct a painter from scratch. The output bitmap is
159 		// addressed with:
160 		//   pixelValue = ((TYPE*)(map+y*bytesPerRow)))[x]
161 		// Where:
162 		//   x is the X-coordinate of the pixel in the range of
163 		//   (int)clipX1 to (int)ceil(clipX2)-1.
164 		//   y is the Y-coordinate of the pixel in the range of
165 		//   (int)clipY1 to (int)ceil(clipY2)-1.
166 		//   TYPE is an 8, 16 or 32-bit integer type, according to
167 		//   bytesPerPixel.
168 		//   pixelValue is the pixel color consisting of three
169 		//   channels, according to redMask, greenMask and blueMask.
170 		// Arguments:
171 		//   rootContext     - The root context.
172 		//   map             - Pointer to the output bitmap.
173 		//   bytesPerRow     - Size of a row in the map, in bytes.
174 		//   bytesPerPixel   - Size of a pixel in the map, in bytes.
175 		//                     This must be 1, 2 or 4.
176 		//   redMask         - A bit mask which denotes the red channel
177 		//                     within a pixel value.
178 		//   greenMask       - A bit mask which denotes the green
179 		//                     channel within a pixel value.
180 		//   blueMask        - A bit mask which denotes the blue channel
181 		//                     within a pixel value.
182 		//   clipX1,clipY1,clipX2,clipY2 - The clipping rectangle (see
183 		//                     SetClipping).
184 		//   originX,originY - The origin (see SetOrigin).
185 		//   scaleX,scaleY   - The scale factors (see SetScaling).
186 		//   userSpaceMutex  - See SetUserSpaceMutex.
187 		//   usmLockedByThisThread - See SetUserSpaceMutex.
188 
189 	// Even have a look at emImage::PreparePainter
190 
191 	~emPainter();
192 		// Destructor.
193 
194 	emPainter & operator = (const emPainter & painter);
195 		// Copy all the settings from another painter to this painter.
196 
197 	double GetClipX1() const;
198 	double GetClipY1() const;
199 	double GetClipX2() const;
200 	double GetClipY2() const;
201 	void SetClipping(double clipX1, double clipY1, double clipX2,
202 	                 double clipY2);
203 		// Get or set the clipping rectangle. It is in pixel
204 		// coordinates. Note that these can be fractional numbers - a
205 		// paint operation on a partly clipped pixel will result in an
206 		// appropriate blending operation.
207 
208 	double GetUserClipX1() const;
209 	double GetUserClipY1() const;
210 	double GetUserClipX2() const;
211 	double GetUserClipY2() const;
212 		// Get the clipping rectangle in user coordinates.
213 
214 	double GetOriginX() const;
215 	double GetOriginY() const;
216 	double GetScaleX() const;
217 	double GetScaleY() const;
218 	void SetOrigin(double originX, double originY);
219 	void SetScaling(double scaleX, double scaleY);
220 	void SetTransformation(double originX, double originY,
221 	                       double scaleX, double scaleY);
222 		// Get or set the user coordinate system, which is used by all
223 		// the painting methods. The transformation of user coordinates
224 		// to pixel coordinates is:
225 		//   xPixels = xUser * ScaleX + OriginX
226 		//   yPixels = yUser * ScaleY + OriginY
227 		// The scale factors must be positive!
228 
229 	double RoundX(double x) const;
230 	double RoundY(double y) const;
231 	double RoundDownX(double x) const;
232 	double RoundDownY(double y) const;
233 	double RoundUpX(double x) const;
234 	double RoundUpY(double y) const;
235 		// Round user coordinates to pixel boundary.
236 
237 	void SetUserSpaceMutex(
238 		emThreadMiniMutex * userSpaceMutex,
239 		bool * usmLockedByThisThread
240 	);
241 		// Set the pointer to the user space mutex, and the pointer to a
242 		// variable which always says whether the mutex is currently
243 		// locked by the thread which owns this emPainter. Both pointers
244 		// can be NULL for single-threaded mode. This method is normally
245 		// only to be called by emViewRenderer.
246 
247 	bool LeaveUserSpace() const;
248 		// Unlock the user space mutex. Returns true if it was locked.
249 		// In multi-threaded mode, each thread has it's own emPainter on
250 		// an own output region. The mutex is unlocked when a thread is
251 		// deeply in a paint method of emPainter, so that the low-level
252 		// painting can happen concurrently. Normally, the mutex is
253 		// always locked while one thread is in some code which "uses"
254 		// emPainter (i.e. emPanel::Paint implementation), so that the
255 		// user code must not be so thread-safe. But advanced user code
256 		// which is fully thread-safe, may call LeaveUserSpace() and
257 		// EnterUserSpace() in order to be concurrent. All paint methods
258 		// of emPainter can be called with or without having the mutex
259 		// locked, and they always return with the same lock state as
260 		// they were called.
261 
262 	bool EnterUserSpace() const;
263 		// Lock the user space mutex. Returns true if it was unlocked.
264 
265 
266 	//--------------------------- Painting areas ---------------------------
267 
268 	void Clear(const emTexture & texture=emColor::BLACK,
269 	           emColor canvasColor=0) const;
270 		// Like PaintRect on the whole clipping rectangle.
271 
272 	void PaintRect(double x, double y, double w, double h,
273 	               const emTexture & texture, emColor canvasColor=0) const;
274 		// Paint a rectangle.
275 		// Arguments:
276 		//   x,y,w,h     - Upper-left corner and size of the rectangle.
277 		//   texture     - The texture by which to fill the rectangle.
278 		//   canvasColor - Please read the general comments more above.
279 
280 	void PaintPolygon(const double xy[], int n, const emTexture & texture,
281 	                  emColor canvasColor=0) const;
282 		// Paint a polygon. The polygon may have holes, and it does not
283 		// matter whether the edges run clockwise or counterclockwise.
284 		// But there must not be any crossings in the edges.
285 		// Arguments:
286 		//   xy[]        - Coordinates of the polygon vertices. The
287 		//                 array elements are:
288 		//                 x0, y0, x1, y1, x2, y2, ..., x(n-1), y(n-1)
289 		//   n           - Number of vertices.
290 		//   texture     - The texture by which to fill the polygon.
291 		//   canvasColor - Please read the general comments more above.
292 
293 	void PaintEdgeCorrection(double x1, double y1, double x2, double y2,
294 	                         emColor color1, emColor color2) const;
295 		// If you don't have a canvas color when painting adjacent
296 		// polygons (or rectangles), this method can be helpful in
297 		// reducing the visual errors at the edges. Just call this to
298 		// paint the correction over the contact edge of two polygons
299 		// which have already been painted without canvas color. color1
300 		// must be the color used for painting the first polygon, and
301 		// color2 must be the color used for the other polygon which has
302 		// been painted later. (x1,y1) and (x2,y2) are the vertices of
303 		// the contact edge, but the order is important: When looking
304 		// from (x1,y1) to (x2,y2), the first polygon must be on the
305 		// left.
306 
307 	void PaintEllipse(double x, double y, double w, double h,
308 	                  const emTexture & texture,
309 	                  emColor canvasColor=0) const;
310 	void PaintEllipse(double x, double y, double w, double h,
311 	                  double startAngle, double rangeAngle,
312 	                  const emTexture & texture,
313 	                  emColor canvasColor=0) const;
314 		// Paint an ellipse or a sector of an ellipse.
315 		// Arguments:
316 		//   x,y,w,h     - Upper-left corner and size of the bounding
317 		//                 rectangle of the ellipse.
318 		//   startAngle  - Start angle of the sector in degrees. Zero
319 		//                 points to the right, 90 points down...
320 		//   rangeAngle  - Range angle of the sector.
321 		//   texture     - The texture by which to fill the ellipse.
322 		//   canvasColor - Please read the general comments more above.
323 
324 	void PaintRoundRect(double x, double y, double w, double h,
325 	                    double rx, double ry, const emTexture & texture,
326 	                    emColor canvasColor=0) const;
327 		// Paint a rectangle with elliptic corners.
328 		// Arguments:
329 		//   x,y,w,h     - Upper-left corner and size of the rectangle.
330 		//   rx,ry       - Radiuses of the ellipses.
331 		//   texture     - The texture by which to fill the round
332 		//                 rectangle.
333 		//   canvasColor - Please read the general comments more above.
334 
335 
336 	//--------------------------- Painting lines ---------------------------
337 
338 	enum LineCap {
339 		LC_FLAT,
340 		LC_SQUARE,
341 		LC_ROUND
342 	};
343 	void PaintLine(double x1, double y1, double x2, double y2,
344 	               double thickness, LineCap cap1, LineCap cap2,
345 	               emColor color, emColor canvasColor=0) const;
346 		// Paint a line.
347 		// Arguments:
348 		//   x1,y1       - Coordinates of the first end of the line.
349 		//   x2,y2       - Coordinates of the other end of the line.
350 		//   thickness   - Width of the stroke.
351 		//   cap1,cap2   - How to paint the endings:
352 		//                  LC_FLAT: Do not extend the ending.
353 		//                  LC_SQUARE: Extend by thickness/2.
354 		//                  LC_ROUND: Have a semicircle.
355 		//   color       - The color (alpha part is used for blending).
356 		//   canvasColor - Please read the general comments more above.
357 
358 	void PaintRectOutline(double x, double y, double w, double h,
359 	                      double thickness, emColor color,
360 	                      emColor canvasColor=0) const;
361 	void PaintPolygonOutline(const double xy[], int n, double thickness,
362 	                         emColor color, emColor canvasColor=0) const;
363 	void PaintEllipseOutline(double x, double y, double w, double h,
364 	                         double thickness, emColor color,
365 	                         emColor canvasColor=0) const;
366 	void PaintEllipseOutline(double x, double y, double w, double h,
367 	                         double startAngle, double rangeAngle,
368 	                         double thickness, emColor color,
369 	                         emColor canvasColor=0) const;
370 	void PaintRoundRectOutline(double x, double y, double w, double h,
371 	                           double rx, double ry, double thickness,
372 	                           emColor color, emColor canvasColor=0) const;
373 		// These are like PaintRect, PaintPolygon, PaintEllipse and
374 		// PaintRoundRect, but the objects are outlined instead of being
375 		// filled. The argument thickness is the width of the stroke.
376 		// The lines are centered on the boundary of the objects. The
377 		// second version of PaintEllipseOutline paints just an arc
378 		// (instead of the outline of a pie).
379 		// ??? BUG: PaintPolygonOutline currently always ignores the
380 		// canvasColor, and it does not produce correct results if the
381 		// alpha channel of the color is not 255.
382 
383 
384 	//------------------------ Painting from images ------------------------
385 
386 	void PaintImage(double x, double y, double w, double h,
387 	                const emImage & img, int alpha=255,
388 	                emColor canvasColor=0,
389 	                emTexture::ExtensionType extension=
390 	                emTexture::EXTEND_EDGE_OR_ZERO) const;
391 	void PaintImage(double x, double y, double w, double h,
392 	                const emImage & img, int srcX, int srcY, int srcW,
393 	                int srcH, int alpha=255, emColor canvasColor=0,
394 	                emTexture::ExtensionType extension=
395 	                emTexture::EXTEND_EDGE_OR_ZERO) const;
396 		// Paint a rectangle from an image or from a sub-image. This is
397 		// like PaintRect(..) with an emImageTexture. Please see
398 		// emImageTexture for details.
399 		// Arguments:
400 		//   x,y,w,h     - Upper-left corner and size of the target
401 		//                 rectangle.
402 		//   img         - The image. If the image has an alpha channel,
403 		//                 it is used for blending.
404 		//   srcX,srcY,srcW,srcH - Upper-left corner and size of the
405 		//                 source rectangle on the image. If these
406 		//                 arguments are missing, the whole image is
407 		//                 taken.
408 		//   alpha       - An additional alpha value for blending
409 		//                 (0-255).
410 		//   canvasColor - Please read the general comments more above.
411 		//   extension   - Please read the comments on
412 		//                 emTexture::ExtensionType.
413 
414 	void PaintImageColored(double x, double y, double w, double h,
415 	                       const emImage & img, emColor color1,
416 	                       emColor color2, emColor canvasColor=0,
417 	                       emTexture::ExtensionType extension=
418 	                       emTexture::EXTEND_EDGE_OR_ZERO) const;
419 	void PaintImageColored(double x, double y, double w, double h,
420 	                       const emImage & img, int srcX, int srcY,
421 	                       int srcW, int srcH, emColor color1,
422 	                       emColor color2, emColor canvasColor=0,
423 	                       emTexture::ExtensionType extension=
424 	                       emTexture::EXTEND_EDGE_OR_ZERO) const;
425 		// Paint a rectangle from an image or sub-image, with coloring.
426 		// This is like PaintRect(..) with an emImageColoredTexture.
427 		// Please see emImageColoredTexture for details.
428 		// Arguments:
429 		//   x,y,w,h     - Upper-left corner and size of the target
430 		//                 rectangle.
431 		//   img         - The image.
432 		//   srcX,srcY,srcW,srcH - Upper-left corner and size of the
433 		//                 source rectangle on the image. If these
434 		//                 arguments are missing, the whole image is
435 		//                 taken.
436 		//   color1      - The color of the beginning of the gradient
437 		//                 (where the image values are zero).
438 		//   color2      - The color of the end of the gradient
439 		//                 (where the image values are 255).
440 		//   canvasColor - Please read the general comments more above.
441 		//   extension   - Please read the comments on
442 		//                 emTexture::ExtensionType.
443 
444 	void PaintBorderImage(
445 		double x, double y, double w, double h,
446 		double l, double t, double r, double b,
447 		const emImage & img,
448 		int srcL, int srcT, int srcR, int srcB,
449 		int alpha=255, emColor canvasColor=0,
450 		int whichSubRects=0757
451 	) const;
452 	void PaintBorderImage(
453 		double x, double y, double w, double h,
454 		double l, double t, double r, double b,
455 		const emImage & img,
456 		int srcX, int srcY, int srcW, int srcH,
457 		int srcL, int srcT, int srcR, int srcB,
458 		int alpha=255, emColor canvasColor=0,
459 		int whichSubRects=0757
460 	) const;
461 	void PaintBorderImageColored(
462 		double x, double y, double w, double h,
463 		double l, double t, double r, double b,
464 		const emImage & img,
465 		int srcL, int srcT, int srcR, int srcB,
466 		emColor color1, emColor color2, emColor canvasColor=0,
467 		int whichSubRects=0757
468 	) const;
469 	void PaintBorderImageColored(
470 		double x, double y, double w, double h,
471 		double l, double t, double r, double b,
472 		const emImage & img,
473 		int srcX, int srcY, int srcW, int srcH,
474 		int srcL, int srcT, int srcR, int srcB,
475 		emColor color1, emColor color2, emColor canvasColor=0,
476 		int whichSubRects=0757
477 	) const;
478 		// Like PaintImage and PaintImageColored, but with a special
479 		// type of scaling, typically used for painting borders. The
480 		// rectangle is divided into a grid of nine sub-rectangles: four
481 		// corners, four edges and an inner rectangle. The operation
482 		// allows to change the height of the upper and lower edges and
483 		// the width of the left and right edges, in relation to the
484 		// size of the whole rectangle. The other sub-rectangles are
485 		// adapted accordingly.
486 		// Arguments:
487 		//   x,y,w,h     - Upper-left corner and size of the target
488 		//                 rectangle.
489 		//   l,t,r,b     - Thickness of the left, top, right and bottom
490 		//                 edges on the target.
491 		//   img         - The image.
492 		//   srcX,srcY,srcW,srcH - Upper-left corner and size of the
493 		//                 source rectangle on the image. If these
494 		//                 arguments are missing, the whole image is
495 		//                 taken.
496 		//   srcL,srcT,srcR,srcB - Thickness of the left, top, right
497 		//                 and bottom edges on the image.
498 		//   color1      - The color of the beginning of the gradient
499 		//                 (where the image values are zero).
500 		//   color2      - The color of the end of the gradient
501 		//                 (where the image values are 255).
502 		//   alpha       - An additional alpha value for blending
503 		//                 (0-255).
504 		//   canvasColor - Please read the general comments more above.
505 		//   whichSubRects - Which of the 9 sub-rectangles are to be
506 		//                 painted. This is a bit mask. Bit numbers are:
507 		//                  8 = upper left | 5 = upper | 2 = upper right
508 		//                  7 = left       | 4 = inner | 1 = right
509 		//                  6 = lower left | 3 = lower | 0 = lower right
510 		//                 The default of 0757 means to paint just the
511 		//                 corners and edges, not the inner part.
512 
513 
514 	//--------------------------- Painting texts ---------------------------
515 
516 	void PaintText(double x, double y, const char * text, double charHeight,
517 	               double widthScale, emColor color, emColor canvasColor=0,
518 	               int textLen=INT_MAX) const;
519 		// Paint a single line of raw text. Any formattings are not
520 		// interpreted.
521 		// Arguments:
522 		//   x,y         - Upper-left corner of the first character.
523 		//   text        - The character string, terminated by a
524 		//                 null-character or through the textLen
525 		//                 argument.
526 		//   charHeight  - The character height. This includes ascenders
527 		//                 and descenders.
528 		//   widthScale  - Factor for making the characters wider (>1.0)
529 		//                 or less wide (<1.0).
530 		//   color       - The color (alpha part is used for blending).
531 		//   canvasColor - Please read the general comments more above.
532 		//   textLen     - Length of the character string if not
533 		//                 null-terminated.
534 
535 	void PaintTextBoxed(double x, double y, double w, double h,
536 	                    const char * text, double maxCharHeight,
537 	                    emColor color, emColor canvasColor=0,
538 	                    emAlignment boxAlignment=EM_ALIGN_CENTER,
539 	                    emAlignment textAlignment=EM_ALIGN_LEFT,
540 	                    double minWidthScale=0.5, bool formatted=true,
541 	                    double relLineSpace=0.0, int textLen=INT_MAX) const;
542 		// Paint a text fitted into a rectangle, with or without
543 		// formatting.
544 		// Arguments:
545 		//   x,y,w,h       - Upper-left corner and size of the
546 		//                   rectangle.
547 		//   text          - The character string, terminated by a
548 		//                   null-character or through the textLen
549 		//                   argument.
550 		//   maxCharHeight - The maximum character height. This includes
551 		//                   ascenders and descenders. The actual
552 		//                   character height may get smaller, so that
553 		//                   the text fits into the rectangle.
554 		//   color         - The color (alpha part is used for
555 		//                   blending).
556 		//   canvasColor   - Please read the general comments more
557 		//                   above.
558 		//   boxAlignment  - How to align the text as a whole within the
559 		//                   rectangle.
560 		//   textAlignment - How to align individual lines within the
561 		//                   text horizontally. The top and bottom flags
562 		//                   are ignored here.
563 		//   minWidthScale - Minimum factor for making the characters
564 		//                   wider (>1.0) or less wide (<1.0). The
565 		//                   implicit maximum is the maximum of 1.0 and
566 		//                   minWidthScale. The maximum is preferred,
567 		//                   but for fitting the text into the
568 		//                   rectangle, the factor may get smaller down
569 		//                   to minWidthScale.
570 		//   formatted     - Whether to interpret formatting characters
571 		//                   (new-line and tabulator).
572 		//   relLineSpace  - Vertical space between text lines, in units
573 		//                   of character heights.
574 		//   textLen       - Length of the character string if not
575 		//                   null-terminated.
576 
577 	static double GetTextSize(const char * text, double charHeight,
578 	                          bool formatted=true, double relLineSpace=0.0,
579 	                          double * pHeight=NULL, int textLen=INT_MAX);
580 		// Calculate the width and height of a text.
581 		// Arguments:
582 		//   text         - The character string, terminated by a
583 		//                  null-character or through the textLen
584 		//                  argument.
585 		//   charHeight   - The character height. This includes
586 		//                  ascenders and descenders.
587 		//   formatted    - Whether to interpret formatting characters
588 		//                  (new-line and tabulator).
589 		//   relLineSpace - Vertical space between text lines, in units
590 		//                  of character heights.
591 		//   pHeight      - Pointer for returning the height of the
592 		//                  text, or NULL.
593 		//   textLen      - Length of the character string if not
594 		//                  null-terminated.
595 		// Returns: The width of the text.
596 
597 
598 	//----------------------------------------------------------------------
599 
600 private:
601 
602 	enum OptimizedPixelFormatIndex {
603 		OPFI_NONE      = -1,
604 		OPFI_8888_0BGR =  0,
605 		OPFI_8888_0RGB =  1,
606 		OPFI_8888_BGR0 =  2,
607 		OPFI_8888_RGB0 =  3
608 	};
609 
610 	struct SharedPixelFormat {
611 		SharedPixelFormat * Next;
612 		int RefCount;
613 		int BytesPerPixel;
614 		emUInt32 RedRange,GreenRange,BlueRange;
615 		int RedShift,GreenShift,BlueShift;
616 		void * RedHash;   // Index bits: rrrrrrrraaaaaaaa or aaaaaaaarrrrrrrr
617 		void * GreenHash; // Index bits: ggggggggaaaaaaaa or aaaaaaaagggggggg
618 		void * BlueHash;  // Index bits: bbbbbbbbaaaaaaaa or aaaaaaaabbbbbbbb
619 		OptimizedPixelFormatIndex OPFIndex;
620 	};
621 
622 	class SharedModel : public emModel {
623 	public:
624 		static emRef<SharedModel> Acquire(emRootContext & rootContext);
625 		emRef<emCoreConfig> CoreConfig;
626 		emRef<emFontCache> FontCache;
627 		emPainter::SharedPixelFormat * PixelFormatList;
628 #		if EM_HAVE_X86_INTRINSICS
629 			bool CanCpuDoAvx2;
630 #		endif
631 		void RemoveUnusedPixelFormats();
632 	private:
633 		SharedModel(emContext & context, const emString & name);
634 		virtual ~SharedModel();
635 	};
636 
637 	class ScanlineTool;
638 
639 	void * Map;
640 	int BytesPerRow;
641 	SharedPixelFormat * PixelFormat;
642 	double ClipX1, ClipY1, ClipX2, ClipY2;
643 	double OriginX, OriginY, ScaleX, ScaleY;
644 	emThreadMiniMutex * UserSpaceMutex;
645 	bool * USMLockedByThisThread;
646 	emRef<SharedModel> Model;
647 
648 	static const double CharBoxTallness;
649 	static const double CircleQuality;
650 };
651 
~emPainter()652 inline emPainter::~emPainter()
653 {
654 	if (PixelFormat) PixelFormat->RefCount--;
655 	// Do not free unused shared pixel formats here. So, it can be re-used
656 	// quickly on next construction.
657 }
658 
GetClipX1()659 inline double emPainter::GetClipX1() const
660 {
661 	return ClipX1;
662 }
663 
GetClipY1()664 inline double emPainter::GetClipY1() const
665 {
666 	return ClipY1;
667 }
668 
GetClipX2()669 inline double emPainter::GetClipX2() const
670 {
671 	return ClipX2;
672 }
673 
GetClipY2()674 inline double emPainter::GetClipY2() const
675 {
676 	return ClipY2;
677 }
678 
SetClipping(double clipX1,double clipY1,double clipX2,double clipY2)679 inline void emPainter::SetClipping(double clipX1, double clipY1,
680                                    double clipX2, double clipY2)
681 {
682 	ClipX1=clipX1;
683 	ClipY1=clipY1;
684 	ClipX2=clipX2;
685 	ClipY2=clipY2;
686 }
687 
GetUserClipX1()688 inline double emPainter::GetUserClipX1() const
689 {
690 	return (ClipX1-OriginX)/ScaleX;
691 }
692 
GetUserClipY1()693 inline double emPainter::GetUserClipY1() const
694 {
695 	return (ClipY1-OriginY)/ScaleY;
696 }
697 
GetUserClipX2()698 inline double emPainter::GetUserClipX2() const
699 {
700 	return (ClipX2-OriginX)/ScaleX;
701 }
702 
GetUserClipY2()703 inline double emPainter::GetUserClipY2() const
704 {
705 	return (ClipY2-OriginY)/ScaleY;
706 }
707 
GetOriginX()708 inline double emPainter::GetOriginX() const
709 {
710 	return OriginX;
711 }
712 
GetOriginY()713 inline double emPainter::GetOriginY() const
714 {
715 	return OriginY;
716 }
717 
GetScaleX()718 inline double emPainter::GetScaleX() const
719 {
720 	return ScaleX;
721 }
722 
GetScaleY()723 inline double emPainter::GetScaleY() const
724 {
725 	return ScaleY;
726 }
727 
SetOrigin(double originX,double originY)728 inline void emPainter::SetOrigin(double originX, double originY)
729 {
730 	OriginX=originX;
731 	OriginY=originY;
732 }
733 
SetScaling(double scaleX,double scaleY)734 inline void emPainter::SetScaling(double scaleX, double scaleY)
735 {
736 	ScaleX=scaleX;
737 	ScaleY=scaleY;
738 }
739 
SetTransformation(double originX,double originY,double scaleX,double scaleY)740 inline void emPainter::SetTransformation(
741 	double originX, double originY, double scaleX, double scaleY
742 )
743 {
744 	OriginX=originX;
745 	OriginY=originY;
746 	ScaleX=scaleX;
747 	ScaleY=scaleY;
748 }
749 
LeaveUserSpace()750 inline bool emPainter::LeaveUserSpace() const
751 {
752 	if (USMLockedByThisThread && *USMLockedByThisThread) {
753 		*USMLockedByThisThread=false;
754 		UserSpaceMutex->Unlock();
755 		return true;
756 	}
757 	return false;
758 }
759 
EnterUserSpace()760 inline bool emPainter::EnterUserSpace() const
761 {
762 	if (USMLockedByThisThread && !*USMLockedByThisThread) {
763 		UserSpaceMutex->Lock();
764 		*USMLockedByThisThread=true;
765 		return true;
766 	}
767 	return false;
768 }
769 
PaintImage(double x,double y,double w,double h,const emImage & img,int alpha,emColor canvasColor,emTexture::ExtensionType extension)770 inline void emPainter::PaintImage(
771 	double x, double y, double w, double h, const emImage & img,
772 	int alpha, emColor canvasColor, emTexture::ExtensionType extension
773 ) const
774 {
775 	PaintRect(
776 		x,y,w,h,
777 		emImageTexture(x,y,w,h,img,alpha,extension),
778 		canvasColor
779 	);
780 }
781 
PaintImage(double x,double y,double w,double h,const emImage & img,int srcX,int srcY,int srcW,int srcH,int alpha,emColor canvasColor,emTexture::ExtensionType extension)782 inline void emPainter::PaintImage(
783 	double x, double y, double w, double h, const emImage & img, int srcX,
784 	int srcY, int srcW, int srcH, int alpha, emColor canvasColor,
785 	emTexture::ExtensionType extension
786 ) const
787 {
788 	PaintRect(
789 		x,y,w,h,
790 		emImageTexture(x,y,w,h,img,srcX,srcY,srcW,srcH,alpha,extension),
791 		canvasColor
792 	);
793 }
794 
PaintImageColored(double x,double y,double w,double h,const emImage & img,emColor color1,emColor color2,emColor canvasColor,emTexture::ExtensionType extension)795 inline void emPainter::PaintImageColored(
796 	double x, double y, double w, double h, const emImage & img,
797 	emColor color1, emColor color2, emColor canvasColor,
798 	emTexture::ExtensionType extension
799 ) const
800 {
801 	PaintRect(
802 		x,y,w,h,
803 		emImageColoredTexture(x,y,w,h,img,color1,color2,extension),
804 		canvasColor
805 	);
806 }
807 
PaintImageColored(double x,double y,double w,double h,const emImage & img,int srcX,int srcY,int srcW,int srcH,emColor color1,emColor color2,emColor canvasColor,emTexture::ExtensionType extension)808 inline void emPainter::PaintImageColored(
809 	double x, double y, double w, double h, const emImage & img,
810 	int srcX, int srcY, int srcW, int srcH,
811 	emColor color1, emColor color2, emColor canvasColor,
812 	emTexture::ExtensionType extension
813 ) const
814 {
815 	PaintRect(
816 		x,y,w,h,
817 		emImageColoredTexture(x,y,w,h,img,srcX,srcY,srcW,srcH,
818 		                      color1,color2,extension),
819 		canvasColor
820 	);
821 }
822 
PaintBorderImage(double x,double y,double w,double h,double l,double t,double r,double b,const emImage & img,int srcL,int srcT,int srcR,int srcB,int alpha,emColor canvasColor,int whichSubRects)823 inline void emPainter::PaintBorderImage(
824 	double x, double y, double w, double h, double l, double t, double r,
825 	double b, const emImage & img, int srcL, int srcT, int srcR, int srcB,
826 	int alpha, emColor canvasColor, int whichSubRects
827 ) const
828 {
829 	PaintBorderImage(
830 		x,y,w,h,l,t,r,b,img,0,0,img.GetWidth(),img.GetHeight(),
831 		srcL,srcT,srcR,srcB,alpha,canvasColor,whichSubRects
832 	);
833 }
834 
PaintBorderImageColored(double x,double y,double w,double h,double l,double t,double r,double b,const emImage & img,int srcL,int srcT,int srcR,int srcB,emColor color1,emColor color2,emColor canvasColor,int whichSubRects)835 inline void emPainter::PaintBorderImageColored(
836 	double x, double y, double w, double h, double l, double t, double r,
837 	double b, const emImage & img, int srcL, int srcT, int srcR, int srcB,
838 	emColor color1, emColor color2, emColor canvasColor, int whichSubRects
839 ) const
840 {
841 	PaintBorderImageColored(
842 		x,y,w,h,l,t,r,b,img,0,0,img.GetWidth(),img.GetHeight(),
843 		srcL,srcT,srcR,srcB,color1,color2,canvasColor,whichSubRects
844 	);
845 }
846 
847 
848 #endif
849