# RamHTML **Repository Path**: rxlib/ram-html ## Basic Information - **Project Name**: RamHTML - **Description**: RamHTML 是一个纯 C++17 编写的 CSS3.0 解析库和轻量级浏览器引擎,**无需任何外部依赖**。它不仅提供完整的 CSS 解析功能,还包含布局引擎和渲染引擎,能够将 HTML 页面渲染到图片文件中。 - **Primary Language**: C++ - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-14 - **Last Updated**: 2026-04-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RamHTML **Pure C++17 CSS3.0 Parser & Browser Engine / 纯 C++17 CSS3.0 解析器与浏览器引擎** ``` License: Apache-2.0 Language: C++17 Dependencies: None (pure standard library) / 无外部依赖(纯标准库实现) Platforms: Windows / Linux / macOS Optional: RamX HTML DOM Parser ``` --- ## 项目简介 RamHTML 是一个纯 C++17 编写的 CSS3.0 解析库和轻量级浏览器引擎,**无需任何外部依赖**。它不仅提供完整的 CSS 解析功能,还包含布局引擎和渲染引擎,能够将 HTML 页面渲染到图片文件中。 ### 核心功能 - **CSS 解析器** - 完整支持 CSS1、CSS2.1 和 CSS3 选择器与属性 - **选择器引擎** - 完整的选择器解析、匹配与优先级计算 - **属性值解析** - 支持颜色、长度单位、URL 等类型化值解析 - **样式表管理** - 完整样式表解析,处理 @import,按优先级排序选择器 - **媒体查询** - 完整 CSS3 媒体查询支持 - **布局引擎** - 支持块级、内联和 Flex 布局 - **渲染引擎** - 生成显示列表,支持基本绘制命令 - **BrowserEngine** - 集成 HTML 解析、布局和渲染,支持 GDI+ 渲染到图片 --- ## 目录结构 ``` RamHTML/ ├── include/ # 头文件 │ ├── css/ # CSS 相关头文件 │ ├── dom/ # DOM 相关头文件 │ ├── html/ # HTML 相关头文件 │ ├── layout/ # 布局引擎头文件 │ ├── loader/ # 资源加载器头文件 │ ├── render/ # 渲染引擎头文件 │ └── ramx.h # RamX 集成头文件 ├── src/ # 源代码 ├── CMakeLists.txt # CMake 构建配置 └── LICENSE # Apache License 2.0 ``` --- ## 编译指南 ### 环境要求 - C++17 编译器 (GCC 9+ / Clang 10+ / MSVC 2019+) - CMake 3.14+ ### 编译步骤 ```bash # 1. 创建并进入 build 目录 mkdir build && cd build # 2. 配置 CMake cmake .. -DCMAKE_BUILD_TYPE=Release # 3. 编译项目 cmake --build . --config Release # 4. 验证编译结果 ls -la Release/ ``` --- ## 快速开始 ### 引入头文件 ```cpp #include "css/ramcss.h" #include "render/browser_engine.h" ``` ### 基本用法 ```cpp #include "css/ramcss.h" #include int main() { // 解析 CSS auto sheet = CSSParser::parse(R"( div { color: red; font-size: 16px; } .container { width: 100%; background: #f0f0f0; } #header { display: flex; justify-content: center; } )"); std::cout << "解析了 " << sheet->rules().size() << " 条规则" << std::endl; return 0; } ``` --- ## 功能详解与示例 ### 1. CSS 选择器解析 **功能说明**:解析各种 CSS 选择器,支持类型、ID、类、属性、伪类等选择器。 **使用示例**: ```cpp #include "css/selector.h" // 解析选择器 auto sel1 = CSSSelector::parse("div.container#main[data-id]"); auto sel2 = CSSSelector::parse("body > div.nav + ul li"); auto sel3 = CSSSelector::parse("[href^='https']:hover::after"); // 计算优先级 // #main -> (1,0,0) ID // .container -> (0,1,0) 类 // div -> (0,0,1) 元素 // div#main -> (1,0,1) ID + 元素 std::cout << "Selector specificity: " << sel1->specificity() << std::endl; ``` ### 2. CSS 属性值解析 **功能说明**:解析各种 CSS 属性值,包括颜色、长度单位、URL 等。 **使用示例**: ```cpp #include "css/color.h" #include "css/value.h" // 解析颜色 auto c1 = CSSColorUtil::parse("#ff0000"); // hex auto c2 = CSSColorUtil::parse("rgb(0, 255, 0)"); // rgb auto c3 = CSSColorUtil::parse("rgba(0,0,255,0.5)"); // rgba auto c4 = CSSColorUtil::parse("hsl(120,100%,50%)"); // hsl auto c5 = CSSColorUtil::parse("cornflowerblue"); // 命名色 // 解析长度 auto l1 = CSSUtil::parseLength("100px"); auto l2 = CSSUtil::parseLength("1.5em"); auto l3 = CSSUtil::parseLength("50%"); auto l4 = CSSUtil::parseLength("2rem"); // 解析为像素值 float px = l1->resolve(16.0f, 16.0f); // 基础字体大小, 根字体大小 ``` ### 3. 样式表解析 **功能说明**:解析完整的 CSS 样式表,处理 @import,按优先级排序选择器。 **使用示例**: ```cpp #include "css/parser.h" const char* css = R"( /* Reset */ * { margin: 0; padding: 0; } body { font-family: Arial, sans-serif; font-size: 16px; color: #333; } #header { width: 100%; height: 60px; background-color: hsl(211, 100%, 50%); display: flex; flex-direction: row; justify-content: space-between; } .nav-item { color: rgba(255,255,255,0.8); font-size: 14px; } button.primary:hover { opacity: 0.9; } )"; auto sheet = CSSParser::parse(css); std::cout << "解析了 " << sheet->rules().size() << " 条规则" << std::endl; // 规则按优先级自动排序 ``` ### 4. 媒体查询 **功能说明**:解析和匹配 CSS 媒体查询,支持各种媒体特性。 **使用示例**: ```cpp #include "css/media.h" // 解析媒体查询 auto mql = CSSMediaQueryList::parse("screen and (min-width: 768px)"); // 检查是否匹配环境 bool matches = mql->matches( /* viewportWidth */ 1920, /* viewportHeight */ 1080, /* deviceWidth */ 1920, /* deviceHeight */ 1080, /* color */ true, /* colorIndex */ 8, /* monochrome */ 0 ); std::cout << "Media query matches: " << (matches ? "yes" : "no") << std::endl; // 媒体类型: screen, print, speech, all ``` ### 5. 布局引擎 **功能说明**:构建布局树,计算元素位置和大小,支持块级、内联和 Flex 布局。 **使用示例**: ```cpp #include "layout/layout_engine.h" // 创建布局引擎 auto layoutEngine = std::make_unique(); // 构建布局树(假设已有 DOM 节点) auto domRoot = /* 从 HTML 解析器获取 */; auto layoutRoot = layoutEngine->buildLayoutTree(domRoot); // 计算布局 layoutEngine->calculateLayout(layoutRoot, 800); // 视口宽度 800px // 访问布局结果 std::cout << "Root width: " << layoutRoot->dims.width << std::endl; std::cout << "Root height: " << layoutRoot->dims.height << std::endl; ``` ### 6. 渲染引擎 **功能说明**:从布局树构建渲染树,生成显示列表,支持基本绘制命令。 **使用示例**: ```cpp #include "render/render_engine.h" // 创建渲染树 RenderTree tree; tree.setViewport(800, 600); // 从布局树构建渲染树 auto layoutRoot = /* 从布局引擎获取 */; tree.buildFromLayout(layoutRoot); // 计算位置 tree.calculatePositions(800); // 生成显示列表 DisplayList displayList = tree.paint(); // 显示列表包含绘制命令 std::cout << "Display list size: " << displayList.size() << std::endl; ``` ### 7. BrowserEngine 渲染到图片 **功能说明**:集成 HTML 解析、布局和渲染,使用 GDI+ 将页面渲染到图片文件。 **使用示例**: ```cpp #include "render/browser_engine.h" #include "html/parser.h" // 创建 BrowserEngine auto browserEngine = std::make_shared(); // 设置视口大小 browserEngine->setViewport(800, 600); // 加载 HTML 内容 std::string htmlContent = R"(

