Increase temporary buffer size of streams Reading large files using a small buffer causes significant delays. See #26457
Avoid out-of-bounds palette write in wxIFFDecoder::ConvertToImage The transparent colour index from the IFF BMHD chunk is a 16-bit value stored unclamped in m_image->transparent. Using it as a palette index without checking it against the CMAP-derived colour count writes 3 bytes at an attacker-controlled offset past the palette buffer. Validate the index against the actual palette size before applying the magenta mask.
Reject IFF images with out-of-range transparent colour index Following review on the previous commit, switch from silently ignoring an out-of-bounds BMHD transparent colour index to rejecting the file outright in wxIFFDecoder::ConvertToImage. The earlier "ignore" approach let the load succeed, which made the BadIFF test pass only as a side effect of corruption from the unrelated overrun and so failed intermittently in some wxMSW builds. Apply the bounds check using the form suggested in the PR review.
Fix text size in SVG after wxSVGGraphicsContext addition This was inadvertently broken by e1c72e28fc (Add wxSVGGraphicsContext, 2026-05-19) which replaced floating point division with integer division when determining the scale to use. Fix this indirectly by adding a new helper ScaleFontForSVG() with the correct code, which is now reused by both GetTextMetricDC() and DoGetTextExtent() instead of duplicating its code in both of them. See #26395.
Add function to read entire wxInputStream to a buffer When the size is known, read the data directly into the buffer. Otherwise read it in chucks until the end of the stream is reached.
Improve speed of reading webp into memory Use the newly added wxInputStream::Read() function to read the entire file into a buffer instead of using wxMemoryOutputStream. See #26457
Merge branch 'fix/iff-transparent-bounds-check' of github.com:MarkLee131/wxWidgets Avoid out-of-bounds palette write in wxIFFDecoder::ConvertToImage(). See #26440.
Merge branch 'webp-read-buffer-speed' of github.com:MaartenBent/wxWidgets Improve speed of reading WebP images and add generally useful wxInputStream::Read(vector<byte>&) overload. See #26461.
Add getters to wxSVGAttributes, add unit tests Closes #26479.
| ... | ... | @@ -24,6 +24,7 @@ set(TEST_GUI_SRC |
| 24 | 24 | graphics/boundingbox.cpp
|
| 25 | 25 | graphics/clipper.cpp
|
| 26 | 26 | graphics/clippingbox.cpp
|
| 27 | + graphics/svgattributes.cpp
|
|
| 27 | 28 | graphics/coords.cpp
|
| 28 | 29 | graphics/graphbitmap.cpp
|
| 29 | 30 | graphics/graphmatrix.cpp
|
| ... | ... | @@ -53,9 +53,23 @@ public: |
| 53 | 53 | wxSVGAttributes& Id(const wxString& id) { return Add(wxASCII_STR("id"), id); }
|
| 54 | 54 | wxSVGAttributes& Class(const wxString& classname) { return Add(wxASCII_STR("class"), classname); }
|
| 55 | 55 | |
| 56 | + wxString GetRole() const { return GetAttribute(wxASCII_STR("role")); }
|
|
| 57 | + wxString GetAriaLabel() const { return GetAttribute(wxASCII_STR("aria-label")); }
|
|
| 58 | + wxString GetAriaLabelledBy() const { return GetAttribute(wxASCII_STR("aria-labelledby")); }
|
|
| 59 | + wxString GetAriaDescribedBy() const { return GetAttribute(wxASCII_STR("aria-describedby")); }
|
|
| 60 | + bool IsAriaHidden() const { return GetAttribute(wxASCII_STR("aria-hidden")) == wxASCII_STR("true"); }
|
|
| 61 | + wxString GetAriaDetails() const { return GetAttribute(wxASCII_STR("aria-details")); }
|
|
| 62 | + wxString GetAriaRoleDescription() const { return GetAttribute(wxASCII_STR("aria-roledescription")); }
|
|
| 63 | + |
|
| 64 | + wxString GetId() const { return GetAttribute(wxASCII_STR("id")); }
|
|
| 65 | + wxString GetClass() const { return GetAttribute(wxASCII_STR("class")); }
|
|
| 66 | + |
|
| 56 | 67 | // Add or update an attribute.
|
| 57 | 68 | wxSVGAttributes& Add(const wxString& name, const wxString& value);
|
| 58 | 69 | |
| 70 | + // Get an attribute value, returns empty string if not found.
|
|
| 71 | + wxString GetAttribute(const wxString& name) const;
|
|
| 72 | + |
|
| 59 | 73 | // Returns the attributes as a string of name="value" pairs, each prefixed with a space.
|
| 60 | 74 | wxString GetAsString() const;
|
| 61 | 75 |
| ... | ... | @@ -134,6 +134,10 @@ public: |
| 134 | 134 | // when EOF is reached or an error occurs
|
| 135 | 135 | wxInputStream& Read(wxOutputStream& streamOut);
|
| 136 | 136 | |
| 137 | + // copy the entire contents of this stream into buffer, stopping only
|
|
| 138 | + // when EOF is reached or an error occurs
|
|
| 139 | + bool Read(std::vector<wxUint8>& buffer);
|
|
| 140 | + |
|
| 137 | 141 | |
| 138 | 142 | // status functions
|
| 139 | 143 | // ----------------
|
| ... | ... | @@ -71,12 +71,26 @@ public: |
| 71 | 71 | */
|
| 72 | 72 | wxSVGAttributes& Role(const wxString& role);
|
| 73 | 73 | |
| 74 | + /**
|
|
| 75 | + Returns the @c role attribute.
|
|
| 76 | + |
|
| 77 | + @since 3.3.3
|
|
| 78 | + */
|
|
| 79 | + wxString GetRole() const;
|
|
| 80 | + |
|
| 74 | 81 | /**
|
| 75 | 82 | Sets the @c aria-label attribute: a short accessible name read
|
| 76 | 83 | aloud by screen readers. Use when no visible text label exists.
|
| 77 | 84 | */
|
| 78 | 85 | wxSVGAttributes& AriaLabel(const wxString& label);
|
| 79 | 86 | |
| 87 | + /**
|
|
| 88 | + Returns the @c aria-label attribute.
|
|
| 89 | + |
|
| 90 | + @since 3.3.3
|
|
| 91 | + */
|
|
| 92 | + wxString GetAriaLabel() const;
|
|
| 93 | + |
|
| 80 | 94 | /**
|
| 81 | 95 | Sets the @c aria-labelledby attribute: instead of supplying a name
|
| 82 | 96 | inline, points at the @c id of another element whose text content
|
| ... | ... | @@ -84,6 +98,13 @@ public: |
| 84 | 98 | */
|
| 85 | 99 | wxSVGAttributes& AriaLabelledBy(const wxString& id);
|
| 86 | 100 | |
| 101 | + /**
|
|
| 102 | + Returns the @c aria-labelledby attribute.
|
|
| 103 | + |
|
| 104 | + @since 3.3.3
|
|
| 105 | + */
|
|
| 106 | + wxString GetAriaLabelledBy() const;
|
|
| 107 | + |
|
| 87 | 108 | /**
|
| 88 | 109 | Sets the @c aria-describedby attribute: points at the @c id of
|
| 89 | 110 | another element whose text content provides a longer description,
|
| ... | ... | @@ -91,6 +112,13 @@ public: |
| 91 | 112 | */
|
| 92 | 113 | wxSVGAttributes& AriaDescribedBy(const wxString& id);
|
| 93 | 114 | |
| 115 | + /**
|
|
| 116 | + Returns the @c aria-describedby attribute.
|
|
| 117 | + |
|
| 118 | + @since 3.3.3
|
|
| 119 | + */
|
|
| 120 | + wxString GetAriaDescribedBy() const;
|
|
| 121 | + |
|
| 94 | 122 | /**
|
| 95 | 123 | Sets the @c aria-hidden attribute.
|
| 96 | 124 | |
| ... | ... | @@ -101,6 +129,13 @@ public: |
| 101 | 129 | */
|
| 102 | 130 | wxSVGAttributes& AriaHidden(bool hidden = true);
|
| 103 | 131 | |
| 132 | + /**
|
|
| 133 | + Returns @true if the @c aria-hidden attribute is set to @c "true".
|
|
| 134 | + |
|
| 135 | + @since 3.3.3
|
|
| 136 | + */
|
|
| 137 | + bool IsAriaHidden() const;
|
|
| 138 | + |
|
| 104 | 139 | /**
|
| 105 | 140 | Sets the @c aria-details attribute: points at the @c id of another
|
| 106 | 141 | element containing extended information about this one
|
| ... | ... | @@ -108,6 +143,13 @@ public: |
| 108 | 143 | */
|
| 109 | 144 | wxSVGAttributes& AriaDetails(const wxString& id);
|
| 110 | 145 | |
| 146 | + /**
|
|
| 147 | + Returns the @c aria-details attribute.
|
|
| 148 | + |
|
| 149 | + @since 3.3.3
|
|
| 150 | + */
|
|
| 151 | + wxString GetAriaDetails() const;
|
|
| 152 | + |
|
| 111 | 153 | /**
|
| 112 | 154 | Sets the @c aria-roledescription attribute: a human-readable,
|
| 113 | 155 | optionally localized phrase that replaces the default spoken role
|
| ... | ... | @@ -115,6 +157,13 @@ public: |
| 115 | 157 | */
|
| 116 | 158 | wxSVGAttributes& AriaRoleDescription(const wxString& desc);
|
| 117 | 159 | |
| 160 | + /**
|
|
| 161 | + Returns the @c aria-roledescription attribute.
|
|
| 162 | + |
|
| 163 | + @since 3.3.3
|
|
| 164 | + */
|
|
| 165 | + wxString GetAriaRoleDescription() const;
|
|
| 166 | + |
|
| 118 | 167 | /**
|
| 119 | 168 | Sets the @c id attribute, giving the element a unique identifier
|
| 120 | 169 | other attributes (such as @c aria-labelledby) or stylesheets can
|
| ... | ... | @@ -122,12 +171,26 @@ public: |
| 122 | 171 | */
|
| 123 | 172 | wxSVGAttributes& Id(const wxString& id);
|
| 124 | 173 | |
| 174 | + /**
|
|
| 175 | + Returns the @c id attribute.
|
|
| 176 | + |
|
| 177 | + @since 3.3.3
|
|
| 178 | + */
|
|
| 179 | + wxString GetId() const;
|
|
| 180 | + |
|
| 125 | 181 | /**
|
| 126 | 182 | Sets the @c class attribute, used to associate the element with
|
| 127 | 183 | one or more CSS classes for styling the SVG output.
|
| 128 | 184 | */
|
| 129 | 185 | wxSVGAttributes& Class(const wxString& classname);
|
| 130 | 186 | |
| 187 | + /**
|
|
| 188 | + Returns the @c class attribute.
|
|
| 189 | + |
|
| 190 | + @since 3.3.3
|
|
| 191 | + */
|
|
| 192 | + wxString GetClass() const;
|
|
| 193 | + |
|
| 131 | 194 | /**
|
| 132 | 195 | Adds or updates an arbitrary attribute.
|
| 133 | 196 | |
| ... | ... | @@ -136,6 +199,15 @@ public: |
| 136 | 199 | */
|
| 137 | 200 | wxSVGAttributes& Add(const wxString& name, const wxString& value);
|
| 138 | 201 | |
| 202 | + /**
|
|
| 203 | + Returns the value of the attribute with the given @a name.
|
|
| 204 | + |
|
| 205 | + Returns an empty string if the attribute is not set.
|
|
| 206 | + |
|
| 207 | + @since 3.3.3
|
|
| 208 | + */
|
|
| 209 | + wxString GetAttribute(const wxString& name) const;
|
|
| 210 | + |
|
| 139 | 211 | /// Returns @true if no attributes have been set.
|
| 140 | 212 | bool IsEmpty() const;
|
| 141 | 213 | };
|
| ... | ... | @@ -648,6 +648,17 @@ public: |
| 648 | 648 | */
|
| 649 | 649 | wxInputStream& Read(wxOutputStream& stream_out);
|
| 650 | 650 | |
| 651 | + /**
|
|
| 652 | + Read all data from the stream and stores it in the specified buffer.
|
|
| 653 | + Data is read until the end of the input stream, or until an error occurs.
|
|
| 654 | + The buffer will be resized to the number of bytes read.
|
|
| 655 | + |
|
| 656 | + @return Returns true if the entire stream is read.
|
|
| 657 | + |
|
| 658 | + @since 3.3.3
|
|
| 659 | + */
|
|
| 660 | + bool Read(std::vector<wxUint8>& buffer);
|
|
| 661 | + |
|
| 651 | 662 | /**
|
| 652 | 663 | Reads exactly the specified number of bytes into the buffer.
|
| 653 | 664 |
| ... | ... | @@ -365,9 +365,8 @@ wxString CreateBrushFill(const wxBrush& brush, wxSVGShapeRenderingMode mode) |
| 365 | 365 | return s;
|
| 366 | 366 | }
|
| 367 | 367 | |
| 368 | -wxMemoryDC GetTextMetricDC(const wxFont& font)
|
|
| 368 | +wxFont ScaleFontForSVG(wxFont font, wxDC& dc)
|
|
| 369 | 369 | {
|
| 370 | - wxMemoryDC dc;
|
|
| 371 | 370 | const double dcDPI = dc.GetPPI().y;
|
| 372 | 371 | const double scale = dcDPI / SVG_DPI.y;
|
| 373 | 372 | if ( scale != 1 )
|
| ... | ... | @@ -377,15 +376,17 @@ wxMemoryDC GetTextMetricDC(const wxFont& font) |
| 377 | 376 | // We can't just divide the returned sizes by the scale factor, because
|
| 378 | 377 | // text does not scale linear (at least on Windows). Therefore, we scale
|
| 379 | 378 | // the font size instead.
|
| 380 | - wxFont scaledFont = font;
|
|
| 381 | - scaledFont.SetFractionalPointSize(scaledFont.GetFractionalPointSize() / scale);
|
|
| 382 | - dc.SetFont(scaledFont);
|
|
| 383 | - }
|
|
| 384 | - else
|
|
| 385 | - {
|
|
| 386 | - dc.SetFont(font);
|
|
| 379 | + font.SetFractionalPointSize(font.GetFractionalPointSize() / scale);
|
|
| 387 | 380 | }
|
| 388 | 381 | |
| 382 | + return font;
|
|
| 383 | +}
|
|
| 384 | + |
|
| 385 | +wxMemoryDC GetTextMetricDC(const wxFont& font)
|
|
| 386 | +{
|
|
| 387 | + wxMemoryDC dc;
|
|
| 388 | + dc.SetFont(ScaleFontForSVG(font, dc));
|
|
| 389 | + |
|
| 389 | 390 | return dc;
|
| 390 | 391 | }
|
| 391 | 392 | |
| ... | ... | @@ -554,6 +555,12 @@ wxSVGAttributes& wxSVGAttributes::Add(const wxString& name, const wxString& valu |
| 554 | 555 | return *this;
|
| 555 | 556 | }
|
| 556 | 557 | |
| 558 | +wxString wxSVGAttributes::GetAttribute(const wxString& name) const
|
|
| 559 | +{
|
|
| 560 | + auto it = m_attributes.find(name);
|
|
| 561 | + return it != m_attributes.end() ? it->second : wxString();
|
|
| 562 | +}
|
|
| 563 | + |
|
| 557 | 564 | wxString wxSVGAttributes::GetAsString() const
|
| 558 | 565 | {
|
| 559 | 566 | wxString s;
|
| ... | ... | @@ -1380,20 +1387,12 @@ void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string, |
| 1380 | 1387 | wxCoord* externalLeading,
|
| 1381 | 1388 | const wxFont* theFont) const
|
| 1382 | 1389 | {
|
| 1383 | - wxFont font = theFont ? *theFont : m_font;
|
|
| 1384 | - |
|
| 1385 | 1390 | // A bitmap must be selected before wrapping the memory DC in a wxGCDC
|
| 1386 | 1391 | // (size is irrelevant).
|
| 1387 | 1392 | wxBitmap metricBmp(1, 1);
|
| 1388 | 1393 | wxMemoryDC memDc(metricBmp);
|
| 1389 | - const double scale = memDc.GetPPI().y / SVG_DPI.y;
|
|
| 1390 | - if ( scale != 1.0 && scale != 0.0 )
|
|
| 1391 | - {
|
|
| 1392 | - // SVG is DPI-independent, so we want text metrics at the default (96) DPI.
|
|
| 1393 | - // Text does not scale linearly (at least on MSW), so scale the font size,
|
|
| 1394 | - // rather than dividing the returned extent.
|
|
| 1395 | - font.SetFractionalPointSize(font.GetFractionalPointSize() / scale);
|
|
| 1396 | - }
|
|
| 1394 | + |
|
| 1395 | + wxFont font = ScaleFontForSVG(theFont ? *theFont : m_font, memDc);
|
|
| 1397 | 1396 | |
| 1398 | 1397 | #if wxUSE_GRAPHICS_CONTEXT
|
| 1399 | 1398 | // Measure through a wxGCDC so widths come from the platform's modern font engine
|
| ... | ... | @@ -148,6 +148,9 @@ bool wxIFFDecoder::ConvertToImage(wxImage *image) const |
| 148 | 148 | // set transparent colour mask
|
| 149 | 149 | if (transparent != -1)
|
| 150 | 150 | {
|
| 151 | + if (transparent < 0 || transparent >= colors)
|
|
| 152 | + return false;
|
|
| 153 | + |
|
| 151 | 154 | for (i = 0; i < colors; i++)
|
| 152 | 155 | {
|
| 153 | 156 | if ((pal[3 * i + 0] == 255) &&
|
| ... | ... | @@ -34,8 +34,6 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxWEBPHandler, wxImageHandler); |
| 34 | 34 | |
| 35 | 35 | #if wxUSE_STREAMS
|
| 36 | 36 | |
| 37 | -#include "wx/mstream.h"
|
|
| 38 | - |
|
| 39 | 37 | #include <memory>
|
| 40 | 38 | #include <functional>
|
| 41 | 39 | |
| ... | ... | @@ -103,21 +101,20 @@ bool DecodeWebPDataIntoImage(wxImage* image, WebPData* webp_data, bool verbose) |
| 103 | 101 | return true;
|
| 104 | 102 | }
|
| 105 | 103 | |
| 106 | -WebPDemuxerPtr CreateDemuxer(wxMemoryOutputStream& mos, bool verbose = false)
|
|
| 104 | +WebPDemuxerPtr CreateDemuxer(wxInputStream& stream, std::vector<uint8_t>& buffer, bool verbose = false)
|
|
| 107 | 105 | {
|
| 108 | - wxStreamBuffer* mosb = mos.GetOutputStreamBuffer();
|
|
| 109 | - if (mosb == nullptr)
|
|
| 106 | + if (!stream.Read(buffer))
|
|
| 110 | 107 | {
|
| 111 | 108 | if (verbose)
|
| 112 | 109 | {
|
| 113 | - wxLogError(_("WebP: Allocating stream buffer failed."));
|
|
| 110 | + wxLogError(_("WebP: Error reading data."));
|
|
| 114 | 111 | }
|
| 115 | 112 | return nullptr;
|
| 116 | 113 | }
|
| 117 | 114 | |
| 118 | 115 | WebPData webp_data{};
|
| 119 | - webp_data.bytes = reinterpret_cast<uint8_t*>(mosb->GetBufferStart());
|
|
| 120 | - webp_data.size = mosb->GetBufferSize();
|
|
| 116 | + webp_data.bytes = buffer.data();
|
|
| 117 | + webp_data.size = buffer.size();
|
|
| 121 | 118 | |
| 122 | 119 | WebPDemuxerPtr demux(
|
| 123 | 120 | WebPDemux(&webp_data),
|
| ... | ... | @@ -157,9 +154,8 @@ bool wxWEBPHandler::LoadFile(wxImage* image, wxInputStream& stream, bool verbose |
| 157 | 154 | // be a sub-frame, smaller than the full image. Its size is known, but
|
| 158 | 155 | // the x_offset and y_offset can not be queried, so we can't
|
| 159 | 156 | // reconstruct the full-size image.
|
| 160 | - wxMemoryOutputStream mos;
|
|
| 161 | - stream.Read(mos);
|
|
| 162 | - WebPDemuxerPtr demux = CreateDemuxer(mos, verbose);
|
|
| 157 | + std::vector<uint8_t> buffer;
|
|
| 158 | + WebPDemuxerPtr demux = CreateDemuxer(stream, buffer, verbose);
|
|
| 163 | 159 | if (demux != nullptr)
|
| 164 | 160 | {
|
| 165 | 161 | WebPIterator iter;
|
| ... | ... | @@ -191,21 +187,19 @@ bool wxWEBPHandler::LoadFile(wxImage* image, wxInputStream& stream, bool verbose |
| 191 | 187 | |
| 192 | 188 | bool wxWEBPHandler::LoadAnimation(std::vector<wxWebPAnimationFrame>& frames, wxInputStream& stream, bool verbose)
|
| 193 | 189 | {
|
| 194 | - wxMemoryOutputStream mos;
|
|
| 195 | - stream.Read(mos);
|
|
| 196 | - wxStreamBuffer* mosb = mos.GetOutputStreamBuffer();
|
|
| 197 | - if (mosb == nullptr)
|
|
| 190 | + std::vector<uint8_t> buffer;
|
|
| 191 | + if (!stream.Read(buffer))
|
|
| 198 | 192 | {
|
| 199 | 193 | if (verbose)
|
| 200 | 194 | {
|
| 201 | - wxLogError(_("WebP: Allocating stream buffer failed."));
|
|
| 195 | + wxLogError(_("WebP: Error reading data."));
|
|
| 202 | 196 | }
|
| 203 | 197 | return false;
|
| 204 | 198 | }
|
| 205 | 199 | |
| 206 | 200 | WebPData webp_data{};
|
| 207 | - webp_data.bytes = reinterpret_cast<uint8_t*>(mosb->GetBufferStart());
|
|
| 208 | - webp_data.size = mosb->GetBufferSize();
|
|
| 201 | + webp_data.bytes = buffer.data();
|
|
| 202 | + webp_data.size = buffer.size();
|
|
| 209 | 203 | |
| 210 | 204 | WebPAnimDecoderOptions dec_options;
|
| 211 | 205 | WebPAnimDecoderOptionsInit(&dec_options);
|
| ... | ... | @@ -305,9 +299,8 @@ bool wxWEBPHandler::SaveFile(wxImage* image, wxOutputStream& stream, bool) |
| 305 | 299 | int wxWEBPHandler::DoGetImageCount(wxInputStream& stream)
|
| 306 | 300 | {
|
| 307 | 301 | int frame_count = 0;
|
| 308 | - wxMemoryOutputStream mos;
|
|
| 309 | - stream.Read(mos);
|
|
| 310 | - WebPDemuxerPtr demux = CreateDemuxer(mos);
|
|
| 302 | + std::vector<uint8_t> buffer;
|
|
| 303 | + WebPDemuxerPtr demux = CreateDemuxer(stream, buffer);
|
|
| 311 | 304 | if (demux != nullptr)
|
| 312 | 305 | {
|
| 313 | 306 | frame_count = WebPDemuxGetI(demux.get(), WEBP_FF_FRAME_COUNT);
|
| ... | ... | @@ -39,7 +39,7 @@ |
| 39 | 39 | // ----------------------------------------------------------------------------
|
| 40 | 40 | |
| 41 | 41 | // the temporary buffer size used when copying from stream to stream
|
| 42 | -#define BUF_TEMP_SIZE 4096
|
|
| 42 | +#define BUF_TEMP_SIZE 65536
|
|
| 43 | 43 | |
| 44 | 44 | // ============================================================================
|
| 45 | 45 | // implementation
|
| ... | ... | @@ -915,6 +915,43 @@ wxInputStream& wxInputStream::Read(wxOutputStream& stream_out) |
| 915 | 915 | return *this;
|
| 916 | 916 | }
|
| 917 | 917 | |
| 918 | +bool wxInputStream::Read(std::vector<wxUint8>& buffer)
|
|
| 919 | +{
|
|
| 920 | + const size_t stream_size = IsOk() ? GetSize() : 0;
|
|
| 921 | + size_t lastcount = 0;
|
|
| 922 | + |
|
| 923 | + if ( stream_size > 0 )
|
|
| 924 | + {
|
|
| 925 | + buffer.resize(stream_size);
|
|
| 926 | + lastcount = Read(buffer.data(), stream_size).LastRead();
|
|
| 927 | + |
|
| 928 | + // Read one more byte to set EOF
|
|
| 929 | + wxUint8 temp;
|
|
| 930 | + Read(&temp, 1);
|
|
| 931 | + }
|
|
| 932 | + else if ( IsOk() )
|
|
| 933 | + {
|
|
| 934 | + const size_t read_size = BUF_TEMP_SIZE * 8;
|
|
| 935 | + for ( ;; )
|
|
| 936 | + {
|
|
| 937 | + if ( buffer.size() < (lastcount + read_size) )
|
|
| 938 | + buffer.resize(lastcount + read_size);
|
|
| 939 | + |
|
| 940 | + size_t bytes_read = Read(buffer.data() + lastcount, read_size).LastRead();
|
|
| 941 | + if ( !bytes_read )
|
|
| 942 | + break;
|
|
| 943 | + |
|
| 944 | + lastcount += bytes_read;
|
|
| 945 | + }
|
|
| 946 | + }
|
|
| 947 | + |
|
| 948 | + m_lastcount = lastcount;
|
|
| 949 | + |
|
| 950 | + buffer.resize(m_lastcount);
|
|
| 951 | + |
|
| 952 | + return Eof();
|
|
| 953 | +}
|
|
| 954 | + |
|
| 918 | 955 | bool wxInputStream::ReadAll(void *buffer_, size_t size)
|
| 919 | 956 | {
|
| 920 | 957 | char* buffer = static_cast<char*>(buffer_);
|
| ... | ... | @@ -192,6 +192,7 @@ TEST_GUI_OBJECTS = \ |
| 192 | 192 | test_gui_boundingbox.o \
|
| 193 | 193 | test_gui_clipper.o \
|
| 194 | 194 | test_gui_clippingbox.o \
|
| 195 | + test_gui_svgattributes.o \
|
|
| 195 | 196 | test_gui_coords.o \
|
| 196 | 197 | test_gui_graphbitmap.o \
|
| 197 | 198 | test_gui_graphmatrix.o \
|
| ... | ... | @@ -998,6 +999,9 @@ test_gui_clipper.o: $(srcdir)/graphics/clipper.cpp $(TEST_GUI_ODEP) |
| 998 | 999 | test_gui_clippingbox.o: $(srcdir)/graphics/clippingbox.cpp $(TEST_GUI_ODEP)
|
| 999 | 1000 | $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/graphics/clippingbox.cpp
|
| 1000 | 1001 | |
| 1002 | +test_gui_svgattributes.o: $(srcdir)/graphics/svgattributes.cpp $(TEST_GUI_ODEP)
|
|
| 1003 | + $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/graphics/svgattributes.cpp
|
|
| 1004 | + |
|
| 1001 | 1005 | test_gui_coords.o: $(srcdir)/graphics/coords.cpp $(TEST_GUI_ODEP)
|
| 1002 | 1006 | $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/graphics/coords.cpp
|
| 1003 | 1007 |
| 1 | +///////////////////////////////////////////////////////////////////////////////
|
|
| 2 | +// Name: tests/graphics/svgattributes.cpp
|
|
| 3 | +// Purpose: wxSVGAttributes unit tests
|
|
| 4 | +// Author: wxWidgets team
|
|
| 5 | +// Created: 2026-05-19
|
|
| 6 | +// Copyright: (c) 2026 wxWidgets development team
|
|
| 7 | +// Licence: wxWindows licence
|
|
| 8 | +///////////////////////////////////////////////////////////////////////////////
|
|
| 9 | + |
|
| 10 | +#include "testprec.h"
|
|
| 11 | + |
|
| 12 | +#if wxUSE_SVG
|
|
| 13 | + |
|
| 14 | +#include "wx/dcsvg.h"
|
|
| 15 | + |
|
| 16 | +TEST_CASE("wxSVGAttributes::Getters", "[svg][attributes]")
|
|
| 17 | +{
|
|
| 18 | + wxSVGAttributes attr;
|
|
| 19 | + attr.Role("img")
|
|
| 20 | + .AriaLabel("label")
|
|
| 21 | + .AriaLabelledBy("id1")
|
|
| 22 | + .AriaDescribedBy("id2")
|
|
| 23 | + .AriaHidden(true)
|
|
| 24 | + .AriaDetails("id3")
|
|
| 25 | + .AriaRoleDescription("desc")
|
|
| 26 | + .Id("myid")
|
|
| 27 | + .Class("myclass");
|
|
| 28 | + |
|
| 29 | + CHECK( attr.GetRole() == "img" );
|
|
| 30 | + CHECK( attr.GetAriaLabel() == "label" );
|
|
| 31 | + CHECK( attr.GetAriaLabelledBy() == "id1" );
|
|
| 32 | + CHECK( attr.GetAriaDescribedBy() == "id2" );
|
|
| 33 | + CHECK( attr.IsAriaHidden() == true );
|
|
| 34 | + CHECK( attr.GetAriaDetails() == "id3" );
|
|
| 35 | + CHECK( attr.GetAriaRoleDescription() == "desc" );
|
|
| 36 | + CHECK( attr.GetId() == "myid" );
|
|
| 37 | + CHECK( attr.GetClass() == "myclass" );
|
|
| 38 | + |
|
| 39 | + attr.AriaHidden(false);
|
|
| 40 | + CHECK( attr.IsAriaHidden() == false );
|
|
| 41 | + |
|
| 42 | + attr.Add("custom", "value");
|
|
| 43 | + CHECK( attr.GetAttribute("custom") == "value" );
|
|
| 44 | + CHECK( attr.GetAttribute("nonexistent").empty() );
|
|
| 45 | +}
|
|
| 46 | + |
|
| 47 | +#endif // wxUSE_SVG |
| ... | ... | @@ -1363,6 +1363,32 @@ TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadXPM", "[image][xpm][error]") |
| 1363 | 1363 | |
| 1364 | 1364 | #endif // wxUSE_XPM
|
| 1365 | 1365 | |
| 1366 | +#if wxUSE_IFF
|
|
| 1367 | + |
|
| 1368 | +TEST_CASE_METHOD(ImageHandlersInit, "wxImage::BadIFF", "[image][iff][error]")
|
|
| 1369 | +{
|
|
| 1370 | + // A FORM/ILBM file whose BMHD transparent-colour field is 0x4000 while
|
|
| 1371 | + // the palette only has 2 entries (1 bitplane and no CMAP chunk). The
|
|
| 1372 | + // transparent index used to be applied to the palette without a bounds
|
|
| 1373 | + // check, writing past the end of the palette buffer; loading such a file
|
|
| 1374 | + // must now be rejected.
|
|
| 1375 | + static const unsigned char data[] =
|
|
| 1376 | + {
|
|
| 1377 | + 0x46,0x4f,0x52,0x4d,0x00,0x00,0x00,0x2e,
|
|
| 1378 | + 0x49,0x4c,0x42,0x4d,0x42,0x4d,0x48,0x44,
|
|
| 1379 | + 0x00,0x00,0x00,0x14,0x00,0x01,0x00,0x01,
|
|
| 1380 | + 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
|
|
| 1381 | + 0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
|
|
| 1382 | + 0x42,0x4f,0x44,0x59,0x00,0x00,0x00,0x02,
|
|
| 1383 | + 0x00,0x00,
|
|
| 1384 | + };
|
|
| 1385 | + wxMemoryInputStream mis(data, WXSIZEOF(data));
|
|
| 1386 | + wxImage img;
|
|
| 1387 | + REQUIRE( !img.LoadFile(mis, wxBITMAP_TYPE_IFF) );
|
|
| 1388 | +}
|
|
| 1389 | + |
|
| 1390 | +#endif // wxUSE_IFF
|
|
| 1391 | + |
|
| 1366 | 1392 | TEST_CASE_METHOD(ImageHandlersInit, "wxImage::DibPadding", "[image]")
|
| 1367 | 1393 | {
|
| 1368 | 1394 | /*
|
| ... | ... | @@ -165,6 +165,7 @@ TEST_GUI_OBJECTS = \ |
| 165 | 165 | $(OBJS)\test_gui_boundingbox.o \
|
| 166 | 166 | $(OBJS)\test_gui_clipper.o \
|
| 167 | 167 | $(OBJS)\test_gui_clippingbox.o \
|
| 168 | + $(OBJS)\test_gui_svgattributes.o \
|
|
| 168 | 169 | $(OBJS)\test_gui_coords.o \
|
| 169 | 170 | $(OBJS)\test_gui_graphbitmap.o \
|
| 170 | 171 | $(OBJS)\test_gui_graphmatrix.o \
|
| ... | ... | @@ -945,6 +946,9 @@ $(OBJS)\test_gui_clipper.o: ./graphics/clipper.cpp |
| 945 | 946 | $(OBJS)\test_gui_clippingbox.o: ./graphics/clippingbox.cpp
|
| 946 | 947 | $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
|
| 947 | 948 | |
| 949 | +$(OBJS)\test_gui_svgattributes.o: ./graphics/svgattributes.cpp
|
|
| 950 | + $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
|
|
| 951 | + |
|
| 948 | 952 | $(OBJS)\test_gui_coords.o: ./graphics/coords.cpp
|
| 949 | 953 | $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
|
| 950 | 954 |
| ... | ... | @@ -180,6 +180,7 @@ TEST_GUI_OBJECTS = \ |
| 180 | 180 | $(OBJS)\test_gui_boundingbox.obj \
|
| 181 | 181 | $(OBJS)\test_gui_clipper.obj \
|
| 182 | 182 | $(OBJS)\test_gui_clippingbox.obj \
|
| 183 | + $(OBJS)\test_gui_svgattributes.obj \
|
|
| 183 | 184 | $(OBJS)\test_gui_coords.obj \
|
| 184 | 185 | $(OBJS)\test_gui_graphbitmap.obj \
|
| 185 | 186 | $(OBJS)\test_gui_graphmatrix.obj \
|
| ... | ... | @@ -1252,6 +1253,9 @@ $(OBJS)\test_gui_clipper.obj: .\graphics\clipper.cpp |
| 1252 | 1253 | $(OBJS)\test_gui_clippingbox.obj: .\graphics\clippingbox.cpp
|
| 1253 | 1254 | $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\graphics\clippingbox.cpp
|
| 1254 | 1255 | |
| 1256 | +$(OBJS)\test_gui_svgattributes.obj: .\graphics\svgattributes.cpp
|
|
| 1257 | + $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\graphics\svgattributes.cpp
|
|
| 1258 | + |
|
| 1255 | 1259 | $(OBJS)\test_gui_coords.obj: .\graphics\coords.cpp
|
| 1256 | 1260 | $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\graphics\coords.cpp
|
| 1257 | 1261 |
| ... | ... | @@ -202,6 +202,7 @@ |
| 202 | 202 | graphics/boundingbox.cpp
|
| 203 | 203 | graphics/clipper.cpp
|
| 204 | 204 | graphics/clippingbox.cpp
|
| 205 | + graphics/svgattributes.cpp
|
|
| 205 | 206 | graphics/coords.cpp
|
| 206 | 207 | graphics/graphbitmap.cpp
|
| 207 | 208 | graphics/graphmatrix.cpp
|
| ... | ... | @@ -1001,6 +1001,7 @@ |
| 1001 | 1001 | <ClCompile Include="graphics\boundingbox.cpp" />
|
| 1002 | 1002 | <ClCompile Include="graphics\clipper.cpp" />
|
| 1003 | 1003 | <ClCompile Include="graphics\clippingbox.cpp" />
|
| 1004 | + <ClCompile Include="graphics\svgattributes.cpp" />
|
|
| 1004 | 1005 | <ClCompile Include="graphics\coords.cpp" />
|
| 1005 | 1006 | <ClCompile Include="graphics\graphbitmap.cpp" />
|
| 1006 | 1007 | <ClCompile Include="graphics\graphmatrix.cpp" />
|
| ... | ... | @@ -311,6 +311,9 @@ |
| 311 | 311 | <ClCompile Include="graphics\clippingbox.cpp">
|
| 312 | 312 | <Filter>Source Files</Filter>
|
| 313 | 313 | </ClCompile>
|
| 314 | + <ClCompile Include="graphics\svgattributes.cpp">
|
|
| 315 | + <Filter>Source Files</Filter>
|
|
| 316 | + </ClCompile>
|
|
| 314 | 317 | <ClCompile Include="graphics\coords.cpp">
|
| 315 | 318 | <Filter>Source Files</Filter>
|
| 316 | 319 | </ClCompile>
|
—
View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help