mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-10 08:12:39 +00:00
UI, http with gzip, etc.
This commit is contained in:
parent
3b9750ee49
commit
a509d38357
@ -16,6 +16,7 @@ LOCAL_SRC_FILES :=\
|
||||
base/colorutil.cpp \
|
||||
base/error_context.cpp \
|
||||
base/stringutil.cpp \
|
||||
data/compression.cpp \
|
||||
ext/rg_etc1/rg_etc1.cpp \
|
||||
ext/cityhash/city.cpp \
|
||||
ext/sha1/sha1.cpp \
|
||||
@ -32,6 +33,7 @@ LOCAL_SRC_FILES :=\
|
||||
file/zip_read.cpp \
|
||||
json/json_writer.cpp \
|
||||
i18n/i18n.cpp \
|
||||
input/gesture_detector.cpp \
|
||||
math/math_util.cpp \
|
||||
math/curves.cpp \
|
||||
math/lin/aabb.cpp.arm \
|
||||
|
@ -263,8 +263,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN
|
||||
lock_guard guard(input_state.lock);
|
||||
input_state.pad_lstick_x = left_joystick_x_async;
|
||||
input_state.pad_lstick_y = left_joystick_y_async;
|
||||
NativeUpdate(input_state);
|
||||
}
|
||||
NativeUpdate(input_state);
|
||||
|
||||
{
|
||||
lock_guard guard(input_state.lock);
|
||||
@ -319,17 +319,14 @@ extern "C" jint Java_com_henrikrydgard_libnative_NativeApp_audioRender(JNIEnv* e
|
||||
|
||||
extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch
|
||||
(JNIEnv *, jclass, float x, float y, int code, int pointerId) {
|
||||
ELOG("Touch Enter %i", pointerId);
|
||||
lock_guard guard(input_state.lock);
|
||||
|
||||
if (pointerId >= MAX_POINTERS) {
|
||||
ELOG("Too many pointers: %i", pointerId);
|
||||
return; // We ignore 8+ pointers entirely.
|
||||
}
|
||||
float scaledX = (int)(x * dp_xscale); // why the (int) cast?
|
||||
float scaledY = (int)(y * dp_yscale);
|
||||
input_state.pointer_x[pointerId] = scaledX;
|
||||
input_state.pointer_y[pointerId] = scaledY;
|
||||
|
||||
TouchInput touch;
|
||||
touch.id = pointerId;
|
||||
touch.x = scaledX;
|
||||
touch.y = scaledY;
|
||||
if (code == 1) {
|
||||
@ -341,8 +338,16 @@ extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch
|
||||
} else {
|
||||
touch.flags = TOUCH_MOVE;
|
||||
}
|
||||
NativeTouch(touch);
|
||||
|
||||
if (pointerId >= MAX_POINTERS) {
|
||||
ELOG("Too many pointers: %i", pointerId);
|
||||
return; // We ignore 8+ pointers entirely.
|
||||
}
|
||||
input_state.pointer_x[pointerId] = scaledX;
|
||||
input_state.pointer_y[pointerId] = scaledY;
|
||||
input_state.mouse_valid = true;
|
||||
NativeTouch(touch);
|
||||
ELOG("Touch Exit %i", pointerId);
|
||||
}
|
||||
|
||||
static void AsyncDown(int padbutton) {
|
||||
|
@ -46,8 +46,10 @@ void Buffer::AppendValue(int value) {
|
||||
void Buffer::Take(size_t length, std::string *dest) {
|
||||
CHECK_LE(length, data_.size());
|
||||
dest->resize(length);
|
||||
memcpy(&(*dest)[0], &data_[0], length);
|
||||
data_.erase(data_.begin(), data_.begin() + length);
|
||||
if (length > 0) {
|
||||
memcpy(&(*dest)[0], &data_[0], length);
|
||||
data_.erase(data_.begin(), data_.begin() + length);
|
||||
}
|
||||
}
|
||||
|
||||
int Buffer::TakeLineCRLF(std::string *dest) {
|
||||
|
@ -63,10 +63,14 @@ public:
|
||||
// Other simple string utilities.
|
||||
|
||||
inline bool startsWith(const std::string &str, const std::string &what) {
|
||||
if (str.size() < what.size())
|
||||
return false;
|
||||
return str.substr(0, what.size()) == what;
|
||||
}
|
||||
|
||||
inline bool endsWith(const std::string &str, const std::string &what) {
|
||||
if (str.size() < what.size())
|
||||
return false;
|
||||
return str.substr(str.size() - what.size()) == what;
|
||||
}
|
||||
|
||||
|
103
data/compression.cpp
Normal file
103
data/compression.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
// Little utility functions for data compression.
|
||||
// Taken from http://panthema.net/2007/0328-ZLibString.html
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
/** Compress a STL string using zlib with given compression level and return
|
||||
* the binary data. */
|
||||
bool compress_string(const std::string& str, std::string *dest, int compressionlevel) {
|
||||
z_stream zs; // z_stream is zlib's control structure
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
if (deflateInit(&zs, compressionlevel) != Z_OK) {
|
||||
ELOG("deflateInit failed while compressing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
zs.next_in = (Bytef*)str.data();
|
||||
zs.avail_in = str.size(); // set the z_stream's input
|
||||
|
||||
int ret;
|
||||
char outbuffer[32768];
|
||||
std::string outstring;
|
||||
|
||||
// retrieve the compressed bytes blockwise
|
||||
do {
|
||||
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
|
||||
zs.avail_out = sizeof(outbuffer);
|
||||
|
||||
ret = deflate(&zs, Z_FINISH);
|
||||
|
||||
if (outstring.size() < zs.total_out) {
|
||||
// append the block to the output string
|
||||
outstring.append(outbuffer,
|
||||
zs.total_out - outstring.size());
|
||||
}
|
||||
} while (ret == Z_OK);
|
||||
|
||||
deflateEnd(&zs);
|
||||
|
||||
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
|
||||
std::ostringstream oss;
|
||||
oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
|
||||
return false;
|
||||
}
|
||||
|
||||
*dest = outstring;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Decompress an STL string using zlib and return the original data. */
|
||||
bool decompress_string(const std::string& str, std::string *dest) {
|
||||
if (!str.size())
|
||||
return false;
|
||||
|
||||
z_stream zs; // z_stream is zlib's control structure
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
// modification by hrydgard: inflateInit2, 16+MAXWBITS makes it read gzip data too
|
||||
if (inflateInit2(&zs, 32+MAX_WBITS) != Z_OK) {
|
||||
ELOG("inflateInit failed while decompressing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
zs.next_in = (Bytef*)str.data();
|
||||
zs.avail_in = str.size();
|
||||
|
||||
int ret;
|
||||
char outbuffer[32768];
|
||||
std::string outstring;
|
||||
|
||||
// get the decompressed bytes blockwise using repeated calls to inflate
|
||||
do {
|
||||
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
|
||||
zs.avail_out = sizeof(outbuffer);
|
||||
|
||||
ret = inflate(&zs, 0);
|
||||
|
||||
if (outstring.size() < zs.total_out) {
|
||||
outstring.append(outbuffer,
|
||||
zs.total_out - outstring.size());
|
||||
}
|
||||
|
||||
} while (ret == Z_OK);
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
|
||||
std::ostringstream oss;
|
||||
ELOG("Exception during zlib decompression: (%i) %s", ret, zs.msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
*dest = outstring;
|
||||
}
|
@ -1,5 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
bool compress_string(const std::string& str, std::string *dest, int compressionlevel = Z_BEST_COMPRESSION);
|
||||
bool decompress_string(const std::string& str, std::string *dest);
|
||||
|
||||
|
||||
// Delta encoding/decoding - many formats benefit from a pass of this before zlibbing.
|
||||
// WARNING : Do not use these with floating point data, especially not float16...
|
||||
|
@ -189,6 +189,7 @@
|
||||
<ClInclude Include="base\stats.h" />
|
||||
<ClInclude Include="base\stringutil.h" />
|
||||
<ClInclude Include="base\timeutil.h" />
|
||||
<ClInclude Include="data\compression.h" />
|
||||
<ClInclude Include="data\listable.h" />
|
||||
<ClInclude Include="ext\cityhash\city.h" />
|
||||
<ClInclude Include="ext\cityhash\citycrc.h" />
|
||||
@ -223,7 +224,6 @@
|
||||
<ClInclude Include="input\gesture_detector.h" />
|
||||
<ClInclude Include="input\input_state.h" />
|
||||
<ClInclude Include="json\json_writer.h" />
|
||||
<ClInclude Include="math\compression.h" />
|
||||
<ClInclude Include="math\curves.h" />
|
||||
<ClInclude Include="math\geom2d.h" />
|
||||
<ClInclude Include="math\lin\aabb.h" />
|
||||
@ -293,6 +293,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="base\stringutil.cpp" />
|
||||
<ClCompile Include="base\timeutil.cpp" />
|
||||
<ClCompile Include="data\compression.cpp" />
|
||||
<ClCompile Include="ext\cityhash\city.cpp">
|
||||
<InlineFunctionExpansion Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AnySuitable</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IntrinsicFunctions>
|
||||
|
@ -131,9 +131,6 @@
|
||||
<ClInclude Include="file\file_util.h">
|
||||
<Filter>file</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="math\compression.h">
|
||||
<Filter>math</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gfx_es2\vertex_format.h">
|
||||
<Filter>gfx</Filter>
|
||||
</ClInclude>
|
||||
@ -272,6 +269,9 @@
|
||||
<ClInclude Include="ui\ui_screen.h">
|
||||
<Filter>ui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="data\compression.h">
|
||||
<Filter>data</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="gfx\gl_debug_log.cpp">
|
||||
@ -480,6 +480,9 @@
|
||||
<ClCompile Include="ui\ui_screen.cpp">
|
||||
<Filter>ui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="data\compression.cpp">
|
||||
<Filter>data</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="gfx">
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/buffer.h"
|
||||
#include "base/stringutil.h"
|
||||
#include "data/compression.h"
|
||||
#include "net/resolve.h"
|
||||
#include "net/url.h"
|
||||
|
||||
@ -84,8 +85,6 @@ void Connection::Disconnect() {
|
||||
if ((intptr_t)sock_ != -1) {
|
||||
closesocket(sock_);
|
||||
sock_ = -1;
|
||||
} else {
|
||||
WLOG("Socket was already disconnected.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,38 +98,103 @@ void Connection::Reconnect() {
|
||||
namespace http {
|
||||
|
||||
Client::Client() {
|
||||
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
#define USERAGENT "METAGET 1.0"
|
||||
// TODO: do something sane here
|
||||
#define USERAGENT "NATIVEAPP 1.0"
|
||||
|
||||
|
||||
void DeChunk(Buffer *inbuffer, Buffer *outbuffer) {
|
||||
while (true) {
|
||||
std::string line;
|
||||
inbuffer->TakeLineCRLF(&line);
|
||||
if (!line.size())
|
||||
return;
|
||||
int chunkSize;
|
||||
sscanf(line.c_str(), "%x", &chunkSize);
|
||||
if (chunkSize) {
|
||||
std::string data;
|
||||
inbuffer->Take(chunkSize, &data);
|
||||
outbuffer->Append(data);
|
||||
} else {
|
||||
// a zero size chunk should mean the end.
|
||||
inbuffer->clear();
|
||||
return;
|
||||
}
|
||||
inbuffer->Skip(2);
|
||||
}
|
||||
}
|
||||
|
||||
int Client::GET(const char *resource, Buffer *output) {
|
||||
Buffer buffer;
|
||||
const char *tpl = "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " USERAGENT "\r\n\r\n";
|
||||
const char *tpl =
|
||||
"GET %s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"User-Agent: " USERAGENT "\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Accept-Encoding: gzip\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n";
|
||||
|
||||
buffer.Printf(tpl, resource, host_.c_str());
|
||||
bool flushed = buffer.FlushSocket(sock());
|
||||
if (!flushed) {
|
||||
return -1; // TODO error code.
|
||||
}
|
||||
|
||||
// Snarf all the data we can.
|
||||
if (!output->ReadAll(sock()))
|
||||
Buffer readbuf;
|
||||
|
||||
// Snarf all the data we can into RAM. A little unsafe but hey.
|
||||
if (!readbuf.ReadAll(sock()))
|
||||
return -1;
|
||||
|
||||
// Grab the first header line that contains the http code.
|
||||
|
||||
// Skip the header. TODO: read HTTP code and file size so we can make progress bars.
|
||||
|
||||
std::string firstline;
|
||||
CHECK_GT(output->TakeLineCRLF(&firstline), 0);
|
||||
int code = atoi(&firstline[9]);
|
||||
std::string line;
|
||||
CHECK_GT(readbuf.TakeLineCRLF(&line), 0);
|
||||
int code = atoi(&line[line.find(" ") + 1]);
|
||||
|
||||
while (output->SkipLineCRLF() > 0)
|
||||
;
|
||||
bool gzip = false;
|
||||
int contentLength = 0;
|
||||
while (true) {
|
||||
int sz = readbuf.TakeLineCRLF(&line);
|
||||
if (!sz)
|
||||
break;
|
||||
if (startsWith(line, "Content-Length:")) {
|
||||
contentLength = atoi(&line[16]);
|
||||
} else if (startsWith(line, "Content-Encoding:")) {
|
||||
if (line.find("gzip") != std::string::npos) {
|
||||
gzip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// output now contains the rest of the reply. Dechunk it.
|
||||
DeChunk(&readbuf, output);
|
||||
|
||||
// If it's gzipped, we decompress it and put it back in the buffer.
|
||||
if (gzip) {
|
||||
std::string compressed;
|
||||
output->TakeAll(&compressed);
|
||||
// What is this garbage?
|
||||
//if (compressed[0] == 0x8e)
|
||||
// compressed = compressed.substr(4);
|
||||
std::string decompressed;
|
||||
bool result = decompress_string(compressed, &decompressed);
|
||||
if (!result) {
|
||||
ELOG("Error decompressing using zlib");
|
||||
return -1;
|
||||
}
|
||||
output->Append(decompressed);
|
||||
}
|
||||
|
||||
// output now contains the rest of the reply.
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -86,10 +86,11 @@ void UIContext::PopScissor() {
|
||||
void UIContext::ActivateTopScissor() {
|
||||
if (scissorStack_.size()) {
|
||||
const Bounds &bounds = scissorStack_.back();
|
||||
int x = g_dpi_scale * bounds.x;
|
||||
int y = g_dpi_scale * (dp_yres - bounds.y2());
|
||||
int w = g_dpi_scale * bounds.w;
|
||||
int h = g_dpi_scale * bounds.h;
|
||||
float scale = 1.0f / g_dpi_scale;
|
||||
int x = scale * bounds.x;
|
||||
int y = scale * (dp_yres - bounds.y2());
|
||||
int w = scale * bounds.w;
|
||||
int h = scale * bounds.h;
|
||||
|
||||
glstate.scissorRect.set(x,y,w,h);
|
||||
glstate.scissorTest.enable();
|
||||
|
@ -109,7 +109,7 @@ private:
|
||||
class LinearLayout : public ViewGroup {
|
||||
public:
|
||||
LinearLayout(Orientation orientation, LayoutParams *layoutParams = 0)
|
||||
: ViewGroup(layoutParams), spacing_(5), orientation_(orientation), defaultMargins_(0) {}
|
||||
: ViewGroup(layoutParams), orientation_(orientation), defaultMargins_(0), spacing_(10) {}
|
||||
|
||||
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
|
||||
void Layout();
|
||||
@ -153,7 +153,13 @@ private:
|
||||
class ScrollView : public ViewGroup {
|
||||
public:
|
||||
ScrollView(Orientation orientation, LayoutParams *layoutParams = 0) :
|
||||
ViewGroup(layoutParams), orientation_(orientation), scrollPos_(0), scrollTarget_(0), scrollToTarget_(false) {}
|
||||
ViewGroup(layoutParams),
|
||||
orientation_(orientation),
|
||||
scrollPos_(0),
|
||||
scrollStart_(0),
|
||||
scrollMax_(0),
|
||||
scrollTarget_(0),
|
||||
scrollToTarget_(false) {}
|
||||
|
||||
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
|
||||
void Layout();
|
||||
|
Loading…
x
Reference in New Issue
Block a user