RamHTML Test

)"; // 解析 HTML auto domRoot = parseHtml(htmlContent); // 构建布局树 auto layoutRoot = browserEngine->buildLayoutTree(domRoot); // 生成显示列表 auto displayList = browserEngine->generateDisplayList(layoutRoot); // 使用 GDI+ 渲染到图片(完整实现见下文) // renderToImage(displayList, "output.png"); ``` ### 8. GDI+ 渲染实现 **功能说明**:使用 GDI+ 在不依赖 Win32 API 的情况下,将 HTML 页面渲染到图片文件。 **使用示例**: ```cpp #include #include using namespace Gdiplus; // 初始化 GDI+ GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // 执行绘制命令 void executeDrawCommand(const DrawCommand& cmd, Graphics& graphics) { switch (cmd.type) { case DrawCommandType::RECT: { // 创建画刷 SolidBrush brush(Color(255, 0, 0, 0)); // 默认黑色 // 解析颜色 if (!cmd.color.empty()) { // 简单颜色解析,实际项目中应使用 CSSColorUtil if (cmd.color == "red") { brush.SetColor(Color(255, 255, 0, 0)); } else if (cmd.color == "blue") { brush.SetColor(Color(255, 0, 0, 255)); } // 更多颜色处理... } // 绘制矩形 graphics.FillRectangle(&brush, cmd.rect.x, cmd.rect.y, cmd.rect.width, cmd.rect.height); break; } case DrawCommandType::TEXT: { // 创建字体和画刷 Font font(L"Arial", 12); SolidBrush brush(Color(255, 0, 0, 0)); // 黑色文字 // 绘制文本 graphics.DrawString( std::wstring(cmd.text.begin(), cmd.text.end()).c_str(), -1, &font, PointF(cmd.rect.x, cmd.rect.y), &brush); break; } // 更多绘制命令... } } // 渲染到图片 void renderToImage(const DisplayList& displayList, const std::wstring& filename) { // 创建图片 int width = 800; int height = 600; Bitmap bitmap(width, height, PixelFormat32bppARGB); Graphics graphics(&bitmap); // 填充背景 SolidBrush backgroundBrush(Color(255, 240, 240, 240)); graphics.FillRectangle(&backgroundBrush, 0, 0, width, height); // 执行绘制命令 for (const auto& cmd : displayList) { executeDrawCommand(cmd, graphics); } // 保存图片 CLSID pngClsid; GetEncoderClsid(L"image/png", &pngClsid); bitmap.Save(filename.c_str(), &pngClsid, NULL); } // 辅助函数:获取编码器 CLSID int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { UINT num = 0; UINT size = 0; ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&num, &size); if (size == 0) return -1; pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if (pImageCodecInfo == NULL) return -1; GetImageEncoders(num, size, pImageCodecInfo); for (UINT j = 0; j < num; ++j) { if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) { *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; } } free(pImageCodecInfo); return -1; } // 使用示例 int main() { // 初始化 GDI+ GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); try { // 创建 BrowserEngine 并生成显示列表 // ... 前面的代码 ... // 渲染到图片 renderToImage(displayList, L"render_test.png"); std::cout << "渲染完成,输出保存到 render_test.png" << std::endl; } catch (const std::exception& e) { std::cerr << "错误: " << e.what() << std::endl; } // 清理 GDI+ GdiplusShutdown(gdiplusToken); return 0; } ``` --- ## 作为库使用 在你的 `CMakeLists.txt` 中: ```cmake add_subdirectory(path/to/RamHTML) target_link_libraries(your_target PRIVATE ramcss) # 如果使用 GDI+ 渲染 if(WIN32) target_link_libraries(your_target PRIVATE gdiplus) endif() ``` --- ## 功能支持状态 | 功能 | 状态 | |------|------| | **选择器** | | | 类型、ID、类选择器 | ✅ 完整支持 | | 属性选择器 `[attr]`, `[attr=value]` | ✅ 完整支持 | | CSS4 属性操作符 `[^=]`, `[$=]`, `[*=]` | ✅ 完整支持 | | 组合器 `>`, `+`, `~`, `\|\|` | ✅ 完整支持 | | 伪类 `:hover`, `:focus`, `:first-child` | ✅ 完整支持 | | 结构伪类 `:nth-child(an+b)` | ✅ 完整支持 | | **属性** | | | 盒模型 (margin, padding, border) | ✅ 完整支持 | | Flexbox (`display:flex`, `flex-*`, `justify-*`) | ✅ 完整支持 | | 背景 (`background-color`, `background-image` 等) | ✅ 部分支持 | | 排版 (`font-*`, `text-*`, `color`, `opacity`) | ✅ 部分支持 | | **值** | | | 颜色 (hex, rgb, rgba, hsl, hsla, 命名色) | ✅ 完整支持 | | 长度单位 (px, em, rem, %, vw, vh, pt, pc, cm, mm, in) | ✅ 完整支持 | | URL 值 | ✅ 完整支持 | | CSS 全局关键字 (`inherit`, `initial`, `unset`) | ✅ 完整支持 | | **At-规则** | | | `@import` | ✅ 完整支持 | | `@media` | ✅ 完整支持 | | `@keyframes` | 🔜 计划中 | | `@font-face` | 🔜 计划中 | --- ## 技术特点 - **零依赖** - 仅使用 C++ 标准库,无外部依赖 - **跨平台** - 支持 Windows (MSVC)、Linux (GCC/Clang)、macOS (Clang) - **现代 C++ 设计** - 使用 `std::variant` 进行类型化值处理,智能指针,移动语义 - **140+ 命名颜色** - 完整 CSS4 命名色表 - **GDI+ 渲染** - 在 Windows 平台上支持渲染到图片文件 - **模块化设计** - 各组件可独立使用,也可集成使用 --- ## 测试示例 ### 测试目录结构 ``` RamHTML/test/ ├── render_page.cpp # 基本渲染测试 ├── render_flex_page.cpp # Flex 布局测试 ├── test_page.html # 测试页面 ├── flex_test.html # Flex 布局测试页面 ├── test_output.png # 渲染输出图片 └── flex_test_output.png # Flex 布局渲染输出图片 ``` ### 测试页面示例 **test_page.html** 是一个测试页面,包含不同背景颜色的元素和 Flex 布局: ```html Background Color Test

