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