Background Color Test

This page tests different background colors for various elements...

Left Section

This section has a red background...

Sub-box with orange background...

Right Section

This section has a green background...

Sub-box with orange background...

``` ### 渲染测试结果 #### 基本渲染测试 **test_output.png** - 基本测试页面的渲染结果: ![Basic Render Test](test/test_output.png) #### Flex 布局测试 **flex_test_output.png** - Flex 布局测试页面的渲染结果: ![Flex Render Test](test/flex_test_output.png) ### 运行测试 1. **编译测试程序**: ```bash # 在 build 目录中 cmake --build . --config Release --target render_page cmake --build . --config Release --target render_flex_page ``` 2. **运行测试**: ```bash # 基本渲染测试 cd test ../build/Release/render_page.exe # Flex 布局测试 ../build/Release/render_flex_page.exe ``` 测试程序会读取 HTML 文件,渲染页面,并生成对应的 PNG 图片文件。 --- ## 示例应用场景 1. **嵌入式浏览器** - 在应用程序中嵌入轻量级浏览器功能 2. **HTML 转图片** - 将 HTML 页面转换为图片文件 3. **CSS 解析工具** - 开发 CSS 分析和处理工具 4. **布局引擎** - 为自定义 UI 框架提供布局功能 5. **教育和学习** - 学习浏览器内部工作原理 --- ## 许可证 ``` Copyright 2026 RamHTML Library. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ```